Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么可以';t我使用一个实现列表的类<;X>;其中一个列表<;X>;预计会发生什么?_Java_Generics - Fatal编程技术网

Java 为什么可以';t我使用一个实现列表的类<;X>;其中一个列表<;X>;预计会发生什么?

Java 为什么可以';t我使用一个实现列表的类<;X>;其中一个列表<;X>;预计会发生什么?,java,generics,Java,Generics,首先是简单案例(A): PsList.java package com.foo; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public class PsList implements List<Ps> { @Override public int size() {

首先是简单案例(A):

PsList.java

package com.foo;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class PsList implements List<Ps>
{
    @Override
    public int size()
    {
        return 0;
    }

    @Override
    public boolean isEmpty()
    {
        return false;
    }

    @Override
    public boolean contains(Object o)
    {
        return false;
    }

    @Override
    public Iterator<Ps> iterator()
    {
        return null;
    }

    @Override
    public Object[] toArray()
    {
        return new Object[0];
    }

    @Override
    public <T> T[] toArray(T[] a)
    {
        return null;
    }

    @Override
    public boolean add(Ps ps)
    {
        return false;
    }

    @Override
    public boolean remove(Object o)
    {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c)
    {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends Ps> c)
    {
        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends Ps> c)
    {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c)
    {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c)
    {
        return false;
    }

    @Override
    public void clear()
    {
    }

    @Override
    public Ps get(int index)
    {
        return null;
    }

    @Override
    public Ps set(int index, Ps element)
    {
        return null;
    }

    @Override
    public void add(int index, Ps element)
    {
    }

    @Override
    public Ps remove(int index)
    {
        return null;
    }

    @Override
    public int indexOf(Object o)
    {
        return 0;
    }

    @Override
    public int lastIndexOf(Object o)
    {
        return 0;
    }

    @Override
    public ListIterator<Ps> listIterator()
    {
        return null;
    }

    @Override
    public ListIterator<Ps> listIterator(int index)
    {
        return null;
    }

    @Override
    public List<Ps> subList(int fromIndex, int toIndex)
    {
        return null;
    }
}
package com.foo;
导入java.util.Collection;
导入java.util.Iterator;
导入java.util.List;
导入java.util.ListIterator;
公共类PsList实现列表
{
@凌驾
公共整数大小()
{
返回0;
}
@凌驾
公共布尔值为空()
{
返回false;
}
@凌驾
公共布尔包含(对象o)
{
返回false;
}
@凌驾
公共迭代器迭代器()
{
返回null;
}
@凌驾
公共对象[]toArray()
{
返回新对象[0];
}
@凌驾
公共T[]toArray(T[]a)
{
返回null;
}
@凌驾
公共布尔加法(Ps)
{
返回false;
}
@凌驾
公共布尔删除(对象o)
{
返回false;
}
@凌驾
公共布尔容器(集合c)
{
返回false;
}
@凌驾
公共布尔addAll(集合c)
{
返回false;
}
@凌驾
公共布尔保留(集合c)
{
返回false;
}
@凌驾
公共空间清除()
{
}
@凌驾
公共Ps get(整数索引)
{
返回null;
}
@凌驾
公共Ps集(整数索引,Ps元素)
{
返回null;
}
@凌驾
公共void添加(int索引,Ps元素)
{
}
@凌驾
公共Ps删除(整型索引)
{
返回null;
}
@凌驾
public int indexOf(对象o)
{
返回0;
}
@凌驾
公共int lastIndexOf(对象o)
{
返回0;
}
@凌驾
公共ListIterator ListIterator()
{
返回null;
}
@凌驾
公共ListIterator ListIterator(int索引)
{
返回null;
}
@凌驾
公共列表子列表(int fromIndex、int toIndex)
{
返回null;
}
}
OtherService.java

package com.foo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class OtherService
{
    private void doSomething(Map<String, List<Ps>> map, Boolean custom)
    {
        if (custom)
        {
            map.put("someValue", new PsList());
        } else {
            map.put("someValue", new ArrayList<>());
        }
    }

    private void callDoSomethingNotCustom()
    {
        Map<String, List<Ps>> map = new HashMap<>();
        doSomething(map, false);
    }

    private void callDoSomethingCustom()
    {
        Map<String, PsList> map = new HashMap<String, PsList>();
        // map is not the right format
        doSomething(map, true);
    }
}
package com.foo;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
公共服务
{
私有void doSomething(映射、布尔自定义)
{
如果(自定义)
{
put(“someValue”,new PsList());
}否则{
put(“someValue”,newArrayList());
}
}
私有void callDoSomethingNotCustom()
{
Map Map=newhashmap();
doSomething(地图,假);
}
私有void callDoSomethingCustom()
{
Map Map=newhashmap();
//地图的格式不正确
doSomething(地图,真实);
}
}
错误的第一个参数类型。找到:“java.lang.String,com.foo.PsList>”,必需:“java.util.Map>”


你绝对可以做到。以下是一个例子:

public class MyClass {

    static interface FooList<T> {}
    static class Ps {}

    static void doSomething(FooList<Ps> list) { }

    static class PsList implements FooList<Ps> { }

    public static void main(String[] args)
    {
        FooList psList = new PsList();

        doSomething(psList);

        System.out.println("HelloWorld!");
    }
}
公共类MyClass{
静态接口傻瓜{}
静态类Ps{}
静态void doSomething(愚人列表){}
静态类PsList实现愚人{}
公共静态void main(字符串[]args)
{
傻瓜psList=新psList();
剂量测定法(psList);
System.out.println(“HelloWorld!”);
}
}

请参阅演示。

正如您似乎在提问的中途意识到的那样,您的问题不在于
List
是否可以与
PsList
互换

问题是您无法添加到
地图

让我们考虑一个更简单的例子:

void doSomething(Map<String, ? extends Number> map) {
    map.put(String, Integer.valueOf(0));    // Not allowed.
}
实际上,您不能向类型为上限通配符的映射或集合添加任何内容,因为无法知道这样做是否正确和安全

在您的情况下,最简单的解决方案是删除通配符:

private void doSomething(Map<String, List<Ps>> map, boolean custom) {
    // ...
    map.put("stringValue", custom ? new PsList() : new ArrayList<Ps>());
}

请你提供一份清单好吗?如果它完全如您所示,我希望它能在您问题的第一部分工作。无法重现错误:
doSomething(psList)
必须并且编译得很好。您使用的是什么版本的Java?我突然意识到,无论在其中创建了什么,我都需要传递相同类型的映射。private void callDoSomethingCustom(){Map Map=new HashMap();doSomething(Map,true);}值得进一步编辑您的问题,因为问题的第一部分(您声称不能将
PsList
作为
List
传递)是不真实的-仅当您将其用作泛型类型参数时才是如此(在
Map
)中)您遇到了问题。(这就是为什么从一开始就提供一个解决方案是如此重要。)感谢您的帮助,这有助于了解到底发生了什么。我肯定为我节省了一些时间。:-)
? extends List<Ps> list = new ArrayList<>();
? extends List<Ps> psList = new PsList();
map.put("string", custom ? psList : list);
package com.foo;

public class Ps
{
}
package com.foo;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class PsList implements List<Ps>
{
    @Override
    public int size()
    {
        return 0;
    }

    @Override
    public boolean isEmpty()
    {
        return false;
    }

    @Override
    public boolean contains(Object o)
    {
        return false;
    }

    @Override
    public Iterator<Ps> iterator()
    {
        return null;
    }

    @Override
    public Object[] toArray()
    {
        return new Object[0];
    }

    @Override
    public <T> T[] toArray(T[] a)
    {
        return null;
    }

    @Override
    public boolean add(Ps ps)
    {
        return false;
    }

    @Override
    public boolean remove(Object o)
    {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c)
    {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends Ps> c)
    {
        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends Ps> c)
    {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c)
    {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c)
    {
        return false;
    }

    @Override
    public void clear()
    {
    }

    @Override
    public Ps get(int index)
    {
        return null;
    }

    @Override
    public Ps set(int index, Ps element)
    {
        return null;
    }

    @Override
    public void add(int index, Ps element)
    {
    }

    @Override
    public Ps remove(int index)
    {
        return null;
    }

    @Override
    public int indexOf(Object o)
    {
        return 0;
    }

    @Override
    public int lastIndexOf(Object o)
    {
        return 0;
    }

    @Override
    public ListIterator<Ps> listIterator()
    {
        return null;
    }

    @Override
    public ListIterator<Ps> listIterator(int index)
    {
        return null;
    }

    @Override
    public List<Ps> subList(int fromIndex, int toIndex)
    {
        return null;
    }
}
package com.foo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class OtherService
{
    private void doSomething(Map<String, List<Ps>> map, Boolean custom)
    {
        if (custom)
        {
            map.put("someValue", new PsList());
        } else {
            map.put("someValue", new ArrayList<>());
        }
    }

    private void callDoSomethingNotCustom()
    {
        Map<String, List<Ps>> map = new HashMap<>();
        doSomething(map, false);
    }

    private void callDoSomethingCustom()
    {
        Map<String, PsList> map = new HashMap<String, PsList>();
        // map is not the right format
        doSomething(map, true);
    }
}
public class MyClass {

    static interface FooList<T> {}
    static class Ps {}

    static void doSomething(FooList<Ps> list) { }

    static class PsList implements FooList<Ps> { }

    public static void main(String[] args)
    {
        FooList psList = new PsList();

        doSomething(psList);

        System.out.println("HelloWorld!");
    }
}
void doSomething(Map<String, ? extends Number> map) {
    map.put(String, Integer.valueOf(0));    // Not allowed.
}
void doSomething(Map<String, ? extends Number> map) {
    // Not allowed.  The caller might have passed a Map<String, Double>.
    map.put(String, Integer.valueOf(0));

    // Not allowed.  The caller might have passed a Map<String, Integer>.
    map.put(String, Double.valueOf(0));

    // Not allowed.  The caller might have passed a Map<String, Integer>
    // or Map<String, Double>.  This method has no way of knowing what the
    // actual restriction is.
    Number someNumber = generateNewNumber();
    map.put(String, someNumber);
}
private void doSomething(Map<String, List<Ps>> map, boolean custom) {
    // ...
    map.put("stringValue", custom ? new PsList() : new ArrayList<Ps>());
}
private <L extends List<Ps>> void doSomething(Map<String, L> map,
                                              Supplier<L> listCreator) {
    // ...

    map.put("stringValue", listCreator.get());
}
if (custom) {
    doSomething(psMap, PsList::new);
} else {
    doSomething(listMap, ArrayList::new);
}