Topic: 老手也来看看这个吧

  Print this page

1.老手也来看看这个吧 Copy to clipboard
Posted by: alin_ass
Posted on: 2004-04-06 23:03

不一定都搞的清楚哦呵呵

/*
* Created on 2004-4-6
* Coffee 2004 japp.org All rights reserved
*/
package org.japp.study.syntax;

/**
* @author <a href="mailto:wanglin@japp.org">wang lin</a>
*/
public class PassByValue {

  public void swapObj(Obj t) {
    System.out.println("swapObj(Obj t)=>  size: " + t.getSize() + ", name:" + t.getName());
    Obj t2 = new Obj();
    t2.setName("B");
    t2.setSize(100);
    t = t2;
    System.out.println("swapObj(Obj t)=>  size: " + t.getSize() + ", name:" + t.getName());
  }
  
  public void changeObj(Obj t) {
    t.setName("c");
    t.setSize(99);
  }
  public static void main(String[] args) {
    PassByValue pbv = new PassByValue();
    Obj obj = new Obj();
    pbv.swapObj(obj);
    System.out.println("main()=>  size: " + obj.getSize() + ", name:" + obj.getName());
    pbv.changeObj(obj);
    System.out.println("main()=>  size: " + obj.getSize() + ", name:" + obj.getName());
  }
}

class Obj {
  private String name = "A";
  private int size = 0;

  /**
   * @return
   */
  public String getName() {
    return name;
  }

  /**
   * @param name
   */
  public void setName(String name) {
    this.name = name;
  }

  /**
   * @return
   */
  public int getSize() {
    return size;
  }

  /**
   * @param i
   */
  public void setSize(int i) {
    size = i;
  }

}

-----------------------------------------------------------------------------
输出:
changeObj(Obj t)=>  size: 0, name:A
changeObj(Obj t)=>  size: 100, name:B
main()=>  size: 0, name:A
main()=>  size: 99, name:c

2.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: jigsaw
Posted on: 2004-04-07 09:20

我觉得就是两条原则:

1.所有的方法的参数都是本地变量,所以swap没有作用,无论参数是Object或者primitive;

2.但是调用参数的方法可以改变其状态。譬如change这样。还有个例子是可以直接改变数组的元素的值。

请指正

3.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: alin_ass
Posted on: 2004-04-07 10:29

你讲的观点是局部变量的作用域,很有道理,也很新颖

我的看法和大多数人一样,参考
http://forum.javaeye.com/viewtopic.php?t=4189里某网友观点:
Java里的传值实际上是拷贝引用,而不是拷贝对象。
所以不管引用怎么变,只要不调用引用的方法,对象的任何属性都不会变。

再来个小例子

/**
* @author <a href="mailto:wanglin@japp.org">wang lin</a>
*/
public class PassByValue2 {

  public static void main(String[] args) {
    String b = "hi";
    String a = "hello";
    a = b;
    b = "love";
    System.out.println("a: " + a);
  }
}

输出:
a: hi

a=b 中 a得到b引用(我觉得引用就是b这个实例在内存中的索引,a可以根据这个索引找到b的Class实例,属性,方法等等)
然后 b = "love";b得到了新的引用,所以此时a跟b是两个指向不同内存地址的引用

------------------------------------------------------------------------

4.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: bwpc
Posted on: 2004-04-07 10:42

我记得一本关于虚拟机的书上是这样说的:虚拟机装载字节码要进行四次检查,有一次就是引用检查,然后把所有引用替换成实际内存地址(指针),
我的理解是java不让程序员来使用指针,而使用引用,虚拟机帮着把引用转为指针,可以避免好多问题

有点记不太清楚,如果说错了请指正,我回去再查查书,呵呵

5.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: mochow
Posted on: 2004-04-07 10:50

关于这个我觉得那本Sun Certified Programmer & Developer for Java 2 Study Guide里面讲的很清楚。不管传值这些东西了,越说越胡涂。

就我自己的理解,简单的说:对象作为方法的参数传入方法中,方法只能改变这个对象的状态或者属性,不能给该对象的引用赋值,也就是不能把该对象的引用赋值为别的对象,就算你进行赋值操作,它也不承认。

6.Re:老手也来看看这个吧 [Re: mochow] Copy to clipboard
Posted by: Jove
Posted on: 2004-04-07 10:59

还有种理解是
void foo(<type> param){
..
}

调用时foo(paramValue);
把 param=paramValue;就这么简单

如果<type>是基本类型如int,则 param=paramValue=3;
如果是对象,则param=paramValue=obj;

7.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: alin_ass
Posted on: 2004-04-07 11:19

收回上个观点,同意jigsaw
该例子调用swap()方法新建堆栈,这个堆栈空间在方法结束时销毁,所以无法影响调用者堆栈.

继续关注

public class PassByValue2 {

  public static void main(String[] args) {
    String b = "hi";
    String a = "hello";
    a = b;
    b = "love";
    System.out.println("a: " + a);
  }
}

8.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: jigsaw
Posted on: 2004-04-07 11:42

err....这个例子不是很显然的吗?
在c里面不也是这样吗?

a,b都是一个容器

a=b; //b的内容倒入a
b="love"; //在b里面倒入"love"

呵呵 考虑问题的时候要简化问题 不要纠缠在字眼上(譬如by value or by refrence)

9.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: alin_ass
Posted on: 2004-04-07 13:05

曹队长的解释
http://forum.javaeye.com/viewtopic.php?t=4189&postdays=0&postorder=asc&start=15

首先要区分出变量和对象的不同。对象是保存在堆中的,而变量是保存在对象instance的这个方法对应的临时slot中的。(slot有点像一个临时的寄存器)。因为每个方法都有自己的临时栈帧,所以这些变量不会相互影响,唯一的例外就是在方法调用的时候,由invokexxx和xreturn执行堆栈的初始化和反向更改。

那么,a="hi",这句话会在堆中产生一个String对象,编译器会在当前执行方法的对象的临时slot中产生一个slot号,比如说是1,这个变量slot中会保存这个String对象在堆中的地址。

a=b,其实就是一次压栈和一次出栈。

每个对象在堆都有一个地址,假若a(假设被编译器指定为slot0)指向的String对象"hello"是125,b(slot1) 指向的String 对象"hi"是126,那么a=b就是:
aload_1;
astore_0;
把'126'压入堆栈,然后弹出到slot0中,最后结果是slot0和slot1中都是126。

最后一句b="love",又在堆中产生了一个String对象,假若它的地址是127,则slot0被赋予127。
最终结果是:
slot0 ( a ) = 126;
slot1 ( b ) = 127.

然后125这个对象因为不再被引用,于是将可能在下次垃圾收集的时候被销毁。

这么说明白了吗?

(察看字节码,请用javap命令行。好像是javap -c -verbose)

10.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: alin_ass
Posted on: 2004-04-07 13:09

jigsaw : 我是学生,容忍下我的好奇心呵呵

11.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: dorrenchen
Posted on: 2004-04-07 13:45

Becuase java pass object reference by value to methods, that's where the confusion is.

Relation of reference and object is like a key to a locked box. when you call a method with a key, a separate new key is passed to the method, inside the method, swapping, reassigning keys has no effects on original keys. After method finishes, original keys stay intact.

As code shown below, new key3 & 4 are created for swapObj method.

public class SwapTest {
  public static void swapObj(Obj key3, Obj key4) {
    Obj temp = key3;
    key3 = key4;
    key4 = temp;
  }

public static void main(String[] args) {
  Obj key1 = new Obj("A", 100);
  Obj key2 = new Obj("B", 200);
  SwapTest.swapObj(key1, key2);
  System.out.println("main()=> obj1: " + key1);
  System.out.println("main()=> obj2: " + key2);
}
}

class Obj {
  private String name;
  private int size;
    
  public Obj(String n, int s){
    name = n;
    size = s;
  }
  
  public String toString(){
    return name + " " + size;
  }
}

>> result
main()=> obj1: A 100
main()=> obj2: B 200

String is not suitable to illustrate this concept, since string is immutable.

google "java swap object" and you shall find this page
http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass_p.html

12.Re:老手也来看看这个吧 [Re: alin_ass] Copy to clipboard
Posted by: floater
Posted on: 2004-04-07 21:43

pass by copies of references.


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923