当Java编译器将一个原语自动装箱到包装器类时,它会在幕后生成什么代码?我想它叫:
假设我们有一个volatile int a.一个线程呢
while (true) {
a = 1;
a = 0;
}
Run Code Online (Sandbox Code Playgroud)
而另一个线程呢
while (true) {
System.out.println(a+a);
}
Run Code Online (Sandbox Code Playgroud)
现在,JIT编译器发出相应的汇编代码是不合法2*a的a+a吗?
一方面,易失性读取的目的是它应该始终从内存中消失.
另一方面,两个读取之间没有同步点,所以我看不出a+a原子处理是非法的,在这种情况下我不会看到如何进行优化2*a会破坏规范.
我们将不胜感激参考JLS.
为什么第二段代码更快?
Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
for (double j = 0.0; j < 10000; j++) {
map.put(i, j);
}
}
Map<Integer, Double> map=new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
for (double j = 0.0; j < 10000; j++) {
map.put(new Integer(i), new Double(j));
}
}
Run Code Online (Sandbox Code Playgroud) 我只是想知道让java autobox说一个整数有什么区别:
Integer myInteger = 3; // This will call Integer.valueOf()
Run Code Online (Sandbox Code Playgroud)
或者你的代码是
Integer myInteger = Integer.valueOf(3);
Run Code Online (Sandbox Code Playgroud)
这有什么微优化吗?我知道第二个更明确,但它也更不必要打字,除此之外有什么区别吗?
以下代码用于Integer使用对象实习:
Integer.valueOf("1")
Run Code Online (Sandbox Code Playgroud)
从API文档中不清楚此代码是否Boolean也使用了interned对象:
Boolean.valueOf("true")
Run Code Online (Sandbox Code Playgroud)
显然,它可能.但是它必须吗?
UPDATE
我同意源代码可以解释实际发生的事情(BTW,感谢答案).为了使问题变得不那么简单,Java API规范或JSL的任何部分是否告诉必须发生什么?
对这样的代码提出问题是很自然的:
String str = "true";
if (Boolean.valueOf(str) == Boolean.TRUE) { ... }
Run Code Online (Sandbox Code Playgroud)
结果取决于"对象实习"是否得到保证.最好完全避免使用这些代码true而不是Boolean.TRUE(而不是查找任何规范或来源中的详细信息),但这是提出问题的正当理由.
注意:事实上,我没有看到Integer任何Google搜索规范中对象实习的保证.所以,它可能只是一个没人应该依赖的实现细节.
阅读 JAVA 13 SE 规范,我在第 5 章第 5.1.7 节中找到。拳击转换以下保证:
如果被装箱的值 p 是对 boolean、char、short、int 或 long 类型的常量表达式(第 15.28 节)求值的结果,并且结果为 true、false,则为 '\u0000' 到 ' 范围内的字符\u007f'(含),或 -128 到 127(含)范围内的整数,然后让 a 和 b 是 p 的任意两次装箱转换的结果。a == b 总是这样
我觉得奇怪的是,字节类型的值被排除在该措辞之外。
例如,在如下代码中:
Byte b1=(byte)4;
Byte b2=(byte)4;
System.out.println(b1==b2);
Run Code Online (Sandbox Code Playgroud)
我们有一个byte类型的常量表达式,装箱后b1和b2的值可能是也可能不是同一个对象。
在没有演员的情况下,它实际上以相同的方式工作:
Byte b1=4;
Run Code Online (Sandbox Code Playgroud)
在这里,我们在赋值上下文中有一个 int 类型的常量表达式。所以,根据规范
如果变量的类型为 Byte、Short 或 Character,并且常量表达式的值可分别以 byte、short 或 char 类型表示,则可以使用缩窄原语转换后跟装箱转换。
因此表达式将被转换为字节,并且该字节类型的值将被装箱,因此不能保证该值是实习的。
我的问题是我对规范的解释是否正确,还是我遗漏了什么?我查看了规范是否需要使用 Byte.valueOf() 方法进行装箱(为此可以保证),但事实并非如此。
这些对我来说都很好:
示例 1:
Character newCharacter = 'c';
Run Code Online (Sandbox Code Playgroud)
示例 2:
Character newCharacterOther = new Character('c');
Run Code Online (Sandbox Code Playgroud)
但有什么区别呢?
在第一个示例中,Character 类如何知道将其值设置为“c”而不需要构造函数?
它是否在幕后使用工厂方法?有人可以向我解释编译器如何知道要做什么吗?
我在java.lang 中提供了Character.class 的构造函数的图像。
它甚至说它已被弃用,不应该像那样访问它,但我仍然有点困惑。
我用以下字段创建了一个Interval类:
...
private static final Integer MINF = Integer.MIN_VALUE;
Integer head,tail;
...
Run Code Online (Sandbox Code Playgroud)
当我创建这个类的实例,制作this.head = Integer.MIN_VALUE,并且我想检查head的值是否相等时MINF,它表示它们不相等.
Interval i = new Interval(Integer.MIN_VALUE,10);
System.out.println(i.toString()); //[-2147483648,10]
Run Code Online (Sandbox Code Playgroud)
所以我继续尝试打印这些值,
public String toString() {
...
//What the hell?
System.out.println("MINF == Integer.MIN_VALUE: " + (MINF == Integer.MIN_VALUE)); //true
System.out.println("MINF == this.head: " + (MINF == this.head)); //false
System.out.println("Integer.MIN_VALUE == this.head: " + (Integer.MIN_VALUE == this.head)); //true
...
return "*insert interval in format*";
}
Run Code Online (Sandbox Code Playgroud)
哪个说
MINF == Integer.MIN_VALUE是真的
MINF == this.head虽然是假的 …
java ×8
autoboxing ×3
boxing ×1
constructor ×1
factory ×1
integer ×1
java-13 ×1
java.lang ×1
jit ×1
jls ×1
memory-model ×1
minimum ×1
performance ×1
volatile ×1