繁体   English   中英

Java泛型通配符及其局限性

[英]Java Generics wildcards and their limitations

我有两个问题

我的书中说明了“如果没有上限指定了通配符,那么只能在通配符类型的值上调用Object类型的方法”

我不知道这可能是什么意思。 这是什么意思?

对于外卡类型(无界和有界)有什么限制? 例如,如果我有对MyClass<?>MyClass<? extends SomeOtherClass>的引用MyClass<? extends SomeOtherClass> MyClass<? extends SomeOtherClass> ,我不允许通过该引用调用哪些方法。 我不明白外卡允许或禁止我做什么,这可能是我不理解本书引用的原因。

我有第二部分的例子:

class SomeOtherClass
{
[...]
}

class MyClass<T>
{
[...]
}

class Test
{
     public static void main(String[] arg)
     {
         MyClass<? extends SomeOtherClass> myClass = new MyClass<String>() // for instance what does the wild card reference limit me to in any way. In a general sence.
     }
}

对于返回参数化类型对象的集合和类,通配符边界(上部和下部)通常是必需的。

你会经常听到PECS ,这意味着“制片人扩展,消费者超级” 我建议你阅读这个问题的答案 ,以避免重复答案。

  • 更准确地说,当您使用<? extends TheClass>定义通配符时 <? extends TheClass> ,然后你告诉编译器通配对象至少是类型TheClass 因此,您可以像使用TheClass的实例一样使用此对象,并调用此类型建议的任何方法。

  • 现在,当您将通配符定义为<? super TheClass> <? super TheClass> ,您告诉编译器您的通配对象类型是由TheClass类型实现或扩展的。 这意味着对象类型可能不是TheClass ,但是TheClass对象可以用作通配符引用的实例。 因此,您无法在该对象上调用任何内容,因为其类型仅在运行时已知,但您可以将该对象传递给等待通配对象的方法。

例子:

private void foo(List<?> list) {
    Object o = list.get(0); // ok
    list.add(new Object()); // won't compile!

    // you cannot add anything, and only extract Object instances
}

private void foo(List<? extends TheClass> list) {
    Object o1 = list.get(0);   // ok
    TheClass o2 = list.get(0); // ok
    list.add(new Object());    // won't compile!
    list.add(new TheClass());  // won't compile!

    // You are sure that the objects are of a subtype of TheClass,
    // so you can extract TheClass instances safely. However, you cannot
    // add anything to this list since its type is not known (may be
    // different from TheClass, so the compiler does not allow anything).
}

private void foo(List<? super TheClass> list) {
    Object o1 = list.get(0);   // ok
    TheClass o2 = list.get(0); // won't compile!
    list.add(new Object());    // won't compile!
    list.add(new TheClass());  // ok

    // You are sure that the objects are of a type implemented by TheClass,
    // so you can add any TheClass instances to the list. However, you cannot
    // extract TheClass objects since the objects type may be just implemented
    // by TheClass, but different.
}

普通通用;

ArrayList<Man> list= new ArrayList<Man>();
list.put(man); 
Man m = list.get(0);

使用带上限的通配符:

ArrayList<? extends Person> list= new ArrayList<? extends Person>();
list.put(man); //Man is a person..
Person p = list.get(0);

使用通配符:

ArrayList<?> list= new ArrayList<?>();
list.put(man);
Object o = list.get(0);

如果使用通配符,则无法知道ArrayList的泛型类型,因此您只能从列表中获取Object,这意味着您将返回使用ArrayLists,而不使用泛型。

比如你有<? 扩展MyClass>通配符。 这意味着匹配此通配符的任何类都可以是MyClass类型或其任何后代。 但由于我们唯一知道它是MyClass的后代,我们只能保证MyClass类可用的方法可以调用。

对于带有bo上限<?>的通配符,上限将是Object类。 这意味着我们所知道的是该类扩展了Object,因此只有保证在此类中存在的方法才是在Object类中定义的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM