Java 为什么可以';t我使用一个实现列表的类<;X>;其中一个列表<;X>;预计会发生什么?
首先是简单案例(A): PsList.javaJava 为什么可以';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() {
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);
}