相关疑难解决方法(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万
查看次数

什么是PECS(制作人扩展消费者超级)?

我在阅读泛型时遇到了PECS(制片extends人和消费者的super简称).

能否给我一个人解释如何使用佩奇之间解决困惑extendssuper

java generics super pecs bounded-wildcard

680
推荐指数
11
解决办法
9万
查看次数

泛型方法上的多个通配符使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:通配符类型不匹配导致编译错误

我在我的项目中创建了一个工厂类,它允许我(理论上)为任何(支持的)给定类型创建管理器.与管理器交互允许我改变给定类型的某些属性.我面临的问题是当我尝试为泛型类型创建一个管理器时,编译器会破坏我的希望和梦想.

以下代码是我正在使用的精简版本.我尝试创建'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)

java generics wildcard

5
推荐指数
1
解决办法
1005
查看次数

如何编写一个接受任何扩展Throwable类的集合的方法?

我想传递一个扩展Throwable到方法的类的集合.但是,我的尝试无法使用jdk1.6.0_39在Netbeans中编译:

package com.memex.sessionmanager;

import java.util.Collection;
import java.util.Collections;

public class GenericsDemo
{
    public void foo(Collection<Class<? extends Throwable>> c)
    {
    }

    public void bar()
    {
        foo(Collections.singleton(RuntimeException.class));
    }
}
Run Code Online (Sandbox Code Playgroud)

编译说foo(java.util.Collection<java.lang.Class<? extends java.lang.Throwable>>) in com.memex.sessionmanager.GenericsDemo cannot be applied to (java.util.Set<java.lang.Class<java.lang.RuntimeException>>).

我可以通过将调用代码更改为:

foo(Collections.<Class<? extends Throwable>>singleton(RuntimeException.class));
Run Code Online (Sandbox Code Playgroud)

但我宁愿不强迫客户写这个钝的泛型类型.是否有可能编写一个方法,它将采用哪种类的子类型Throwable

编辑:

有人用方法签名修复了上面的例子:

public <T extends Throwable> void foo(Collection<Class<T>> c) {}
Run Code Online (Sandbox Code Playgroud)

但是我现在在使用参数时遇到了问题.具体来说,我想将它分配给一个字段,如下所示:

package com.memex.sessionmanager;

import java.util.Collection;
import java.util.Collections;

public class GenericsDemo
{

    private Collection<Class<? extends Throwable>> throwables;

    public <T extends Throwable> …
Run Code Online (Sandbox Code Playgroud)

java generics

4
推荐指数
1
解决办法
769
查看次数

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

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

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
查看次数

创建一个通用类列表

我有一个实用程序方法,可以从某些对象中创建一个元素列表:

public static final <T> List<T> list(T t) {
    final List<T> rv = new ArrayList<>();
    rv.add(t);
    return rv;
}
Run Code Online (Sandbox Code Playgroud)

我也有一个接受type参数的方法List<Class<?>>。因此,我必须创建该类型的对象。这是我尝试做的事情:

final Class<?> aClass = Integer.class;
final List<Class<?>> trivialListOfClasses = list(aClass);
Run Code Online (Sandbox Code Playgroud)

……这失败了:

[javac] /some/path/Foo.java:41: error: incompatible types
[javac]             final List<Class<?>> trivialListOfClasses = list(aClass);
[javac]                                                                  ^
[javac]   required: List<Class<?>>
[javac]   found:    List<Class<CAP#1>>
[javac]   where CAP#1 is a fresh type-variable:
[javac]     CAP#1 extends Object from capture of ?
[javac] 1 error
Run Code Online (Sandbox Code Playgroud)

完成上述任务的正确方法是什么?我了解有关Java泛型不变的部分,但是到底发生了什么?

java generics java-7

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