相关疑难解决方法(0)

泛型 - 集合中的Java集合

我是仿制药的新手,所以不确定我哪里出错了......

我有一个名为Cat,Dog和Rabbit的类,它们实现了Animal的接口.

以下代码将编译

Set<? extends Animal> animalSet;
Set<Dog> dogSet = new HashSet<Dog>();
animalSet = dogSet;
Run Code Online (Sandbox Code Playgroud)

但是下面的代码不会

Map<String, Set<? extends Animal>> animalMap;
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();
animalMap = dogMap; // this line will not compile
Run Code Online (Sandbox Code Playgroud)

编译器说这些类型是不兼容的.我哪里错了?

UPDATE

谢谢大家的帮助

我通过添加另一个通配符更改了第一行代码以下代码将编译

Map<String, ? extends Set<? extends Animal>> animalMap;
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();
animalMap = dogMap;
Run Code Online (Sandbox Code Playgroud)

另请参阅下面的Cyrille Ka给出的解决方案 - 使用putAll()将值从dogMap传输到animalMap,而不是将dogMap分配给animalMap.

java generics collections nested

9
推荐指数
2
解决办法
274
查看次数

List <List <String >>是Collection <Collection <T >>的实例吗?

我编写了这个方便的通用函数,用于将集合集合转换为单个集合:

public static <T> Set<T> makeSet(Collection<Collection<T>> a_collection) {
    Iterator<Collection<T>> it = a_collection.iterator();
    Set<T> result = new HashSet<T>();
    while (it.hasNext()) {
        result.addAll(it.next());
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

然后我试着打电话给它:

    List<List<String>> resultLists = ... ;
    Set<String> labelsSet = CollectionsHelper.makeSet(resultLists);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

<T>makeSet(java.util.Collection<java.util.Collection<T>>) in CollectionsHelper 
cannot be applied to (java.util.List<java.util.List<java.lang.String>>)
Run Code Online (Sandbox Code Playgroud)

现在a List 是a Collection,a String 是a T.那么为什么这不起作用,我该如何解决呢?

java generics collections covariance

8
推荐指数
2
解决办法
2149
查看次数

具有上限的通配符类型变量的迭代器

大家好,我尝试扩展一个HashMap<String,String>强制执行"全小写"规则

public class HttpQueryMap extends HashMap<String,String>
{    
    ...
    @Override
    public void putAll(Map<? extends String, ? extends String> m)
    {       
        ...
        Iterator<Map.Entry<String,String>> iterator = m.entrySet().iterator();
        ...      
    }
    ... 
}
Run Code Online (Sandbox Code Playgroud)

我收到编译时错误

incompatible types
required: Iterator<Entry<String,String>>
found:    Iterator<Entry<CAP#1,CAP#2>>
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends String from capture of ? extends String
CAP#2 extends String from capture of ? extends String
Run Code Online (Sandbox Code Playgroud)

下一个解决方案可以完成这项工作,但实际上很难看:

public class HttpQueryMap extends HashMap<String,String>
{    
    ...
    @Override
    public void putAll(Map<? extends String, ? extends String> m)
    {       
        ... …
Run Code Online (Sandbox Code Playgroud)

java generics

8
推荐指数
1
解决办法
1521
查看次数

Java 7/8泛型中嵌套通配符的可赋值性差异

以下在JDK8中编译得很好,但是与JDK7 给出了不兼容的类型错误.

List<List<? extends Number>> xs = Arrays.asList(Arrays.asList(0));
Run Code Online (Sandbox Code Playgroud)

根据这个答案,List<List<? extends Number>>没有超类型的关系List<List<Integer>>.

在Java 8中改变了什么使得这个任务有效?我也有一个很难理解为什么它不会在Java 7的工作.


这两个语句使用JDK7编译时没有类型错误:

List<? extends Number> xs = Arrays.asList(0);
List<? extends List<? extends Number>> ys = Arrays.asList(Arrays.asList(0));
Run Code Online (Sandbox Code Playgroud)

对我来说,这两个都在JDK7中工作似乎非常不直观,但上面的原始示例却没有.所有这些当然都适用于JDK8.我想要真正理解这里发生了什么,我需要理解为什么这些例子在Java 7中是合法的,但原始的例子却不是.

java generics java-8 bounded-wildcard

8
推荐指数
1
解决办法
430
查看次数

为什么不允许转换为"GenericType <?>"?

此代码导致javac编译错误(但值得注意的是,不是Eclipse 4.2.2!):

public interface Foo<T> {
}

class Bar<T> implements Foo<Iterable<T>> {
}

class Test {
    void test(Foo<? extends Iterable<? extends String>> foo) {
        Bar<?> bar = (Bar<?>) foo;
    }
}
Run Code Online (Sandbox Code Playgroud)

来自javac的错误是这样的:

Foo.java:9: error: inconvertible types
        Bar<?> bar = (Bar<?>) foo;
                              ^
  required: Bar<?>
  found:    Foo<CAP#1>
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Iterable<? extends String> from capture of ? extends Iterable<? extends String>
Run Code Online (Sandbox Code Playgroud)

将转换更改为(Bar) foo(即使用原始类型)允许代码编译,就像更改类型一样foo简单Foo<? extends Iterable<?>>.

编辑:非常有趣,这个简单的改变导致Eclipse拒绝,但javac接受:

void test(Foo<Iterable<String>> foo) { …
Run Code Online (Sandbox Code Playgroud)

java eclipse generics

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

带有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 &lt;String,Class &lt;的声明有问题吗?扩展可序列化&gt;&gt;

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类是泛型类型的一部分。

java generics extends hashmap serializable

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

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

嵌套通配符

发现了有关使我烦恼的无限制通配符的事实。例如:

public class Test {

      private static final Map<Integer, Map<Integer, String>> someMap = new HashMap<>();

      public static void main(String[] args) {
         getSomeMap();
      }

      static Map<?, Map<?, ?>> getSomeMap() {
         return someMap;  //compilation fails
      }
}
Run Code Online (Sandbox Code Playgroud)

尽管可以使用Map<?, ?>Map<?, Map<Integer, String>>返回类型,但失败。

有人可以告诉我确切原因吗?提前致谢。


更新资料

我认为,对于此问题,我似乎理解并最简单的解释(忽略所有这些复杂的规则)是Capture Conversion(link)中的最后一个注释:Capture conversion is not applied recursively.

java generics wildcard

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

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

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

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

将元素添加到wildchar列表会导致编译错误

我有一个列表包含未来的任务,未来的类型是未知的,所以我创建一个带通配符类型的列表?,但是当我向列表中添加一个元素时,就会发生编译错误.

这是代码:

private List<Pair<String, Future<?>>> futureTasks = Collections.synchronizedList(
        new ArrayList<Pair<String, Future<?>>>(8));

// taskId is a string
futureTasks.add(Pair.makePair(taskId, getExecutors().submit(
    new Callable<String>() {
        public String call() {
            try {
                return exportAccountSrcTask(tmpFile); // return a string
            } catch (Exception e) {
                logger.error("failed to export account src", e);
            }
            return null;
    }}))
);
Run Code Online (Sandbox Code Playgroud)

编译错误:

add(Pair<String,Future<?>>)类型中的方法List<Pair<String,Future<?>>>不适用于参数(Pair<String,Future<String>>)

java generics

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

通用方法与通配符 - 编译错误

我有一个问题(简化):

public void method(List<List<?>> list){...}
Run Code Online (Sandbox Code Playgroud)

调用时给出了一个编译错误:

method(new ArrayList<List<String>>()); // This line gives the error
Run Code Online (Sandbox Code Playgroud)

在阅读了类似的线程之后,我明白如果我将方法签名重写为:

public void method(List<? extends List<?>> list){...}
Run Code Online (Sandbox Code Playgroud)

现在,我的问题是,为什么以下工作呢?

public <T> void method(List<List<T>> list){...}
Run Code Online (Sandbox Code Playgroud)

java generics

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