Java扩展转换

时间:2014-08-13 19:11:02

标签: 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失败?

我不清楚它是如何工作的。有人可以提供明确的解释吗?

5 个答案:

答案 0 :(得分:19)

Section 5.2 of the JLS涵盖了分配上下文中允许的转换类型。

  

分配上下文允许使用以下之一:

     
      
  • 身份转换(第5.1.1节)

  •   
  • 扩大原始转换(第5.1.2节)

  •   
  • 扩大参考转换(第5.1.5节)

  •   
  • 拳击转换(§5.1.7),可选地后跟扩展参考转换

  •   

此外,

  

此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):

     
      
  • 如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。

  •   
  • 如果变量的类型为:

    ,则可以使用缩小的基元转换,然后进行装箱转换。      
        
    • 字节和常量表达式的值可以在类型字节中表示。

    •   
    • 简短,常量表达式的值可以在短类型中表示。

    •   
    • 字符和常量表达式的值可以在char类型中表示。

    •   
  •   

Byte b = 10编译好,因为10是一个常量表达式,可以表示为byte

Byte b = new Byte(10)将无法编译,因为10int文字,方法调用转换不会执行原始缩小转换。要调用Byte构造函数进行编译,您可以明确地将10强制转换为byte

Byte b = new Byte( (byte) 10);

Long l = new Long(10)编译,因为方法调用转换将执行原始扩展转换,包括从intlong

Long l = 10将无法编译,因为Java不会特别允许进行扩展转换,然后进行装箱转换,as I discussed in a recent answer。要使其编译,您可以使用long文字,因此只需要装箱。

Long l = 10L;

答案 1 :(得分:10)

基本规则是:

  • 你不能一步转换 - 和 - 自动装箱(JLS 5.1.7定义装箱转换,它不包括转换和自动装箱类型转换,所以不允许)
  • 你不能隐含地缩小类型

这些规则解释了为什么Long l = 10不起作用以及new Byte(10)。第一个将要求将int literal 10扩展为long,然后将其装箱,这是不允许的。 (更确切地说,它需要从intLong的转换,JLS 5.1.7没有定义。)第二个要求将int literal 10隐式缩小为{{1 },这是不允许的。

但规则有例外。 JLS 5.2明确允许byte

  

此外,如果表达式是类型为Byte b = 10byteshortchar的常量表达式(第15.28节):

     
      
  • 如果变量的类型是:则可以使用缩小的基元转换,然后使用装箱转换:   
        
    • int,常量表达式的值可在Byte类型中表示。
    •   
  •   

(省略了一些不相关的部分)

最后,byte有效,因为int lite 10 可以自动扩展为10L长。

答案 2 :(得分:1)

10是一个整数文字,你必须向下传播它以将它传递给Byte构造函数。遗憾的是,没有字节文字语法来删除演员。

  

为什么Long l = new Long(10)编译好但Long l = 10失败?

因为10,一个整数,可以适合长而没有问题。整数不能放入一个字节,因此在这种情况下需要强制转换(扩展转换)。

这个演员也是编译时间,因为它也是一个扩大的转换。 Check out section 5.1.5 in the JLS

  

扩展引用转换在运行时从不需要特殊操作,因此决不会在运行时抛出异常。它们只是简单地将引用视为具有某种其他类型,并且在编译时可以证明是正确的。

答案 3 :(得分:1)

字节构造函数采用字节类型或字符串类型。见this

Long的构造函数需要long作为参数。由于long可以采用整数,因此它允许在构造函数中使用。

答案 4 :(得分:1)

我想我有一个解决你问题的方法......

//constructor for Byte class
Byte(byte value){

}

java类型转换有两个规则

  1. 两种类型都兼容
  2. 目标类型大于源类型
  3. 现在在你的情况下你试图将int转换为字节,这违反了我们的第二条规则.... 但下面是解决方案

    Byte b = new Byte((byte)10);
    

    现在让我们谈谈你的第二个问题......

     Long x = 10;//incompatible type
    

    这是自动装箱的问题...... 现在我们都知道autoboxing会自动将原始类型转换为它的包装类。 但是在自动装箱的情况下转换不会发生.... int 转换为整数 字节转换为字节 .. 现在当你将int基本类型赋给Long时,它会给你错误的类型不兼容....... 解决方案

    Long x = (long) 10;//works fine....