从JDK 5.0开始,自动装箱/拆箱是在java中引入的,技巧简单而有用,但是当我开始测试包装类和原始类型之间的不同转换时,我真的很困惑自动装箱的概念如何在java中工作,例如:
拳击
int intValue = 0;
Integer intObject = intValue;
byte byteValue = 0;
intObject = byteValue; // ==> Error
Run Code Online (Sandbox Code Playgroud)
尝试不同的情况下(后short
,long
,float
,double
),这是由编译器所接受的唯一情况是,当值的上做作运算符右侧的类型是int
.当我查看我的源代码时Integer.class
发现它只实现了一个带int
参数的构造函数.
所以我的结论是自动装箱的概念是基于包装类中实现的构造函数.我想知道这个结论是否属实,还是有自动拳击使用的另一个概念?
拆箱
Integer intObject = new Integer(0);
byte byteValue = intObject; // ==> Error (the same Error with short)
int intValue = intObject;
double doubleValue = intObject;
Run Code Online (Sandbox Code Playgroud)
关于拆箱的结论是包装类给出了对应的类型(Integer
==> int
)包装的值,然后编译器使用通常的转换基元类型的规则(byte
=> short
=> int
=> long
=> float
=> double
).我想知道这个结论是否属实,还是自动拆箱使用了另一个概念? …
所以我今天被问到这个问题.
Integer a = 3;
Integer b = 2;
Integer c = 5;
Integer d = a + b;
System.out.println(c == d);
Run Code Online (Sandbox Code Playgroud)
这个节目打印出来的是什么?它返回true.我回答它总会打印出来,因为我理解自动(和自动联合)拳击.我的印象是,分配整数a = 3将创建一个新的整数(3),以便==将评估参考而不是原始值.
有谁能解释一下?
我有点困惑:我有一个函数,它以Object作为参数.但是如果我只传递一个原语甚至将布尔基元识别为布尔对象,编译器就不会抱怨.为什么会这样?
public String test(Object value)
{
if (! (value instanceof Boolean) ) return "invalid";
if (((Boolean) value).booleanValue() == true ) return "yes";
if (((Boolean) value).booleanValue() == false ) return "no";
return "dunno";
}
String result = test(true); // will result in "yes"
Run Code Online (Sandbox Code Playgroud) 在斯卡拉,
{ x: Option[Int] => x }
.getClass
.getMethod("apply", classOf[Option[_]])
.getGenericParameterTypes
Run Code Online (Sandbox Code Playgroud)
回报Array(scala.Option<java.lang.Object>)
.我最初期待看到Array(scala.Option<scala.Int>)
,但我看到它scala.Int
是一个值类(extends AnyVal
)'其实例未被底层主机系统表示为对象'.
不过,我仍然不理解擦除Object
.难道不是更有用java.lang.Integer
吗?
前NullPointerException
几天我在三元运算符中意外地进行了类型转换,这让我感到非常奇怪.鉴于此(无用的示例)功能:
Integer getNumber() {
return null;
}
Run Code Online (Sandbox Code Playgroud)
我希望编译后以下两个代码段完全相同:
Integer number;
if (condition) {
number = getNumber();
} else {
number = 0;
}
Run Code Online (Sandbox Code Playgroud)
与
Integer number = (condition) ? getNumber() : 0;
Run Code Online (Sandbox Code Playgroud)
.
事实证明,如果condition
是true
,if
-statement工作正常,而第二个代码段中的三元操作抛出一个NullPointerException
.似乎三元操作决定int
在将结果自动装箱之前将两种选择都输入到一个Integer
!?!事实上,如果我明确地转换0
为Integer
,则异常消失.换一种说法:
Integer number = (condition) ? getNumber() : 0;
Run Code Online (Sandbox Code Playgroud)
是不一样的:
Integer number = (condition) ? getNumber() : (Integer) 0;
Run Code Online (Sandbox Code Playgroud)
.
因此,似乎三元运算符和等效if-else
语句之间存在字节码差异(我没想到的事情).这提出了三个问题:为什么会有差异?这是三元实现中的错误还是有类型转换的原因?鉴于存在差异,三元运算的性能是否与等效的if
陈述相比或多或少(我知道,差异不是很大,但仍然存在)?
我是一名高级解决方案架构师,但我最近偶然发现了一个让我停下来思考的问题......
对我来说,下面的代码总是应该触发错误,但当我的一位同事问我为什么Eclipse没有显示错误时,我无法回答任何问题.
class A {
public static void main(String... args) {
System.out.println(new Object() == 0);
}
}
Run Code Online (Sandbox Code Playgroud)
我已经调查过,发现在源级别为1.6时确实会抛出一个错误:
incomparable types: Object and int
Run Code Online (Sandbox Code Playgroud)
但现在在1.7中编译好了.
请问,有哪些新功能可以保证这种行为?
我正在尝试制定下面方案中使用的规则.请解释为什么我得到2个不同的输出.
场景1输出:我是一个对象.
class Test {
public static void main (String[] args) {
Test t = new Test();
byte b_var = 10;
t.do_the_test(b_var);
}
public void do_the_test(Character c) {
System.out.println("I am a character.");
}
public void do_the_test(Integer i) {
System.out.println("I am an integer.");
}
public void do_the_test(Object obj) {
System.out.println("I am an object.");
}
}
Run Code Online (Sandbox Code Playgroud)
场景2输出:我是一个整数.
class Test {
public static void main (String[] args) {
Test t = new Test();
byte b_var = 10;
t.do_the_test(b_var);
}
public void …
Run Code Online (Sandbox Code Playgroud) 在使用int
和short
类型的常量自动装箱期间没有错误Byte
,但是类型为常量的常量long
有错误.为什么?
final int i = 3;
Byte b = i; // no error
final short s = 3;
Byte b = s; // no error
final long l = 3;
Byte b = l; // error
Run Code Online (Sandbox Code Playgroud) 以下是有什么区别的:
Integer in = (Integer)y;
和
Integer in = new Integer(y);
我想将int
类型转换为Integer
类型,反之亦然.这是我的代码:
public class CompareToDemo {
public static void main(String[] args) {
// Integer x=5;
int y=25;
System.out.println(y+" this is int variable");
Integer in = (Integer)y;
//Integer in = new Integer(y);
if(in instanceof Integer){
System.out.println(in +" this is Integer variable");
}
}
}
Run Code Online (Sandbox Code Playgroud) Java SE 11 的JLS §5.2包含一些 Java 8 的 JLS 没有的新类型转换案例,请参阅列表中的第 4 项和第 5 项:
赋值上下文允许使用以下之一:
- 身份转换
- 扩大原始转换
- 扩大参考转换
- 一个扩大的参考转换,然后是一个拆箱转换
- 扩展引用转换,然后是拆箱转换,然后是扩展基元转换
- 拳击转换
- 一个装箱转换,然后是一个扩大的参考转换
- 拆箱转换
- 一个拆箱转换,然后是一个扩大的原始转换
我不明白列表中的案例 4和案例 5。谁能用例子给我一些解释?如果可能,还请说明其实际用途。
更新:
正如@Naman 所评论的,这里是更改 JLS 的提议 - JDK-8166326:5.2:允许在拆箱前加宽,这是自 Java-9 以来生效的。在报告中,它提到:
这种行为对于与 capture 的互操作性尤其重要:各种现有程序都希望能够将 a 的元素
List<? extends Integer>
视为整数。Run Code Online (Sandbox Code Playgroud)List<? extends Integer> li = null; int i = li.get(0);
这可能暗示着这次 JLS 的改变确实有实际的必要性。但我还是不明白为什么 <? extends Integer> 很重要。什么是与捕获的互操作性意味着,它为什么如此重要?这些现有的各种程序是什么样的?它们是 Java …
autoboxing ×10
java ×9
unboxing ×2
boolean ×1
casting ×1
compare ×1
eclipse ×1
equivalence ×1
java-11 ×1
java-7 ×1
jls ×1
overloading ×1
primitive ×1
scala ×1
ternary ×1
type-erasure ×1