Java中对象和对象引用的区别
本文最后更新于:12 天前
⚡对象
对象是什么?
在《Java编程思想》里,是这样解释的:
“按照通俗的说法,每个对象都是某个类(class)的一个实例(instance),这里,‘类’就是‘类型’的同义词。”
所以对象是类的实例。而类就是类型的意思。
⚡对象引用
同样是《Java编程思想》里面的一句话:
“每种编程语言都有自己的数据处理方式。有些时候,程序员必须注意将要处理的数据是什么类型。你是直接操纵元素,还是用某种基于特殊语法的间接表示(例如C/C++里的指针)来操作对象。所有这些在 Java 里都得到了简化,一切都被视为对象。因此,我们可采用一种统一的语法。尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“引用”(reference)。”
用一个例子来理解
A a = new A();
A a则仅仅是对象的声明,是在栈上创建了一个对象引用。
即a是一个对象引用而非对象本身。
而只有当new A()这个操作调用之后,才在堆上创建一个类A的对象,或者说是实例。
而a = new A();才是真正把a这个对象引用和对象本身关联上。
⚡对象和对象引用的区别
下面看一个例子
public class Test{
public static void main(String[] args){
int[] a = new int[]{0};
int b = a[0];
b = 123;
System.out.println(a[0]);
}
}
如果我们认为Java中的引用和C中的指针是同一个东西的话,上面这段Java程序就应该对应的下面这段c++程序
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a[1]={0};
int *b = a;
*b = 123;
cout<<a[0];
return 0;
}
这段C++程序的结果当然是123。
但上面第一段Java程序输出结果当然是0而不是123。
这是因为Java中的引用虽然和C++的指针看似好像一样,都是描述变量的工具,但实际上还是有差别的。
Java中的变量只有两种类型,一种是基本数据类型,还有一种是引用类型。
当作为参数传递给一个方法时,处理这两种类型的方式是相同的。Java中都是按值传递,没有引用传递。即:
按值传递意味着传递的是原始值的一个副本。这样,即使函数改变了值,改变的也是原始值的副本,而非原始值本身。
而引用传递则意味着函数接收的就是原始值本身,这样当函数修改这个值,那么对应的原始值也会被修改。
看一个例子
/**
* @author yinchao
*/
public class NewClassForTest {
int a;
String name;
}
import org.junit.jupiter.api.Test;
/**
* @author yinchao
*/
class TestMethod {
@Test
public void test() {
String string = new String("123");
NewClassForTest newClassForTest = new NewClassForTest();
newClassForTest.a = 1;
newClassForTest.name = "test1";
change(string,newClassForTest);
System.out.println(string);
System.out.println(newClassForTest.a+"\n"+newClassForTest.name);
}
private void change(String newString,NewClassForTest newClassForTest) {
newString = "1234";
newClassForTest.a = 2;
newClassForTest.name = "test2";
}
}
结果:
123
2
test2
那么在此处为什么同样是通过change方法,string的结果没变,而newClassForTest的改变了?
-
对于string因为在change方法中,newString这个对象引用已经不再指向原来的对象"123"了
在 new String的过程中,newString 这个对象引用已经把原来的指向取消,而且建立了一个新的指向到这个新的"1234"。而原来的string还是指向到原来的"123",并没有收到对象引用副本改变指向的影响。
-
对于newClassForTest,newClassForTest.a = 2;实际上是把对象的属性赋了新的值。函数形参和实参都是对象的引用,而且都是指向同一个对象,和副本并无关系,和是否在函数内也没有关系。这两个newClassForTest并没有主从之分,一个对象引用改变的对象的属性,另一个对象引用的对象当然也会随之改变。
本博客所有文章除特别声明外,均采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 。转载请注明出处!