Java 泛型:实例化<;类型的泛型类;?超级某类,另一类<;?扩展YetAnotherClass>&燃气轮机;

Java 泛型:实例化<;类型的泛型类;?超级某类,另一类<;?扩展YetAnotherClass>&燃气轮机;,java,generics,Java,Generics,在下面的代码中,我想从映射中获得一个“?super-SomeInterface”?如何声明“value”的类型以使我能够这样做 class SomeClass { /* override hashCode & equals appropriately */} interface SomeInterface<T> { } interface AnotherInterface { } class MainClass { private final Map<

在下面的代码中,我想从映射中获得一个“?super-SomeInterface”?如何声明“value”的类型以使我能够这样做

class SomeClass { /* override hashCode & equals appropriately */}
interface SomeInterface<T> { }
interface AnotherInterface { }


class MainClass {
       private final Map<SomeClass, ? super SomeInterface<? extends AnotherInterface>> someMap;
       private final SomeClass someClass = new SomeClass();

       public MainClass() {
          someMap = new HashMap<SomeClass, SomeInterface<? extends AnotherInterface>>();
          someMap.put(someClass, new SomeInterface<AnotherInterface>(){});
       }

       private void getValue(SomeClass someClass) {
          /*
           * I want to get a "? super SomeInterface<? extends AnotherInterface>" from the Map
           * how do I declare the type of "value" to enable me to do so
           * 
           */
          Object value = someMap.get(someClass);
       }

       private
       <T extends SomeInterface<? extends AnotherInterface>>
       T getValue2(SomeClass someClass) {
          T value;
          // the code below does not work
          // Type mismatch: cannot convert from capture#3-of
          // ? super SomeInterface<? extends AnotherInterface> to T
          value = someMap.get(someClass);
        }
    }
class SomeClass{/*覆盖hashCode&equals*/}
接口{}
接口另一个接口{}
类主类{

private final Map对于
getValue2
方法,编译器无法保证提供的密钥将映射到该特定类型
T
(无论调用方期望什么)。这是因为映射的值是使用通配符声明的,并且无法确保为您的
getValue2
方法指定了任意的
?super-SomeInterface,编译器无法保证提供的键将映射到该特定类型
T
(无论调用方期望什么)这是因为映射的值是使用通配符声明的,并且无法确保任意的
?super-SomeInterface
对象
是唯一可以声明
为的对象,因为如果您有一个
?super-Anything
它可以是
Anything
的任何超类,一直到O因此,必须将其指定给最通用的类型


如果您有一个生成
对象的泛型类型
是唯一可以将
声明为的对象,因为如果您有一个
?super Anything
,它可以是
Anything
的任何超类,一直到对象。因此,您必须将它指定给最通用的类型


如果您有一个生成
的泛型类型,让我们尝试另一种方法。我将接口替换为类,因为我认为这有助于澄清一些问题。我还对它们进行了扩展,以演示一个示例

class SomeClass { /* override hashCode & equals appropriately */ }
class Parent { }    
class Child extends Parent { }

class MainClass {

    private final Map<SomeClass, ? super Child> someMap;
    private final SomeClass someClass = new SomeClass();

    public MainClass() {
        someMap = new HashMap<SomeClass, Child>();     // #1
        // someMap = new HashMap<SomeClass, Parent>(); // #2 , also valid
        // someMap = new HashMap<SomeClass, Object>(); // #3 , also valid
        someMap.put(someClass, new Child());     // #4
        // someMap.put(someClass, new Parent()); // #5 error
        // someMap.put(someClass, new Object()); // #6 error
    }

    private void getValue(SomeClass someClass) {

        Object value = someMap.get(someClass);
    }

    private <T extends Child> T getValue2(SomeClass someClass) {
        // error
        T value = someMap.get(someClass);
    }
}
因此,值的类型可以是Child、Parent或Object。但编译器不知道,因为泛型是通过类型擦除实现的。因此,如果实际类型是Child,而您要放置一个Parent,那么这将不起作用

get()如下所示:

? super Child java.util.Map.get(Object key)

现在来看最难的部分。同样,您不知道这是什么实际类型。如上所述,可以使用#1、#2或#3。如果您使用#2或#3,并且您希望返回类型至少是Child,那么您将为Child类型的变量分配一个父对象或一个对象。这就是编译器禁止它的原因。

让我们尝试另一种方法。我替换它d类的接口,因为我认为这有助于澄清一些问题。我还对它们进行了扩展,以演示一个示例

class SomeClass { /* override hashCode & equals appropriately */ }
class Parent { }    
class Child extends Parent { }

class MainClass {

    private final Map<SomeClass, ? super Child> someMap;
    private final SomeClass someClass = new SomeClass();

    public MainClass() {
        someMap = new HashMap<SomeClass, Child>();     // #1
        // someMap = new HashMap<SomeClass, Parent>(); // #2 , also valid
        // someMap = new HashMap<SomeClass, Object>(); // #3 , also valid
        someMap.put(someClass, new Child());     // #4
        // someMap.put(someClass, new Parent()); // #5 error
        // someMap.put(someClass, new Object()); // #6 error
    }

    private void getValue(SomeClass someClass) {

        Object value = someMap.get(someClass);
    }

    private <T extends Child> T getValue2(SomeClass someClass) {
        // error
        T value = someMap.get(someClass);
    }
}
因此,值的类型可以是Child、Parent或Object。但编译器不知道,因为泛型是通过类型擦除实现的。因此,如果实际类型是Child,而您要放置一个Parent,那么这将不起作用

get()如下所示:

? super Child java.util.Map.get(Object key)
现在来看最难的部分。同样,您不知道这是什么实际类型。如上所述,可以使用#1、#2或#3。如果您使用#2或#3,并且您希望返回类型至少是Child,那么您将为Child类型的变量分配一个父对象或一个对象。这就是编译器禁止它的原因