2012-04-13 188 views
5

我有一个方法需要List<?>作为参数。Java泛型类型参数

public static String method(List<?> arg){ 
    // Do something based on type of the list 
} 

//I call the method as below 
List<ClassA> listA = new ArrayList<ClassA>(); 
List<ClassB> listB = new ArrayList<ClassB>(); 
method(listA); 
method(listB); 

method,我怎么知道,如果argClassA一个ListClassB一个List

+2

声明参数类型为''意思是说你对实际类型不感兴趣。 – biziclop 2012-04-13 22:33:35

+0

重复这个http://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list – evanwong 2012-04-13 22:34:55

+0

@evanwong - 不知道我是否会同意它的愚蠢。 – djangofan 2012-04-13 22:37:32

回答

3

从用户的回答称为Romain“如果您使用<?>,则表示您不打算在任何地方使用参数化类型。要么转到特定类型(对于您的情况,似乎列表< String> )或非常通用的列表对象>“

另外,我相信如果您使用问号,编译器将不会捕获类型不匹配,直到运行时(有效Java的实体化; p.119),绕过擦除,并且有效减少使用泛型类型所带来的好处?

回答提问者的问题:如果使用列表< Object>然后尝试将其转换为A或B,可能使用instanceOf,这可能是一种告诉它是什么的方法。我敢打赌,尽管如此,还是有更好的方法去做。

+1

对于OP,+1正有效地消除了使用泛型类型获得的好处_ – jahroy 2012-04-13 23:11:36

+1

意味着“我没有使用泛型,但我想摆脱编译器警告。” – user949300 2013-02-07 23:31:23

+3

-1,因为这个答案鼓励错误的编码习惯。定义一个采用泛型类型参数的方法是这样做的适当方式 - 它为您提供了类型安全性,并且不需要混乱的转换。请参阅jahroy的回答。 – 2013-03-19 03:19:38

1

鉴于您的示例,无法知道List的泛型类型参数是什么。它们在实例级别被删除。

14

从技术上讲,你CAN使用instanceof检查对象是否是某种类型。

然而,这是不是一个好主意。

你声明你的方法的方式,它可以接受任何类型的列表,所以它并不一定会是A或B.

很难告诉你要怎么做,但你可能应该让你的方法是通用的。

你可以这样做是这样的:

public static <T> String method(List<T> arg) { 
    // We now know that the type of the list is T, which is 
    // determined based on the type of list passed to this 
    // method. This would demonstrate the point better if 
    // the return type was T, but I'm leaving the return type 
    // as String, because that's what your code returns. 
} 

这里有一个更好的例子

如果你想创建一个返回列表的第一个元素的一般方法,你会这样做:

public static <T> T firstElement(List<T> theList) { 
    if (theList == null) { 
     return null; 
    } 
    T objectOfTypeT = theList.get(0); 
    return objectOfTypeT; 
} 

请注意,返回现在类型为T

因为我们使这个方法是通用的,它可以返回列表中使用的相同类型。

您通常只会返回theList.get(0),但我添加了一行以使泛型的用途更加明显。

语法的说明:

  • <T>表明,该方法采用一个名为T

  • 紧随T是返回类型一个类型参数(就像你通常会返回字符串,整数等)。

  • List参数中的T是编译器知道什么是T

这允许编译器说:“这种方法需要类型T的东西哦,看...这样的例子也是T类型如果有人通过字符串列表这种方法,且T必须是一个字符串。如果有人通过整数这种方法的列表,T必须是整数。

相反,你的方法可以返回一个字符串,它根本不知道是什么类型的使用列表。


也...

如果A和B都延长了同一个班级,一个名为TheParentClass,你可以声明你的方法是这样的:

public static String method(List<? extends TheParentClass> arg) 

这样一来,你就知道多一点关于你的参数的可能类型(并且可以从编译时类型检查中受益)。

+0

最后一个例子你给出了“扩展TheParentClass”大概是怎么样的?是“意思”被使用。允许使用?没有延伸位,就像大卫梅森所说的那样,糟糕的做法却是合法的。我认为jahroy应该被授予这个问题的答案,而不是我,因为他钉了它。 – djangofan 2013-03-19 20:10:32