说说 Java 中的对象引用

Java 中的对象引用,一般出现在赋值与方法传递场景,下面分别予以说明。

1 赋值

赋值使用的是符号 = ,表示获取 = 右边的值赋给左边的变量。右边可以是任何常量、变量或者可产生一个返回值的表达式,但左边必须是一个明确的、已命名的变量。也就是说,可以是 x = 3,但不可以是 3 = x。

如果右边是基本类型,那么会直接赋值。比如 x = y,如果 y 是基本类型,那么赋值操作会将 y 的值复制一份给变量 x。

但如果是对象赋值,实际上是将右边的对象的引用赋给左边的对象。请看下例:

class Cup {
    String color;
}

public class Assignment {
    public static void main(String[] args) {
        Cup cup1 = new Cup();
        Cup cup2 = new Cup();
        cup1.color = "red";
        cup2.color = "yellow";
        System.out.println("1: cup1.color:" + cup1.color + ", cup2.color:" + cup2.color);

        cup1 = cup2;
        System.out.println("2: cup1.color:" + cup1.color + ", cup2.color:" + cup2.color);

        cup1.color = "black";
        System.out.println("3: cup1.color:" + cup1.color + ", cup2.color:" + cup2.color);

    }
}

运行结果:

1: cup1.color:red, cup2.color:yellow
2: cup1.color:yellow, cup2.color:yellow
3: cup1.color:black, cup2.color:black

在 Java 中,由于赋予的是对象引用,所以执行 cup1 = cup2; 之后,cup1 与 cup2 实际上指向的是同一个引用,之后改变 cup1 的属性值,也就改变了 cup2,因为 cup1 和 cup2 此时指向的是堆中同一个对象。而 cup1 的原始对象引用在执行 cup1 = cup2; 之后便将其丢弃,这个引用对象会在垃圾回收时被清理。

这种情况,在英文中叫做 aliasing,原意是别名,也就是说,执行 cup1 = cup2; 之后,cup1 其实是 cup2 的别名。

2 方法传递

把对象传递给方法时,也会发生 aliasing。

public class ObjectToMethod {

    static void color(Saucer s) {
        s.color = "red";
    }

    public static void main(String[] args) {
        Saucer saucer = new Saucer();
        saucer.color = "blue";
        System.out.println("1: saucer.color:" + saucer.color);

        color(saucer);
        System.out.println("2: saucer.color:" + saucer.color);
    }
}

运行结果:

1: saucer.color:blue
2: saucer.color:red

这里,我们给方法 color() 传递了一个引用,这个方法在内部改变了这个引用所对应的对象属性值,实际上影响到了外层的这个对象。

因为引用传递给方法时,这个引用仍然指向的是同一个对象。

public class ReferencesToMethod {
    public static void m(ReferencesToMethod r) {
        System.out.println("m() 中的对象:" + r);
    }

    public static void main(String[] args) {
        ReferencesToMethod r = new ReferencesToMethod();
        System.out.println("main() 中的对象:" + r);
        m(r);
    }
}

运行结果:

System.out.println() 中的 r 变量,会直接调用 toString() 方法,它默认打印的是对象的类与对象所在地址,可以看到两个地址一模一样,从而证明了是同一个对象。

发布了626 篇原创文章 · 获赞 705 · 访问量 91万+

猜你喜欢

转载自blog.csdn.net/deniro_li/article/details/104100332