Java通用方法不起作用-参数不受限制 [英] Java generic method not working - parameter not being restricted

查看:56
本文介绍了Java通用方法不起作用-参数不受限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有这个代码:

  class演示{静态< T>T选择(T a1,T a2){返回a2;}公共静态void main(String [] args){pick("d",123);}} 

据我了解,似乎我已经说过两个参数 a1 a2 pick 的返回类型必须为在相同的通用类型 T 下.

那为什么编译器允许我将 String Integer 传递给 pick ?

解决方案

String Integer 都是 Object 的子类,Java中的其他类型.编译通用方法(或类)时,Java会尝试查找在通用类型的每个实例之间共享的最接近的超类型.这部分永远不会失败,因为 Object 存在.但是,如果将通用类型解析为 Object ,则可能不再有用.

那么,如果编译器允许使用任何类型,那么在这里使用泛型有什么意义呢?这与返回类型有关.假设您定义了 pick(),那么当您尝试编译每行时,您会怎么想?

 对象o = pick("Hello",123);//1字符串s = pick("Hello",123);//2字符串s = pick("Hello","world");//3整数i = pick("Hello",123);//4整数i = pick(123,456);//5int i = pick(123,456);//6 

1 可以很好地进行编译,但是您丢失了所有有用的类型信息.如果您根本不使用泛型,而是只对所有内容使用 Object ,就会发生这种情况.在Java 5之前,您必须要做的事情,还有大量的转换和异常捕获.

2 4 无法编译:

 错误:不兼容的类型:推断的类型不符合上限 

由于 pick()的两个参数仅共享 Object 作为通用超类型,因此 T 成为 Object 并且返回 Object ,并且您不能将 Object 分配给 String Integer .

3 效果很好.这两个参数具有相同的类型,因此很容易确定 T String . 5 的工作原理类似.

6 也可以,但是不能,因为 T 变为 int . int 是原始类型,因此不能在泛型中使用.尝试解析通用类型 T 时,编译器首先 Integer ).对于 4 5 ,即使您只是简单地分配了 Integer i = 123; 之类的文字,也会发生这种情况.此处的区别在于,将结果( Integer )取消装箱回到 int ,以便可以将其分配给 i .


在您的 pick()的示例实现中,返回值应与第二个参数具有相同的类型.如果您的API指定结果始终总是主要从该参数派生,则可以使用两种通用类型:

 静态< T,U>T pick(U a1,T a2){返回a2;} 

添加了此功能后, 2 仍无法编译,但 4 仍可以正常工作.

Say I have this code:

class Demo
{
    static <T> T pick(T a1, T a2)
    {
        return a2;
    }

    public static void main(String[] args)
    {
        pick("d", 123);
    }
}

From what I learned, it seems like I have stated that the two parameters a1, a2 and the return type of pick must be under the same generic type T.

So why is the compiler allowing me to pass a String and an Integer to pick?

解决方案

Both String and Integer are subclasses of Object, along with every other type in Java. When compiling a generic method (or class), Java attempts to find the closest supertype shared between every instance of the generic type. This part never fails, because Object exists. But if a generic type is resolved to Object, it may not be useful anymore.

So what’s the point in using generics here if the compiler will let any types to be used? It’s all to do with the return type. Assuming your definition of pick(), what do you think will happen when you try to compile each of these lines?

Object o = pick("Hello", 123);       // 1

String s = pick("Hello", 123);       // 2
String s = pick("Hello", "world");   // 3

Integer i = pick("Hello", 123);      // 4
Integer i = pick(123, 456);          // 5
int i = pick(123, 456);              // 6

1 compiles just fine, but then you’ve lost any useful type information. This is what would happen if you didn’t use generics at all, and instead just used Object for everything. It’s you’d have had to do before Java 5, along with plentiful casting and exception catching.

2 and 4 won’t compile:

error: incompatible types: inferred type does not conform to upper bound(s)

Since the two arguments to pick() share only Object as a common supertype, T becomes Object and an Object is returned and you can’t assign an Object to a String or an Integer.

3 works just fine though. Both arguments have the same type, so T is easily determined to be String. 5 works for similar reasons.

6 also works, but not because T becomes int. int is a primitive type, so it can’t be used in a generic. When attempting to resolve the generic type T, the compiler first autoboxes the primitive arguments into a ‘real’ class (Integer in this case). This also happens for 4 and 5, and even when you simply assign a literal like Integer i = 123;. The difference here is that the result (an Integer) is unboxed back to an int so that it can be assigned to i.


In your example implementation of pick(), the return value should have the same type as the second parameter. If your API specifies that the result is always derived primarily from that parameter, you could use two generic types:

static <T, U> T pick(U a1, T a2) {
    return a2;
}

With this addition, 2 still fails to compile, but 4 works as you’d expect.

这篇关于Java通用方法不起作用-参数不受限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆