【问题标题】:Widening and boxing with Java使用 Java 进行扩展和装箱
【发布时间】:2011-12-22 08:43:20
【问题描述】:

在 Java 编程语言中加宽和装箱不起作用,但在下面的示例中它是如何工作的?

final short myshort = 10;
Integer iRef5 = myshort; 

为什么会这样?这和加宽然后框不一样吗?

但是如果我写下面的代码:

final int myint = 10;
Long myLONG = myint;

为什么它不起作用?

【问题讨论】:

  • 您使用什么编译器来获得结果?它似乎适用于 Eclipse 编译器,但不适用于 javac 编译器
  • 我无法让其中任何一个工作(使用 ideone.com)。

标签: java


【解决方案1】:

按照其他人的说法,我可以确认我可以使用 Eclipse 编译器编译您的第一个示例,但不能编译第二个。正如 Vlad 所说,使用 javac 编译器,两者都不能编译

这似乎是任一编译器中的错误!让我们咨询一下JLS,看看哪个是正确的:-)

【讨论】:

  • eclipse 编译器有一些已知且非常微妙的错误,这些错误在javac 上不存在。我记得另一个使用泛型的例子让我们想了一会儿。
  • @lsoliveira:您可能是对的,另请参阅this issue。但是,过去也发生过相反的情况。
  • 我想这总是有可能的(尽管它从未发生在我或我认识的任何人身上:-))。
【解决方案2】:

对于 java 7,这两个示例都不起作用。你会得到以下异常:

Type mismatch: cannot convert from short to Integer
Type mismatch: cannot convert from int to Long

因为问题不是因为拳击,而是因为转换。

【讨论】:

    【解决方案3】:

    您可以加宽或装箱,但不能同时进行。

    你可以的

    final int myint = 10;
    Long myLONG = (long) myint;
    

    【讨论】:

    • 在自动装箱之前,将short 隐式转换/提升到int 必须有一个微妙之处,应用于第一个示例。你知道哪条规则吗?
    • Object myLONG = 10L; 完全有效
    • @LukasEder 正如弗拉德所说,它不能为我编译。 ;)
    • @JigarJoshi 我不认为扩大参考是 OP 的意思。 Long l = (Integer) 10; 无法编译。
    • 你可以做 int i = 10; long l = i; 这是原始的加宽但是,如果你做 Long l = 10; 这不会编译它应该很长,只有 L 在结尾
    【解决方案4】:

    两者都无法正常工作(在 Linux 上使用 Sun/Oracle 的 javac 1.6.0_26)。 另见here

    b.java:4: incompatible types
    found   : short
    required: java.lang.Integer
            Integer iRef5 = myshort; 
                            ^
    b.java:7: incompatible types
    found   : int
    required: java.lang.Long
            Long myLONG = myint;
                          ^
    2 errors
    

    【讨论】:

    • 第一个示例适用于 Java 6(Eclipse 编译器)...?
    • 他们的行为会不会不同?我正在使用 Sun 的编译器,请参阅 here
    • 可能是。我在过去看到了不同之处,但不是这样简单的情况,请参阅this question, for instance
    【解决方案5】:

    让我们详细检查您要执行的操作:

    final short myshort = 10;
    Integer iRef5 = myshort; 
    

    编译器将首先尝试将这个short 装箱到一个对象中,然后它可以执行赋值(它不能直接扩展,因为它处理不同的类型:对象和原语)。

    简而言之,这相当于:

    final short myshort = 10;
    final Short box = new Short(myshort);  // boxing: so that objects are assignable.
    Integer iRef5 = box;  // widening: this fails as Integer is not a superclass of Short
    

    可以将相同的推理应用于您的第二个示例(也失败),如可见here。如果您的编译器没有抱怨第一个,那么编译器可能存在错误,因为这是 JLS 中定义的。请参阅 JLS here 中的完整转换/推广规则集。

    【讨论】:

      【解决方案6】:

      这些是适用于 Java 表达式的提升规则

      所有 byteshort 值都被提升为 int

      如果一个操作数是long,则整个表达式提升为long

      如果一个操作数是 float ,则整个表达式被提升为 float

      如果一个操作数是 double ,则整个表达式被提升为 double

      因此,short 值被提升为 int。这并没有扩大。 “将子类型转换为其超类型之一称为扩展”


      【讨论】:

        【解决方案7】:

        你可以先box 然后wide 但你不能widen 然后box

        所以

        final short myshort = 10;
        Integer iRef5 = myshort; 
        

        等价于

        final short myshort = 10;
        Integer iRef5 = 10; 
        

        这是完全有效的

        但是

        Long myLONG = 10;//this won't compile , 
        

        但是尝试使用10L 它会这样它会框然后你也可以让它成为对象,即Object o = 10L;


        另请参阅

        【讨论】:

        • 你确定第一个例子完全有效吗? Eclipse 编译器和 javac 编译器之间似乎存在差异。哪个是对的?
        猜你喜欢
        • 2011-10-24
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 2013-02-11
        • 1970-01-01
        • 1970-01-01
        • 2013-07-29
        • 2011-03-22
        相关资源
        最近更新 更多