Java 泛型:实例化<;类型的泛型类;?超级某类,另一类<;?扩展YetAnotherClass>&燃气轮机;
在下面的代码中,我想从映射中获得一个“?super-SomeInterface”?如何声明“value”的类型以使我能够这样做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<
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类型的变量分配一个父对象或一个对象。这就是编译器禁止它的原因