下面有关值类型和引用类型描述正确的是(ABC)?
- A 值类型的变量赋值只是进行数据复制,创建一个同值的新对象,而引用类型变量赋值,仅仅是把对象的引用的指针赋值给变量,使它们共用一个内存地址。
- B 值类型数据是在栈上分配内存空间,它的变量直接包含变量的实例,使用效率相对较高。而引用类型数据是分配在堆上,引用类型的变量通常包含一个指向实例的指针,变量通过指针来引用实例。
- C 引用类型一般都具有继承性,但是值类型一般都是封装的,因此值类型不能作为其他任何类型的基类。
- D 值类型变量的作用域主要是在栈上分配内存空间内,而引用类型变量作用域主要在分配的堆上。
我的理解(有错麻烦大家指正,谢谢!)
值类型:基本数据类型(int、double、boolean …)
引用类型:reference类型,通过它可以直接或间接的查找到对象在java堆中数据存放的起始地址或索引(对象在java堆中的哪个位置)
先来两个例子,变量的赋值在内存中是怎么样的:
一:基本变量的赋值
public void method() {
int a = 1;
int b = a;
}
该方法的字节码:
0 iconst_1 // 将 int 型 1 推送至操作数栈栈顶
1 istore_1 // 将操作数栈栈顶 int 型值存入第二个本地变量
2 iload_1 // 将第二个int型本地变量推送至操作数栈顶
3 istore_2 // 将操作数栈栈顶 int 型值存入第三个本地变量
4 return // 方法返回
二:基本变量的赋值
public void method2() {
Object a = new Object();
Object b = a;
}
该方法的字节码:
0 new #15 <java/lang/Object> // 创建一个对象,并将其引用压入栈顶
3 dup // 复制栈顶引用类型数据并将其值压入栈顶
4 invokespecial #1 <java/lang/Object.<init>> // 执行对象构造方法(使用了栈顶引用类型)
7 astore_1 // 将操作数栈栈顶引用类型数据值存入第二个本地变量 a
8 aload_1 // 将第二个引用类型本地变量推送至栈顶
9 astore_2 // 将栈顶引用类型数值存入第三个本地变量b
10 return // 方法返回
再看选项
-
A:值类型的和引用类型的变量赋值就像上面一样,先把局部变量表中 a 的数值存入操作数栈,再取出来放入 b,不过区别在于:
- 前者在局部变量表中存放的数值是真正意义上的 a 代表的数据,所以说赋值操作是“复制(iload_1、istore_2)”一份出来再给 b
- 后者在局部变量表中存放的数值不是真正意义上 a 代表的数据,只是指向堆中对象的指针(指向 a 真正代表的数据)。赋值操作只是把 a 中数值即指针复制给 b ,堆中a代表正真的数据即对象(0x11)并没有被复制
-
B:
- “值类型数据是在栈(指虚拟机栈)上分配内存空间,它的变量直接包含变量的实例,使用效率相对较高。” :**局部变量表(在虚拟机栈中)**中存放数值的就是真正意义上的数据,不用访问堆,效率较高
- “而引用类型数据是分配在堆上,引用类型的变量通常包含一个指向实例(指向堆中对象)的指针,变量通过指针来引用实例。” :局部变量表中存放的数值是指向堆中数据(对象)的指针
-
C:类可以继承,基本数据类型不能继承
-
D:“值类型变量的作用域主要是在栈上分配内存空间内”:如果是跟上诉一致在方法内定义的基本变量,它的作用域就在栈中;如果是在类中定义的成员变量例如 Class A 中有成员变量 int val,这个类的实例在堆中,那么 val 作用域也在堆中