2017-04-13 70 views
7
short s = 'a';  // valid 
Short ss = 'a';  // valid 
int i = 'a';   // valid 
Integer ii = 'a'; // invalid 

为什么Integer ii ='a'无效,但是int i ='a'有效吗?为什么短ss ='a'有效,但整数ii ='a'无效?java奇怪的分配规则


另一组问题:

byte b; 
final short s = 1; 
final Short ss = 1; 
final int i =1; 
final Integer ii = i; 
final long L = 1; 
final Long LL =1L; 

b = s;  // valid 
b = ss; // invalid 
b = i;  // valid 
b = ii; // invalid 
b = L;  // invalid 
b = LL; // invalid 

为什么B =升;无效,而b = s;有效?

请不要说这都是因为JLS这么说的。我想知道为什么JLS有这些不一致和不直观的规则。我错过了什么?

+6

因为自动装箱(和原始扩展转换)不能使'char'成为Integer。尝试'Integer ii =(int)'a'; ' –

+0

ii是类的实例,而我是整型数据类型的实例。 – Omore

+1

在java中学习'Autoboxing and Unboxing'的好时机。 https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html – yogidilip

回答

5

所以,该行:

Short s = 'a'; // is valid ... 

由于是无符号16位值(最大值为65,536)和是带符号的16位值(最大值为32,767),所以有一个缩小的原始转换(char to short),然后是一个装箱转换(short to short)。

short s = 'a'; // is valid - this is a narrowing primitive conversion (char -> short) 

这些special cases

此外,如果表达式是 型字节,或INT的常量表达式:

  • 缩小比例如果 变量的类型是字节,或,恒定 表达式的值在变量的类型表示的,可以使用略去转换。

可以 可以使用甲基本收缩转换接着装箱转换如果变量的类型是:

  • 字节和常量表达式的值在 类型可表示字节

  • 和常量表达式的值在 型表示的。

  • 字符和常量表达式的值表示的是在 类型

让我们进入下一个例子:

Integer ii = 'a'; // is invalid - not a special case according to Oracle docs 
int i = 'a';  // is valid - widening primitive conversion (char -> int) is allowed 

而更多的情况从你的问题:

byte b; 
final long L = 1; 
b = L // error - incompatible types 

为什么行b = L是无效的?因为它不是上面,我们可以铸造过程中丢失的信息描述一个特殊情况,这就是为什么你必须明确地执行它:

b = (byte) L; // is valid - narrowing primitive conversion (long -> byte) 

而且,看看成一个非常有用的table

在JLS文档中有关于所有这些规则的大量信息,您无需担心所有这些规则。我能说什么关于你的最后一个问题是,没有一个隐含的窄转换文字的任意整数将需要在未来的情况下,投:

// Cast is permitted, but not required - profit! 
byte b = (byte) 100; 
short s = (short) 100; 

感谢,我们可以将其更改为:

byte b = 100; 
short s = 100; 
+0

感谢您的详细回答。我理解你的解释。这完全是因为JLS这么说的。但为什么JLS有这个奇怪的规则?规则不一致。例如;只有在表达式是byte,short,char或int类型的常量表达式时才会发生缩小原语。但不长久?长期有什么问题? –

+0

@VincentQuan缩小的原始转换永远不会对'long'有意义,因为它是最大的原始整数类型。 – Hulk