相关疑难解决方法(0)

List <Dog>是List <Animal>的子类吗?为什么Java泛型不是隐式多态的?

我对Java泛型如何处理继承/多态性感到困惑.

假设以下层次结构 -

动物(父母)

- (儿童)

所以假设我有一个方法doSomething(List<Animal> animals).根据所有继承和多态的规则,我会假设a List<Dog> a List<Animal>而a List<Cat> a List<Animal>- 所以任何一个都可以传递给这个方法.不是这样.如果我想实现这种行为,我必须明确告诉该方法接受一个Animal的任何子类的列表doSomething(List<? extends Animal> animals).

我知道这是Java的行为.我的问题是为什么?为什么多态通常是隐含的,但是当涉及泛型时必须指定它?

java generics polymorphism inheritance

727
推荐指数
10
解决办法
10万
查看次数

泛型方法上的多个通配符使Java编译器(和我!)非常混淆

让我们首先考虑一个简单的场景(请参阅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 generics compiler-errors wildcard

58
推荐指数
1
解决办法
7197
查看次数

Java通用列表<List <?扩展数>>

为什么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>>

java generics

39
推荐指数
2
解决办法
2万
查看次数

不兼容的类型和新的类型变量

我得到以下编译消息:

[javac]   ... error: incompatible types
[javac]         exceptionClassHolder = new Holder<>( (new Exception()).getClass() );
[javac]                                ^
[javac]   required: Holder<Class<? extends Exception>>
[javac]   found:    Holder<Class<CAP#1>>
[javac]   where CAP#1 is a fresh type-variable:
[javac]     CAP#1 extends Exception from capture of ? extends Exception
[javac] 1 error
Run Code Online (Sandbox Code Playgroud)

在我看来,根据信息所有应该是正确的.CAP#1确实扩展了Exception.那么如何理解上述信息呢?下面的SSCCE(最初没有发布,因为我希望在一般情况下理解错误消息本身):

class Holder<T> {
    public T t;
    public Holder(T t) {
       this.t = t;
    }
}

public class FooMain {
    public static void main(String args[]) throws Exception {
        Holder<Class<? extends Exception>> exceptionClassHolder;
        exceptionClassHolder = …
Run Code Online (Sandbox Code Playgroud)

java generics

14
推荐指数
1
解决办法
1万
查看次数

带有Java泛型的双通配符参数化(嵌套通配符)

我正在使用来自第三方库(Reflection)的方法,该方法应该找到给定类型的子类型并且看起来像

public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) {
...
Run Code Online (Sandbox Code Playgroud)

当调用者代码看起来像

Class<?> type = ...
Set<Class<?>> subTypes = reflections.getSubTypesOf(type);
Run Code Online (Sandbox Code Playgroud)

我收到编译错误:" cannot convert from Set<Class<? extends capture#19-of ?>> to Set<Class<?>>".以下修复了这种情况:

Class<?> type = ...
Set<?> subTypes = reflections.getSubTypesOf(ht);
Run Code Online (Sandbox Code Playgroud)

所以看起来不正确的唯一可能的补救措施Set<Class<? extends ?>>Set<?>,但不是Set<Class<?>>.为什么会这样?谢谢你对此有任何解释.

java generics

6
推荐指数
1
解决办法
1050
查看次数

有界通配符相关的编译器错误

我想知道这段代码有什么问题:

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<?>但我想尝试更具体.

java generics bounded-wildcard

3
推荐指数
1
解决办法
1246
查看次数

不兼容的通配符类型

这个问题之后,它提供了一个解决方案,但没有解释它(不幸的是,答案中的链接现在已经死了):

采取以下方法:

void method(Map<?, ?> myMap) {
    Set<Map.Entry<?, ?>> set = myMap.entrySet();
    ...
}
Run Code Online (Sandbox Code Playgroud)

简单,不是吗?但是,这无法在jdk1.7.0_25上编译:

incompatible types
required: java.util.Set<java.util.Map.Entry<?,?>>
found:    java.util.Set<java.util.Map.Entry<capture#1 of ?,capture#2 of ?>>
Run Code Online (Sandbox Code Playgroud)

WTF?Map.entrySet()被指定为返回一个类型的对象Set<Map.Entry<K, V>>,所以在上面的例子中,myMap.entrySet()返回一个Set<Map.Entry<?, ?>>.但它不编译!

甚至更奇怪,从顶部的链接问题,将方法更改为this使其编译:

void method(Map<?, ?> myMap) {
    Set<? extends Map.Entry<?, ?>> set = myMap.entrySet();
    ...
}
Run Code Online (Sandbox Code Playgroud)

跆拳道??? 呼叫entrySet上的Map<?, ?>回报Set<Map.Entry<K, V>>,这是不能被分配给类型的变量Set<Map.Entry<K, V>>,但它可以以类型的变量Set<? extends Map.Entry<K, V>>?????

任何人都可以了解这里发生的事情吗?这是否意味着,每当我使用至少2级深度的通配符类型编写方法时,我必须记得将它? extends ...放在某处?

java generics wildcard unbounded-wildcard

3
推荐指数
1
解决办法
1674
查看次数