Java泛型列表返回类型
我对返回泛型列表的方法有一些问题。代码基本上是这样的:Java泛型列表返回类型,java,generics,generic-list,Java,Generics,Generic List,我对返回泛型列表的方法有一些问题。代码基本上是这样的: public class MyClass{ private List<MyListElement> myList = new ArrayList<MyListElement>(); public <E> List<E> getGenericList(){ return new ArrayList<E>(); } public vo
public class MyClass{
private List<MyListElement> myList = new ArrayList<MyListElement>();
public <E> List<E> getGenericList(){
return new ArrayList<E>();
}
public void thisWorks(){
List<MyListElement> newList = getGenericList();
myList.addAll(newList);
}
public void thisDoesntWork(){
myList.addAll(getGenericList());
}
public void thisDoesntWorkEither(){
for(MyListElement elem : getGenericList()){
fiddle();
}
}
}
公共类MyClass{
private List myList=new ArrayList();
公共列表getGenericList(){
返回新的ArrayList();
}
公共工程(){
List newList=getGenericList();
myList.addAll(newList);
}
公共无效ThisDoesNetwork(){
addAll(getGenericList());
}
public void this doesntworkeither(){
对于(MyListElement元素:getGenericList()){
小提琴();
}
}
}
为什么
ThisDoesNetwork()
方法不起作用,还有其他方法吗(除了用不总是实用的thisWorks()
方法之外)?您可以这样更改ThisDoesNetwork()
:
public void thisDoesntWork(){ // well, it works now
myList.addAll(this.<String>getGenericList());
}
public void this doesnetwork(){//好吧,它现在可以工作了
myList.addAll(this.getGenericList());
}
您需要告诉编译器正在处理什么类型的
getGenericList()
。编译器无法推断要为ThisDoesNetwork()
中的泛型方法getGenericList()
的类型参数
选择什么类型
在这种情况下,需要通过调用getGenericList()
或者,您可以更改getGenericList()
的签名以接受Class
参数。然后在thisWorks()
和ThisDoesNetwork()中调用getGenericList(MyListElement.class)
。诚然,这有点冗长,但对您的方法的客户来说更直观
我想说,作为一般规则,尝试使泛型方法的类型参数可以从该方法的参数推断出来。泛型方法的类型参数getGenericsList()
可以在调用时传递:
this.<String>getGenericsList()
编译器似乎无法推断正确的类型,老实说,我不知道这是因为它不够聪明,还是因为它不想通过设计承担责任
我甚至做了一个测试,看看问题是否出在通配符上,或者addAll()
是否无法从参数化类型推断类型参数,但似乎什么都不起作用:
公共类泛型列表{
公共静态void main(字符串[]args){
//与JavaAPI相同的签名
列表基=新列表();
base.addAll(GenericsList.getList());//错误!
//addAll()不使用通配符
List2 base2=新的List2();
base2.addAll(getList2());//错误!
//通用方法呢?
addAll(base,getList());//错误!
}
静态列表getList(){
返回新列表();
}
静态void addAll(List src,List other){}
静态列表2 getList2(){
返回新的List2();
}
静态类列表{
void addAll(List此代码适用于您。
getGenericList()
应该知道它返回什么,并且应该与您的列表类型兼容
您不需要将其强制转换为字符串或其他人建议的任何其他类型,因为它会通过将其绑定到字符串类型来限制getGenericList方法的意图。
public class MyClass{
private List<MyListElement> myList = new ArrayList<MyListElement>();
public <E extends MyListElement> List<E> getGenericList(){
return new ArrayList<E>();
}
public void thisWorks(){
List<MyListElement> newList = getGenericList();
myList.addAll(newList);
}
public void thisDoesntWork(){
myList.addAll(getGenericList());
}
public void thisDoesntWorkEither(){
for(MyListElement elem : getGenericList()){
fiddle();
}
}
}
公共类MyClass{
private List myList=new ArrayList();
公共列表getGenericList(){
返回新的ArrayList();
}
公共工程(){
List newList=getGenericList();
myList.addAll(newList);
}
公共无效ThisDoesNetwork(){
addAll(getGenericList());
}
public void this doesntworkeither(){
对于(MyListElement元素:getGenericList()){
小提琴();
}
}
}
当它不实用时,意味着您不应该这样做。即使您的thisWorks
方法也不安全,因为您假设您的genericList
将保留字符串(您无法从代码中确定)。getGenericList()返回一个列表,但您需要调用addAll()使用列表。列表与列表不同,因此会出现错误。那么为什么myList会声明为列表而不是列表呢?@SJuan76:没有办法。原始数据源包含对象,但我们需要能够将内容视为字符串。这在理论上可能会导致ClassCastException是的,但希望我们能够保留它检查包含什么类型的列表。从对象
到字符串
的传递通常使用toString()
完成。只是说这是一个很好的观点,但字符串只是一个示例。我还需要能够处理其他类型。在任何情况下,如果元素实际上不是字符串,则添加toString()的结果与ClassCastException相比,添加到列表中可能会导致更多的混乱。我编辑了这个问题,以反映它实际上与字符串无关。当泛型列表不包含字符串时会发生什么?因为myList
需要String
,我们知道我们正在处理String
s。如果它是其他类型,代码必须相应地更改。getGenericList()只是一个尽可能简化代码的示例方法。在实际应用程序中,它将返回一个实际列表,理论上,其中的对象可能是其他类型。我假设结果是ClassCastException。@jahroy:它不包含任何内容,但这与此无关。我们正试图告诉编译器要推断的类型E
@jahroy:我们不是在讨论运行时(在运行时,不同类型的列表之间没有区别)。我们是在讨论编译时。在编译时,每个表达式都有一个由编译器推断的特定类型。可以同时使用getGenericList()和getGenericList(类)吗版本?这会让打电话的人选择他想要使用的版本。你能解释一下我们如何添加stri列表吗
public class MyClass{
private List<MyListElement> myList = new ArrayList<MyListElement>();
public <E extends MyListElement> List<E> getGenericList(){
return new ArrayList<E>();
}
public void thisWorks(){
List<MyListElement> newList = getGenericList();
myList.addAll(newList);
}
public void thisDoesntWork(){
myList.addAll(getGenericList());
}
public void thisDoesntWorkEither(){
for(MyListElement elem : getGenericList()){
fiddle();
}
}
}