关于Java的=赋值操作和方法传递对象时的引用

  

原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11405920.html

 

  下面通过一段代码和debug结果来展示Java中=操作的赋值改变过程。Test实体类会在最后贴出。

        Test test1 = new Test();
        test1.setKey(1);
        test1.setValue(1);
        Test test4 = new Test();
        test4.setKey(4);
        test4.setValue(4);
        Test test2 = test1;
        test2.setIndex(2);
        test2 = test4;
        test2.setIndex(4);    

  

  结果:

 

  

 

  可以看出:Java的=操作符会将=右侧对象实例的地址引用赋值给=左侧的对象实例,在被赋值期间,值的改变是怎样的呢?

  继续看:  

 

  

  可以看到test1的index值是改变了的,test4的index值也是改变了的,test2首先是test1的引用,在引用test1的时候改变test2的值,test1的值也会相应改变,说明在引用期间所有的改变都是针对实际内存地址操作的,而不是单纯针对该对象的值进行改变。

  接下来,我们再看一下方法传递时候的引用是怎么改变的:

  先贴上两个传入test参数并且在方法内尝试改变index值的方法:

  

    /**
     * 尝试直接改变test的index值
     * @param test
     */
    public static void tryInChangeIndex(Test test){
        test.setIndex(123);
    }

    /**
     * 尝试间接改变test的index值
     * @param test
     */
    public static void tryLinkChangeIndex(Test test){
        Test testLink = new Test();
        testLink = test;
        testLink.setIndex(456);
    }

 

  结果:

 

  

  毫无疑问,成功改变test1的值。

  再看下一个方法:

  

  同样可以改变,没有问题。

  再看看String传递是怎么回事;

  先贴尝试改变String的两个方法:

 

    /**
     * 尝试改变string的值
     * @param str
     */
    public static void tryChangeString(String str){
        str = "hello new str value";
    }

    /**
     * 尝试改变string的值方法2
     * @param str
     */
    public static void tryChangeStringTwo(String str){
        String newStr = str;
        newStr = "world in this place";
    }
    String str1 = "good nice";
    String str2 = "i'm iron man";
    tryChangeString(str1);
    tryChangeStringTwo(str2);    

  debug结果:

   

  

  从这里可以看出,方法里面的str值是有改变的,但是方法外str1的值依然是“good nice”,这说明传入的String 类型是不能被改变的。

  继续看下面这个方法:

  

  同样的,在方法里面,虽然把str指向了newStr,并且给newStr赋了新的值,但是str的值依然是没有变化的,我们再看一下str2的值: 

  

  str2的值也是没有被改变。

  我猜测: 这是因为参数方法在参数列表这里的String str 重新创建了一个实例,而且将该实例的内存引用地址指向了str2的内存引用地址,所以值会相等,但是当对str进行赋值操作的时候,会重新new String,也就是重新开辟一块内存空间去存放这个新的值,并且str会指向这块内存地址,所以改变str的值是无法改变str2的值的,因为它俩根本就不是同一个实例,只是指向了相同的内存引用地址而已.

  *** String 是final类,不可被继承, 但是String如果实例化的时候没有定义为final变量,还是可以重新赋值的!编译器不会报错!注意区别 final类和final变量.

  再来看一种情况:

        TestFather father = new TestFather();
        Test son = new Test();
        son.setIndex(123456);
        father.setSon(son);
        son.setIndex(789);    

  这种情况下,father里面的son值会怎么变化?debug看一下

  

  到了72行,72行还没执行的之后,father的son的index值还是123456的,再往下走一步:

 

  BOOM!!! Every thing is diffrent   

 

  

  很明显,son变了,father拥有的只是son的一个引用,拥有了son的身体却没有son的灵魂,这里涉及到一个深拷贝和浅拷贝的问题,有兴趣可以自行Google或者Baidu。

  Test.java文件  

package entity;

/**
 * 测试实体类
 */
public class Test {
    private int key;
    private int value;
    private int index;

    //getter setter 省略        
}

  TestFather.java

 

package entity;

/**
 * Test的father
 */
public class TestFather {
    private int num;
    private Test son;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Test getSon() {
        return son;
    }

    public void setSon(Test son) {
        this.son = son;
    }
}

 

  结束🔚

 

posted @ 2019-08-24 20:19  前往幸福的路上  阅读(4729)  评论(0编辑  收藏  举报