当我们对变量进行一些操作时,我们只是将指针更改为另一个文字?我对“字面意思”一词的确切含义有点困惑。
假设我们有 int x = 3; // 3 是字面量且不可变,x 是变量
对 ex: x++ 进行操作
现在 x == 4;所以我们的 var x 只是指向一个新的文字。计算机只记得 3 + 1 是 4 吗?
x 不是指针。
JVM 规范只是说明了会发生什么;故意不指定如何发生。所以,这个答案只是解释了它如何在我所知道的所有 JVM 上工作。几乎一样好。它肯定应该澄清问题:
class Example {
int x = 3;
void foo() {
x++;
}
}
这里,任何时候执行
new Example()
,都会为此实例保留一些内存块。对象的实例只是一个内存块,它保存其基本属性(包括这是一个 Example
类型的对象)和存储 every 非静态字段值的空间。在本例中,int x
- 这是一个非静态字段。
原语是特殊的数据类型:它是一个硬编码列表:int、long、short、byte、double、float、boolean 和 char。就是这样。这就是整个列表,您无法添加任何新类型。它们是“特殊的”——原始类型的任何值都只是值。 不是指针。
因此,
int x = 3
意味着任何创建新示例实例(new Example()
)的尝试都将如前所述,在内存中保留一些空间来存储x
字段的值,并且该值是直接3 .它不是“指向3个对象的指针”。只是.. 3. 它至少需要 32 位(因为 int
是 32 位),实际上可能需要 64 位(CPU 几乎要求对象很好地对齐:它们以可整除的值开始64 位,在 64 位 CPU 上)。
x++
只需找到位序列为 0000....0000011 的内存位置(0011
是二进制的“3”),然后将其递增,将其变为 0000....0000100.
相反,让我们尝试使用一个对象 - 任何不在原语列表中的都是对象,并且所有这些值都是指针。 (在java中,“引用”)。所以,在这个稍微改变的代码中:
class Example {
Integer x = 3;
void foo() {
x++;
}
}
一些非常非常不同的事情正在发生。对于初学者来说,自动装箱:这是语法糖,就像您编写的那样进行编译:
class Example {
Integer x = Integer.valueOf(3);
void foo() {
x = Integer.valueOf(x.intValue() + 1);
}
}
为什么?因为 JLS 是这么说的 - 这就是当您尝试
x++
时发生的情况,其中 x
是非原始类型,但是,可以自动装箱为 int
。
那么,这里发生了什么?谁知道?谁在乎呢 -
valueOf
的代码做了它该做的事。它的行为就像规范所说的那样,询问“如何”通常没有用。但是,如果你有兴趣:
Integer
(类)在加载时(它总是会这样,因为它是一个核心类)创建一个“缓存”,并为 -128 到 +127 之间的每个值创建 1 个 Integer 对象。如果可能的话,
Integer.valueOf
将从缓存中返回值(即传递给它的参数在-128和+127之间),否则它会创建一个新的Integer对象。鉴于 3 和 4 适合,你会得到这样的结果:package java.lang;
public class Integer {
private static final Integer[] cache = new Integer[255];
static {
for (int i = 0; i < 256; i++) {
cache[i] = new Integer(i - 128);
}
}
public static Integer valueOf(int v) {
if (v >= -128 && v <= 127) return cache[v + 128];
return new Integer(v);
}
private final int value;
public Integer(int v) {
this.value = v;
}
public int intValue() {
return v;
}
}
x + 1
在java中可以工作,因为规范是这么说的。它没有一些查找表来表示“3 + 1 等于 4”,加法的概念已经融入到 CPU 中。忘记指针之类的东西,计算机是二进制的,因此数字只能严格以零和一的形式存在。因此,即使是 -1 也很棘手(没有“-”。只有零和一!)。然而,仅仅因为数字以二进制存储并不意味着加法在某种程度上是不可能的。
假设 5 和 9:5 = 二进制 00000101
最后的数字是 1 和 1。将它们加在一起:即 0,进位 1。我们有:
???????0
??????10
?????110
00001110
。不需要查找表来执行此操作。只是重复应用这个简单的表格:
数字1 | 数字2 | 输出 | 携带 | |
---|---|---|---|---|
0 | 0 | 0 | 0 | |
1 | 0 | 1 | 0 | |
0 | 1 | 1 | 0 | |
1 | 1 | 0 | 1 | |
0 | 0 | 1 | 0 | |
1 | 0 | 0 | 1 | |
0 | 1 | 0 | 1 | |
1 | 1 | 1 | 1 |