Java扩展转换
我正在准备Java 7认证,并有以下问题。
Byte b = 10
编译好。 看起来编译器正在缩小int 10到byte 10然后装箱。 Byte b = new Byte(10)
怎么会编译? 为什么编译器不能像第一种情况那样缩小int 10到byte 10?
为什么Long l = new Long(10)
编译好但Long l = 10
失败?
我不清楚它是如何工作的。 有人可以提供清楚的解释吗?
JLS的5.2节介绍了赋值上下文中允许的转换类型。
赋值上下文允许使用以下之一:
身份转换(第5.1.1节)
扩展的原始转换(第5.1.2节)
扩大参考转换(第5.1.5节)
一个拳击转换(第5.1.7节),可选地后跟一个加宽的引用转换
另外,
此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):
如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。
如果变量的类型是:则可以使用缩小的基元转换,然后进行装箱转换:
字节和常量表达式的值可在类型字节中表示。
Short和常量表达式的值可以在short类型中表示。
字符和常量表达式的值可在char类型中表示。
Byte b = 10
编译好,因为10
是一个常量表达式,可以表示为一个byte
。
Byte b = new Byte(10)
将不会编译,因为10
是一个int
文字,并且方法调用转换不会执行原始缩小转换。 要调用Byte
构造函数进行编译,可以显式地将10
为byte
:
Byte b = new Byte( (byte) 10);
Long l = new Long(10)
编译因为方法调用转换将执行原始扩展转换,包括从int
到long
。
Long l = 10
将无法编译,因为Java将不会特别允许扩展转换,然后进行装箱转换, 正如我在最近的回答中所讨论的那样 。 要使其编译,您可以使用long
文字,因此只需要装箱。
Long l = 10L;
基本规则是:
- 你不能一步转换和自动转换( JLS 5.1.7定义装箱转换,它不包括转换和自动转换类型转换,所以不允许)
- 你不能隐含地缩小类型
这些规则解释了为什么Long l = 10
不起作用,以及new Byte(10)
。 第一个要求将int literal 10扩展为long
,然后将其装箱,这是不允许的。 (更准确地说,它需要从int
转换为Long
,JLS 5.1.7没有定义。)第二个要求将int literal 10隐式缩小为一个byte
,这是不允许的。
但该规则有例外。 JLS 5.2明确允许Byte b = 10
:
此外,如果表达式是
byte
,short
,char
或int
类型的常量表达式(第15.28节):
- 如果变量的类型是:则可以使用缩小的基元转换,然后进行装箱转换:
Byte
和常量表达式的值可在类型byte
表示。
(省略了一些不相关的部分)
最后, new Long(10)
可以工作,因为int literal 10 可以自动扩展到10L长。
字节构造函数采用字节类型或字符串类型。 看到这个
Long的构造函数需要很长时间才能成为一个参数。 由于long可以采用整数,因此它允许在构造函数中使用。
10是一个整数文字,你必须向下传播它以将它传递给Byte构造函数。 不幸的是,没有字节文字语法来删除演员表。
为什么Long l = new Long(10)编译好但Long l = 10失败?
因为10,一个整数,可以适合长而没有问题。 整数不能放入一个字节,因此在这种情况下需要强制转换(扩展转换)。
这个演员阵容也是编译时间,因为它也是一个扩大的转换。 查看JLS中的5.1.5节 :
扩展引用转换在运行时从不需要特殊操作,因此不会在运行时抛出exception。 它们只是简单地将引用视为具有某种其他类型,其方式可以在编译时certificate是正确的。
我想我有一个解决你问题的方法……
//constructor for Byte class Byte(byte value){ }
java类型转换有两个规则
- 两种类型都兼容
- 目标类型大于源类型
现在在你的情况下,你试图将int转换为字节,这是违反我们的第二条规则….但下面是解决方案
Byte b = new Byte((byte)10);
现在让我们谈谈你的第二个问题……
Long x = 10;//incompatible type
这是autoboxing的问题……现在我们都知道autoboxing自动将原始类型转换为它的包装类..但是在自动装箱的情况下转换不会发生…. int转换为整数 字节转换为字节 。现在,当你将int基本类型赋给Long时,它会给你错误的类型…….解决方案
Long x = (long) 10;//works fine....