当前位置: 代码迷 >> java >> 泛型:如何捕获通配符?
  详细解决方案

泛型:如何捕获通配符?

热度:88   发布时间:2023-07-27 09:15:35.0

不,这个问题不是关于它们之间的区别吗? 和T; 这是关于我如何变成<? >参数命名为<T>。 考虑这个示例代码:

import java.io.Serializable;

class A<T extends Serializable> {
    <S extends Serializable> void bar(S arg) { }
    void bar2(T arg) { }
}

public class B {
    A<? extends Serializable> myA = null;    
    <T extends Serializable> void foo(T arg) {
        myA.bar(arg);
        myA.bar2(arg);
    }
}

我的问题是上面没有编译的事实; 对bar2()的调用给了我

The method bar2(capture#2-of ? extends Serializable) in the type
A<capture#2-of ? extends Serializable> is not applicable for the arguments (T)

我猜这个“原因”是myA是<? extends Serializable> ; 但B.foo中的T ......很好,一个名叫T; 而不是通配符?

“修复”这种方法的一种方法是使<T extends Serializable>为B类的类型参数...但这基本上与我对该类的其他用法冲突。 含义:我最终写下了B及其成员myA,这完全是因为我不想参数化B类。 所以,我开始只使用bar2()方法; 然后稍后添加了bar()......但这并没有真正帮助。

那么 - 有没有办法让我的班级B在我的示例代码中使用A.bar2()作为“预期”?

编辑:而且确切地说 - bar()方法对我没有帮助; 因为那里的“S”......与我在A班中真正使用的“T”不兼容。

你走到了尽头。

A<? extends Serializable> myA = ...;

所以myAA的未知的东西。 它可以是A<String> ,或A<Integer>A<Banana> 你只是不知道。 让我们说这是一个A<Banana>

<T extends Serializable> void foo(T arg) {

所以foo()接受任何可序列化的:String,Integer,Banana,Apple,等等。 假设它以Integer作为参数调用。

myA.bar2(arg);

因此,基于上面的假设,虽然myAA<Banana> ,但它会调用bar2()并将Integer作为参数。 编译器无法接受这一点:它显然不是类型安全的。 B必须是通用的。

@JBNizet已经解释了为什么不能这样做。 这个答案旨在解释你可能有的选择(其中一个在你的问题中正确指出,但这不是唯一的选择)。

使B采用类型参数

class B<T extends Serializable> {

    A<T> myA = null;    

    void foo(T arg) {
        myA.bar(arg);
        myA.bar2(arg);
    }
}

使B从A延伸(如果B通过A的a-a测试)

class B extends A<String> {

    public void foo(String arg) {
        bar2(arg);
        bar(1);
    }
}

两个选项之间的区别在于:1) barbar2需要传递相同的类型,其中2) barbar2可以传递不同的类型,因为bar2由为A声明的类型参数绑定,其中bar是由为方法声明的类型参数绑定。

  相关解决方案