Java 原语的扩展和装箱

发布于 2024-11-29 01:31:26 字数 575 浏览 1 评论 0原文

扩展和装箱 Java 原语。

我知道不可能将包装类从一个扩展为另一个,因为它们不是来自同一继承树。为什么不能将一个基元扩展为另一个基元类型并自动装箱扩展的基元?

鉴于可以将字节参数传递给需要 int 的方法,为什么下面示例中的字节不能扩展为 int,然后装箱为 Integer?

class ScjpTest{
    static void goInteger(Integer x){
        System.out.println("Going with an Integer");
    }

    static void goInt(int x){
        System.out.println("Going with an int");
    }

    public static void main(String args[]){
        byte b = 5;
        goInt(b);
        goInteger(b);
    }
}

在上面的示例中,编译器接受 goInt(b),但拒绝 goInteger(b)

Widening and Boxing Java primitives.

I know it is not possible to widen a wrapper class from one to another as they are not from the same inheritence tree. Why though is it not possible to widen a primitive to another primitive type and autobox the widened primitive?

Given that a byte argument can be passed to a method that expects an int, why cant the byte in the following example be widened to an int and then boxed to an Integer?

class ScjpTest{
    static void goInteger(Integer x){
        System.out.println("Going with an Integer");
    }

    static void goInt(int x){
        System.out.println("Going with an int");
    }

    public static void main(String args[]){
        byte b = 5;
        goInt(b);
        goInteger(b);
    }
}

In the above example, goInt(b) is accepted by the compiler but goInteger(b) is rejected.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

终难遇 2024-12-06 01:31:26

简短回答

java 语言仅支持某种程度的粗心。

更长的答案

我相信添加自动装箱是为了支持开发人员的粗心大意。特别是在这样的情况下:“我需要一个 Integer 作为我想要调用的方法的参数,但我有一个 int。不知何故, new Integer(int) 永远不会出现在我的脑海中。相反,我只会发送一个 int java 编译器将为我执行 new Integer() 调用,感谢 java 粗心支持小组!”

设计自动装箱的人们愿意支持 1 级粗心(int => Integer 并返回),但不愿意支持将较小的原始类型自动转换为较大的原始类型,并结合自动创建和从原始类型包装类中提取。我怀疑这个决策矩阵会比当前自动装箱方案的决策矩阵稍大。

Short answer

The java language only supports some level of carelessness.

Longer answer

I believe that autoboxing was added to support developer carelessness. Specifically in situations like this: "I need an Integer as a parmeter to the method I want to call, but I have an int. Somehow, new Integer(int) never pops into my head. Instead, I'll just send an int and the java compiler will do the new Integer() call for me. Thanks java carelessness support group!"

The folks designing autoboxing were willing to support 1 level of carelessness (int => Integer and back), but were not willing to support auto casting of smaller primitive types to larger primitive types in conjunction with automatic creation and extration from primitive type wrapper classes. I suspect the descision matrix for this would be somewhat larger than the decision matrix for the current autoboxing scheme.

弥繁 2024-12-06 01:31:26

为什么?因为装箱/自动装箱只是一些编译器糖,而不是新的类型系统。
它设计得很糟糕,带来麻烦的次数至少与它简化事情的次数一样多。

但这里有一些针对编译错误的解决方法:

goInteger((int) b);

// these are equivalent
goInteger(((Byte) b).intValue());
goInteger(Byte.valueOf(b).intValue());

Why? Because boxing / autoboxing is only some compiler sugar and not a new type system.
It's badly designed and causes trouble at least as often as it simplifies things.

But here are some workarounds for your compile error:

goInteger((int) b);

// these are equivalent
goInteger(((Byte) b).intValue());
goInteger(Byte.valueOf(b).intValue());
人海汹涌 2024-12-06 01:31:26

如果我们允许太多的魔法转换,就会变得非常混乱。

现有的转换规则已经超出了人们的理解范围。连语言规范都错了!请参阅这个有趣的示例 Java 转换:是编译器错误,还是语言规范错误,还是我错了?

If we allow too many magic conversions, it'll get very confusing.

The existing conversion rules are already more than people care to understand. Even the language spec got it wrong! See this funny example Java casting: is the compiler wrong, or is the language spec wrong, or am I wrong?

七禾 2024-12-06 01:31:26

在Java中,允许拳击+加宽,但不允许加宽+拳击
为了接受 goInteger,首先需要扩展原始数据类型(byte -> int),这是可以的,然后需要装箱(int -> Integer)。
请找出加宽、拳击和 Vararg 的 5 条黄金法则:

  1. 原始扩展>拳击>可变参数。
  2. 不允许加宽和拳击 (WB)。
  3. 允许装箱和加宽 (BW)。
  4. 重载时,加宽 + 可变参数和装箱 + 可变参数只能以互斥的方式使用,即不能一起使用。
  5. 不允许扩展包装类之间

我希望这会对您有所帮助。
就此而言,
苏迪普塔·德布.

In Java, Boxing + Widening is allowed, but not Widening + Boxing..
For goInteger to be accepted, first widening of primitive datatype (byte -> int) is required, which ok and then Boxing is required (int -> Integer).
Please find the 5 golden ruled of Widening, Boxing and Vararg:

  1. Primitive Widening > Boxing > Varargs.
  2. Widening and Boxing (WB) not allowed.
  3. Boxing and Widening (BW) allowed.
  4. While overloading, Widening + vararg and Boxing + vararg can only be used in a mutually exclusive manner i.e. not together.
  5. Widening between wrapper classes not allowed

I hope this will help you.
With regards,
Sudipta Deb.

⊕婉儿 2024-12-06 01:31:26

我认为这个顺序非常有趣。我设计了以下游乐场来查看每种可能的组合。这是我的职能:

static void doSomeThing(short i) {
    System.out.println("short");
}

static void doSomeThing(short... i) {
    System.out.println("short...");
}

static void doSomeThing(Short i) {
    System.out.println("SHORT");
}

static void doSomeThing(Short... i) {
    System.out.println("SHORT...");
}

static void doSomeThing(long i) {
    System.out.println("long");
}

static void doSomeThing(long... i) {
    System.out.println("long...");
}

static void doSomeThing(Long i) {
    System.out.println("LONG");
}

static void doSomeThing(Long... i) {
    System.out.println("LONG...");
}

static void doSomeThing(int i) {
    System.out.println("int");
}

static void doSomeThing(int... i) {
    System.out.println("int...");
}

static void doSomeThing(Integer i) {
    System.out.println("INTEGER");
}

static void doSomeThing(Integer... i) {
    System.out.println("INTEGER...");
}

static void doSomeThing(Object i) {
    System.out.println("Object");
}

static void doSomeThing(Object... i) {
    System.out.println("Object...");
}

规则:

 1.Searches for exactly the same type (int -> int)
 2.Widening (int -> long)
 3.Boxing (int-> Integer, it is NEVER possible to implicit box AND wide (int -> Long NOT possible without cast))
 !!Multiple boxing go BEFORE var args!!
 int -> Object will be chosen before int -> int...
 4.Var args (int -> int...)
 5.Widening + var args (int -> long...)
 6.Boxing + var args (int -> Integer...)
 7.Boxing + widening + var args (int -> Object...)

public class Main{

    public static void main(String...args) {
        //primitive int
        int i = 0;
        doSomeThing(i); //int
        //commented out doSomeThing(int i){}
        doSomeThing(i); //long. It is not possible to narrow, so short, short... Short and Short... will NEVER be called when the input is larger than a short.
        //commented out doSomeThing(long i){}
        doSomeThing(i); //INTEGER
        //commented out doSomething(Integer i){}
        doSomeThing(i); //Object. Notice that there can be multiple boxing before moving to var args
                            //Error occured: compiler if confused: can either execute int..., long..., Object... or Integer...
        //Object... and Integer... are commented out, because in the real world int... will be called first
        doSomeThing(i); //int...
        //commented out int...
        doSomeThing(i); //long...
        //commented out long... and uncommented Integer...
        doSomeThing(i); //Integer...
        //commented out Integer... and uncommented Object...
        doSomeThing(i); //Object...

                //Integer
        //Integer
        Integer i = new Integer(0);
        doSomeThing(i); //INTEGER
        //commented out doSomeThing(Integer i)
        doSomeThing(i); //Object
        //commented out doSomeThing(Object i)
        doSomeThing(i); //int
        //commented out doSomeThing(int i)
        doSomeThing(i); //long so NOT int... it goes widening again
        //commented out doSomeThing(long i)
                        //Error occured: compliler refused: not both have int..., long..., Integer... and Object...
        //int... and long... are commented out
        doSomeThing(i); //INTEGER...
        //commented out doSomeThing(Integer... i)
        doSomeThing(i); //Object...
        //commented out doSomeThing(Object... i)
        //uncommented doSomeThing(int... and long...)
        doSomeThing(i); //int...
        //uncommented doSomeThing(int... i)
        doSomeThing(i); //long...
    }

I think the order is pretty fascinating. I made out the following playground to see every possible combination. This are my functions:

static void doSomeThing(short i) {
    System.out.println("short");
}

static void doSomeThing(short... i) {
    System.out.println("short...");
}

static void doSomeThing(Short i) {
    System.out.println("SHORT");
}

static void doSomeThing(Short... i) {
    System.out.println("SHORT...");
}

static void doSomeThing(long i) {
    System.out.println("long");
}

static void doSomeThing(long... i) {
    System.out.println("long...");
}

static void doSomeThing(Long i) {
    System.out.println("LONG");
}

static void doSomeThing(Long... i) {
    System.out.println("LONG...");
}

static void doSomeThing(int i) {
    System.out.println("int");
}

static void doSomeThing(int... i) {
    System.out.println("int...");
}

static void doSomeThing(Integer i) {
    System.out.println("INTEGER");
}

static void doSomeThing(Integer... i) {
    System.out.println("INTEGER...");
}

static void doSomeThing(Object i) {
    System.out.println("Object");
}

static void doSomeThing(Object... i) {
    System.out.println("Object...");
}

Rules:

 1.Searches for exactly the same type (int -> int)
 2.Widening (int -> long)
 3.Boxing (int-> Integer, it is NEVER possible to implicit box AND wide (int -> Long NOT possible without cast))
 !!Multiple boxing go BEFORE var args!!
 int -> Object will be chosen before int -> int...
 4.Var args (int -> int...)
 5.Widening + var args (int -> long...)
 6.Boxing + var args (int -> Integer...)
 7.Boxing + widening + var args (int -> Object...)

public class Main{

    public static void main(String...args) {
        //primitive int
        int i = 0;
        doSomeThing(i); //int
        //commented out doSomeThing(int i){}
        doSomeThing(i); //long. It is not possible to narrow, so short, short... Short and Short... will NEVER be called when the input is larger than a short.
        //commented out doSomeThing(long i){}
        doSomeThing(i); //INTEGER
        //commented out doSomething(Integer i){}
        doSomeThing(i); //Object. Notice that there can be multiple boxing before moving to var args
                            //Error occured: compiler if confused: can either execute int..., long..., Object... or Integer...
        //Object... and Integer... are commented out, because in the real world int... will be called first
        doSomeThing(i); //int...
        //commented out int...
        doSomeThing(i); //long...
        //commented out long... and uncommented Integer...
        doSomeThing(i); //Integer...
        //commented out Integer... and uncommented Object...
        doSomeThing(i); //Object...

                //Integer
        //Integer
        Integer i = new Integer(0);
        doSomeThing(i); //INTEGER
        //commented out doSomeThing(Integer i)
        doSomeThing(i); //Object
        //commented out doSomeThing(Object i)
        doSomeThing(i); //int
        //commented out doSomeThing(int i)
        doSomeThing(i); //long so NOT int... it goes widening again
        //commented out doSomeThing(long i)
                        //Error occured: compliler refused: not both have int..., long..., Integer... and Object...
        //int... and long... are commented out
        doSomeThing(i); //INTEGER...
        //commented out doSomeThing(Integer... i)
        doSomeThing(i); //Object...
        //commented out doSomeThing(Object... i)
        //uncommented doSomeThing(int... and long...)
        doSomeThing(i); //int...
        //uncommented doSomeThing(int... i)
        doSomeThing(i); //long...
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文