8

我有一个以 aList<?>作为参数的方法。

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中,我怎么知道arg是 a ListofClassA还是 a Listof ClassB

4

2 回答 2

24

从技术上讲,您可以使用instanceof来检查对象是否为某种类型。

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

您声明方法的方式,它可以接受任何类型的 List,因此它不一定是 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;
}

请注意,返回类型是 now T

因为我们将此方法设为通用,所以它可以返回 List 中使用的相同类型。

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

语法解释:

  • <T>表示此方法采用一个名为 T 的类型参数。

  • 紧随其后的T是返回类型(就像您通常会返回字符串、整数等...)。

  • List 参数中的T是编译器如何知道 a 到底T是什么。

这允许编译器说:“这个方法需要 T 类型的东西。哦,看......这个列表也是 T 类型的。如果有人将一个字符串列表传递给这个方法,那么 T 必须是一个字符串。如果有人通过此方法的整数列表,T 必须是整数。 "

相反,您的方法只能返回一个字符串,并且它不知道列表中使用的是什么类型。


还...

如果 A 和 B 都扩展同一个类,名为 TheParentClass,你可以像这样声明你的方法:

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

这样,您将对参数的可能类型了解更多(并且可以从编译时类型检查中受益)。

于 2012-04-13T22:38:43.287 回答
4

从名为Romain的用户的回答中 “如果您使用 <?>,您的意思是您不会在任何地方使用参数化类型。要么转到特定类型(在您的情况下,它似乎是 List<String>),要么转到非常通用的 List<Object>"

另外,我相信如果您使用问号,编译器不会在运行时之前捕获类型不匹配(reified;有效 Java 的第 119 页),绕过擦除,并有效地消除您从使用泛型类型中获得的好处???

回答提问者的问题:如果您使用 List< Object> 然后尝试将其强制转换为 A 或 B ,可能使用 instanceOf ,这可能是一种判断它是什么的方法。我敢打赌,有比这更好的方法。

于 2012-04-13T22:31:40.707 回答