1
public class ConstructorOverloading {
    static class A{
        final String msg;
        public A(Object o){
            this.msg = "via object";
        }

        public A(Integer i){
            this.msg = "via integer";
        }
    }

    public A aWith(Object o){return new A(o);}
    public A aWith(Integer i){return new A(i); }


    static class B{
        final String msg;
        public B(Object o){
            this.msg = "via object";
        }

        public B(Integer i){
            this.msg = "via integer";
        }
    }

    public <T> B bWith(T it){return new B(it);}

    public void test(){
        A aO = aWith(new Object());
        A aI = aWith(Integer.valueOf(14));

        B bO = bWith(new Object());
        B bI = bWith(Integer.valueOf(14));

        System.out.println(format("a0 -> %s", aO.msg));
        System.out.println(format("aI -> %s", aI.msg));
        System.out.println(format("b0 -> %s", bO.msg));
        System.out.println(format("bI -> %s", bI.msg));
    }
}

给我们

a0 -> via object
aI -> via integer
b0 -> via object
bI -> via object

我想那是由于类型擦除。

我可以对此做任何事情而不必插入显式类型检查或重载bWith吗?

我的意思是,应用程序在运行时知道它应该使用Integer-type 参数调用构造函数,它只是不知道调用正确的构造函数,毕竟......

另外——因为我猜答案是“不”——允许这样的事情会有什么问题?

4

1 回答 1

3

我的意思是,应用程序在运行时知道它应该使用整数类型参数调用构造函数,它只是不知道调用正确的构造函数,毕竟......

不,它没有。

这种方法:

public <T> B bWith(T it){return new B(it);}

必须能够为任何参数工作:编译器必须选择一个构造函数以在该方法中调用。唯一符合该标准的构造函数就是那个Object

在运行时让它做不同的唯一方法是显式转换(你也可以删除类型参数,它是多余的):

public B bWith(Object it){
  if (it == null || it instanceof Integer) {
    return new B((Integer) it);
  }
  return new B(it);
}

编辑:添加了it == null检查,因为它new B(null)实际上会调用Integer构造函数,因为它是两者中更具体的。

于 2019-08-21T09:20:45.557 回答