我对Java泛型如何处理继承/多态性感到困惑.
假设以下层次结构 -
动物(父母)
狗 - 猫(儿童)
所以假设我有一个方法doSomething(List<Animal> animals).根据所有继承和多态的规则,我会假设a List<Dog> 是 a List<Animal>而a List<Cat> 是 a List<Animal>- 所以任何一个都可以传递给这个方法.不是这样.如果我想实现这种行为,我必须明确告诉该方法接受一个Animal的任何子类的列表doSomething(List<? extends Animal> animals).
我知道这是Java的行为.我的问题是为什么?为什么多态通常是隐含的,但是当涉及泛型时必须指定它?
我在阅读泛型时遇到了PECS(制片extends人和消费者的super简称).
能否给我一个人解释如何使用佩奇之间解决困惑extends和super?
让我们首先考虑一个简单的场景(请参阅ideone.com上的完整源代码):
import java.util.*;
public class TwoListsOfUnknowns {
static void doNothing(List<?> list1, List<?> list2) { }
public static void main(String[] args) {
List<String> list1 = null;
List<Integer> list2 = null;
doNothing(list1, list2); // compiles fine!
}
}
Run Code Online (Sandbox Code Playgroud)
这两个通配符是不相关的,这就是为什么你可以doNothing用a List<String>和a 调用List<Integer>.换句话说,两者?可以指代完全不同的类型.因此,以下不编译,这是预期的(也在ideone.com上):
import java.util.*;
public class TwoListsOfUnknowns2 {
static void doSomethingIllegal(List<?> list1, List<?> list2) {
list1.addAll(list2); // DOES NOT COMPILE!!!
// The method addAll(Collection<? extends capture#1-of ?>)
// in the type List<capture#1-of …Run Code Online (Sandbox Code Playgroud) 为什么java中我们做不到:
List<List<? extends Number>> aList = new ArrayList<List<Number>>();
Run Code Online (Sandbox Code Playgroud)
即使这样也可以:
List<? extends Number> aList = new ArrayList<Number>();
Run Code Online (Sandbox Code Playgroud)
编译器错误消息是:
Type mismatch: cannot convert from ArrayList<List<Number>> to List<List<? extends Number>>
我有一个通用接口interface ListList<E> extends List<List<E>>。由于某些原因,我无法转换ListList<? super T>为List<List<? super T>>。有什么办法可以做到,为什么不起作用?
至此,我已经尝试了以下方法:
ListList<? super T>给List<? extends List<? super T>>(1),但是当我尝试分配ListList<? super T>给List<List<? super T>>我Incompatible types时,出现编译时错误(1.1)。Incompatible types编译时错误(2),它不起作用。ListList,它可以正常工作(3),但我不喜欢原始类型。ListList<? super T>到中List<? extends List<? super T>>,它可以正常工作(4),但是我需要一个更通用的解决方案,该解决方案不仅适用于ListList<E>,而且适用于任何通用类型。这是我的代码:
ListList<? super T> var = new ArrayListList<>();
List<? extends List<? super T>> work = var; // (1)
List<List<? super T>> notWork = …Run Code Online (Sandbox Code Playgroud) Java通过<? extends class>过滤可用于在这种情况下构建新HashMap的Java类的方式为我提供了一种方法,例如:
我可以这样做:
Map<String,? extends Serializable> map1 = new HashMap<String,String>();
Run Code Online (Sandbox Code Playgroud)
没错,因为String实现了Serializable,所以编译器让我做到了。
但是当我尝试这样做时:
Map<String,GenericClass<? extends Serializable>> map2 = new HashMap<String, GenericClass<String>>();
Run Code Online (Sandbox Code Playgroud)
作为GenericClass:
public class GenericClass<T>
{
.
.
.
}
Run Code Online (Sandbox Code Playgroud)
编译器抛出错误说:
Type mismatch: cannot convert from HashMap<String,GenericClass<String>> to Map<String,GenericClass<? extends Serializable>>
Run Code Online (Sandbox Code Playgroud)
我想知道怎么回事?
也许编译器无法检测到extended类是泛型类型的一部分。
我在我的项目中创建了一个工厂类,它允许我(理论上)为任何(支持的)给定类型创建管理器.与管理器交互允许我改变给定类型的某些属性.我面临的问题是当我尝试为泛型类型创建一个管理器时,编译器会破坏我的希望和梦想.
以下代码是我正在使用的精简版本.我尝试创建'test3Manager'的行不会编译,我试图理解为什么会这样.它下面的行显示了一个'解决方法',我试图避免.
import java.util.List;
public class GenTest {
public static void main(String[] args) {
String test1 = "";
IRandomType<String> test2 = null;
IAnotherRandomType<?> test3 = null;
IManager<String> test1Manager = Factory.createManager(test1);
IManager<IRandomType<String>> test2Manager = Factory.createManager(test2);
IManager<IAnotherRandomType<?>> test3Manager = Factory.createManager(test3); // Doesn't compile. Why?
// Work around?
IManager<?> test3ManagerTmp = Factory.createManager(test3);
IManager<IAnotherRandomType<?>> test3Manager2 = (IManager<IAnotherRandomType<?>>) test3ManagerTmp;
}
public interface IRandomType<T> {}
public interface IAnotherRandomType<T> {}
public interface IManager<T> {}
public static class Factory {
public static <T> IManager<T> createManager(T object) {
return …Run Code Online (Sandbox Code Playgroud) 我想知道这段代码有什么问题:
Map <? extends String, ? extends Integer> m = null;
Set<Map.Entry<? extends String, ? extends Integer>> s = m.entrySet();
Run Code Online (Sandbox Code Playgroud)
编译器抱怨错误消息:
类型不匹配:无法转换
Set<Map.Entry<capture#1-of ? extends String,capture#2-of ? extends Integer>>为Set<Map.Entry<? extends String,? extends Integer>>
应该是什么类型的s?Eclipse建议,Set<?>但我想尝试更具体.
generics ×8
java ×8
wildcard ×3
casting ×1
extends ×1
hashmap ×1
inheritance ×1
lower-bound ×1
pecs ×1
polymorphism ×1
serializable ×1
super ×1