示例:
Integer x = 56; 据我所知,只有在类或方法中调用了字段时,才能将值存储在对象中。在Integer类的情况下,如果不实例化一个对象,它应该不能调用它的value字段,因为value不是静态的。这怎么可能呢?
发布于 2021-05-13 09:51:25
只有在类或方法中调用了字段时,才能将
值存储在对象中。
这句话没有任何意义。我不知道这是对是错,只是...这说不通。
如果不实例化一个对象,它就不能调用它的value字段,因为value不是静态的。我就是想不通这是怎么回事。
Javac看到这一点后说:嘿,你把一个正方形的钉子(一个int类型的常量)塞进了一个圆孔(一个对象类型的变量)--这是没有意义的。除非,在Java中明确指出,如果int表达式出现在int表达式不应该出现的位置,但Integer表达式工作正常,则可以使用“应用自动装箱”。
“应用自动装箱”的意思是:假设程序员想写的是:Integer.valueOf(the expression),而不是他们写的东西。
因此:
Integer x = 56;
Integer x = Integer.valueOf(56);是完全相同的。它们是如此的相同,它们产生相同的字节码。无论您如何编写,对valueOf的调用都在您的类文件中。让我们测试一下:
> cat Test.java
class Test {
Integer x = 56;
}
> javac Test.java
(`javap` is part of java distributions and prints bytecode)
> javap -private -c Test
Compiled from "Test.java"
class Test {
java.lang.Integer x;
Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 56
7: invokestatic #7 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
10: putfield #13 // Field x:Ljava/lang/Integer;
13: return
}看看这个-调用静态方法Integer.valueOf,即使Integer.valueOf在我们的Test.java文件中完全没有出现。
那么,Integer.valueOf是如何工作的呢?
本质上,它是这样工作的:
package java.lang;
public class Integer {
private static final Integer[] CACHE = generateCache();
private final int value;
public Integer(int value) {
this.value = value;
}
private static Integer[] generateCache() {
for (int i = 0; i < 256; i++) {
CACHE[i - 128] = new Integer(i);
}
}
public static Integer valueOf(int v) {
if (v >= -128 && v < 128) return CACHE[i + 128];
return new Integer(v);
}
}换句话说,Integer类预先创建了256个整数对象,从-128到+127 (为什么是这些值?嗯,因为sun认为这些东西会经常出现,25年前就值得缓存它们了)。如果你用一个介于-128和+127之间的值进行valueOf(),你会得到一个缓存。如果你在它之外使用valueOf,你会得到一个新的对象。
我们也可以证明这一点:
> cat Example.java
class Example {
public static void main(String[] args) {
Integer a = -100;
Integer b = -100;
Integer c = 200;
Integer d = 200;
System.out.println("a == b? " + (a == b));
System.out.println("c == d? " + (c == d));
System.out.println("ident-hash a: " + System.identityHashCode(a));
System.out.println("ident-hash b: " + System.identityHashCode(b));
System.out.println("ident-hash c: " + System.identityHashCode(c));
System.out.println("ident-hash d: " + System.identityHashCode(d));
}
}
> java Example.java
a == b? true
c == d? false
ident-hash a: 1880794513
ident-hash b: 1880794513
ident-hash c: 1991313236
ident-hash d: 736778932此代码显示,对于-100,该Integer.valueOf调用返回的是完全相同的对象(==比较引用标识,即:它是否相同的对象,当在对象上使用时,它不会比较值。A和b只是指向相同的对象,而c和d指向具有相同值的不同对象)。
这就像在郊区某处建造的一堆相同的房子:a和b就像一张纸,上面写着相同的地址,而c和d就像一张纸,每个纸上都有不同的地址,但这两个地址上的房子看起来是一样的。
发布于 2021-05-13 09:55:24
对于语言中内置的对象类型,该语言可以而且确实会做出任何它想要的例外。简而言之,你可以在Java中做到这一点,因为Java说你可以做到。
具体地说,原始值(int、long等)到包装类(Integer、Long等)的转换称为“自动装箱”,顾名思义,它是自动执行的。
为什么允许这样做?因为它对用户来说非常方便。与自动拆箱一起,它允许您非常接近于像对待包装器类所包含的原始值一样对待它们。
一些术语:你只“调用”方法,而不是变量或字段。‘'Call’的意思是‘转移控制到’。
在像Integer这样的类中,你甚至不知道它有什么字段。你所知道的就是它可以存储一定范围内的整数值。只能通过调用构造函数或将返回Integer的静态方法之一将值输入Integer。
Documentation for Integer,如果你还没看过的话。请注意,没有任何操作可以“更改”Integer的值;我们说它是“不可变的”。如果你想要一个不同的值,你只能生成一个新的Integer。
https://stackoverflow.com/questions/67512882
复制相似问题