Java泛型类型参数

10
我有一个方法,它接收一个 List<?> 作为参数。
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中,我如何知道argClassAList还是ClassBList

2
将参数类型声明为 <?> 意味着您对实际类型不感兴趣。 - biziclop
我使用了if(arg.get(0) instanceof ClassA) // do something ....并且我得到了预期的结果。但是从这里的回复来看,我不确定这是否是正确的做法。 - user682765
1
即使您不使用泛型(只需删除 <?>),也可以执行此操作。泛型的目的是使您无需使用 instanceof 或担心不安全的转换。 - jahroy
2个回答

28

从技术角度来说,您可以使用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是返回类型(就像您通常会返回String、Integer等)。 - 列表参数中的T是编译器知道如何处理T的方法。 - 这使编译器能够说:“这种方法期望某种类型的T。哦,看起来……列表也是类型为T的。如果有人将字符串列表传递给此方法,则T必须是字符串。如果有人将整数列表传递给此方法,则T必须是整数。”
相比之下,您的方法仅能返回字符串,并且不知道列表中使用的类型。
另外...
如果A和B都扩展了同一个名为TheParentClass的类,则可以像这样声明您的方法:
public static String method(List<? extends TheParentClass> arg)

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

1
你提到的那个"? extends TheParentClass"的例子可能是问号应该使用的方式。在不使用extends部分的情况下使用?是不好的做法,但合法的,就像David Mason所建议的一样。我认为jahroy应该被授予这个问题的答案,而不是我,因为他完美解决了它。 - djangofan

4

以下是来自用户Romain的答案:“如果您使用<?>,则表示您不会在任何地方使用参数化类型。 要么转到特定类型(在您的情况下似乎是List<String>),要么转到非常通用的List<Object>”

此外,我认为如果您使用问号,编译器在运行时(具体化;请参见Effective Java第119页)无法捕获类型不匹配,绕过擦除,并有效地消除了使用通用类型所获得的好处???

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


1
+1 对于 OP 来说,实际上是消除了使用泛型类型所获得的好处。 - jahroy
2
<?> 表示“我不使用泛型,但我想消除编译器警告。” - user949300
6
这个答案鼓励了不好的编程习惯,因此评分为-1。定义一个带有通用类型参数的方法是正确的做法——这样可以确保类型安全而且不需要进行繁琐的类型转换。请参考jahroy的答案。 - David Mason

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接