Understanding upper and lower bounds on ? in Java Generics
我真的很难理解通配符参数。关于这个我有几个问题。
我理解EDOCX1的上界(0)。
在我出错的地方纠正我。
简而言之,只有
1 2 3 | public void printAll(MyList<? super MyClass>){ // code code code } |
根据Ivor Horton的书,
所以,假设
1 2 3 |
号
然后,如果1。清单中有
所以,在阅读了这个问题的许多答案之后,我的理解是:
? as a type parameter can only be used in methods. eg:printAll(MyList extends Serializable>) I cannot define classes with? as type parameter.
在通配符(
的方法,也可以作为参数的类的类型,例如:
1 | static <T extends Serializable> void printAll(MyList<T> myList) |
I understand the upper bound on
? .printAll(MyList extends Serializable>) means printAll will print MyList if it has objects that implement the Serialzable interface
更准确的均值,它将编译
I have a bit of an issue with the
super .printAll(MyList super MyClass>) means printAll will print MyList if it has objects of MyClass or any class which extends MyClass (the descendants of MyClass)
这是一
So, say if MyClass looks like:
1
2
3then, printAll() will print if
There are objects of MyClass in the list There are objects of Thread or ActionListener in the list
你是在正确的轨道。但我想说:"如果有,它将打印对象)是problematic
So, after having read the many answers to the question, here is my
understanding:
? extends T means any class which extends T. Thus, we are referring to
the children of T. Hence, T is the upper bound. The upper-most class
in the inheritance hierarchy
? super T means any class / interface which issuper of T. Thus we are
referring to all the parents of T. T is thus the lower bound. The
lower-most class in the inheritance hierarchy
关闭,但我不是说孩子
首先是
现在我们来看第一个问题:由于通配符
现在,关于第二个问题:下限为泛型方法提供了更大的灵活性。
? extends T :一种未知类型,是T 的一个子类型。? super T :一种未知类型,是T 的超类型。
小精灵
当您想要接受一个与T兼容的类型时,后者可能很有用(这样T就是-A那个类型)。这里可以找到一个实际的例子。
我们从一开始启动。
严格讲任何有效的标识符,可以使用Java的泛型类型参数,它是一个特殊类型的变化:
1 2 3 | public static final class MyGenericClass<MyGenericType> { } |
perfectly Java是有效的。
下一步,你可以使用任何你可以做
1 2 3 4 5 6 7 8 9 10 11 | public static final class MyGenericClass { private final Collection<? extends String> myThings; public MyGenericClass(Collection<? extends String> myThings) { this.myThings = myThings; } public void doStuff(final Collection<? extends String> myThings) { } } |
我们都是有效的,你不能这样做。
1 | final Collection<? extends String> myThings = new ArrayList<? extends String>(); |
当它来与这一个被称为
1 2 3 4 | final Collection<? extends Runnable> example1 = new ArrayList<Runnable>(); final Collection<? extends Runnable> example2 = new ArrayList<TimerTask>(); final Collection<? super Runnable> example3 = new ArrayList<Runnable>(); final Collection<? super Runnable> example4 = new ArrayList<Object>(); |
第一个示例演示
第二个例子证明的
嗯,你对
至于T、E、K、V或N,这些名字本身都是毫无意义的。你可以用你想要的任何东西。不过,约定建议使用单字母大写的值,t通常用于泛型方法,e用于类….
对于第一个问题:您也不能用
1 | void <?> foo() {} |
1 | void foo(List<?> e) {} |
号
你也可以为班级写作:
1 | public class Bar<E extends List<?>> { } |
使用
1 2 3 | public void printAll(MyList<? super MyClass>){ // code code code } |
。
这不会像您所说的那样打印列表"如果它有MyClass的对象"。它可以拥有属于属于MyClass父类的类的子类的任何类的对象。编译器在编译时不知道列表中的对象是什么。
为了更好地理解它,请考虑一个使用
1 2 3 | public void printAll(List<? super Float>){ // code code code } |
然后您可以使用
1 2 3 | List<Number> numbers = new ArrayList<>(); numbers.add(1); // actually only add an Integer printAll(numbers); // compiles. |
。
在这种情况下,这可能不是非常有用的。例如,当您希望将
1 2 3 | public void addFloat(List<? super Float> list){ list.add(2.5); } |
。