[英]Generic wildcard types should not be used in return parameters
说通用通配符类型不应用于方法的返回参数是否可行?
换句话说,像下面这样声明一个接口是有意义的:
interface Foo<T> {
Collection<? extends T> next();
}
此外,可以说泛型通配符类型仅在方法的参数声明中才有意义吗?
使用通配符类型的主要好处,比如在方法形式参数中,是为用户提供灵活性,可以传递任何类型的Collection
,或List
或任何实现 Collection 的东西(假设集合声明为Collection<?>
) . 您经常会发现自己在形式参数中使用通配符类型。
但理想情况下,您应该避免将它们用作方法的返回类型。 因为那样,您将强制该方法的用户在调用方端使用通配符类型,即使他们不想这样做。 通过使用通配符类型,您就是在说,嘿! 这个方法可以返回任何类型的Collection
,所以你的工作是照顾它。 你不应该那样做。 最好使用有界类型参数。 使用有界类型参数,将根据您传递的类型或方法调用的目标类型推断类型。
这是Effective Java Item 28的引用:
不要使用通配符类型作为返回类型。 它不会为您的用户提供额外的灵活性,而是强制他们在客户端代码中使用通配符类型。
如果使用得当,通配符类型对于类的用户几乎是不可见的。 它们导致方法接受他们应该接受的参数并拒绝他们应该拒绝的参数。 如果类的用户必须考虑通配符类型,则类的 API 可能有问题。
不,这样说是不可行的。
或者这样说:拥有这样的界面确实有意义。
想象以下
interface Foo<T>
{
Collection<? extends T> next();
}
class FooInteger implements Foo<Number>
{
private final List<Integer> integers = new ArrayList<Integer>();
void useInternally()
{
integers.add(123);
Integer i = integers.get(0);
}
@Override
public Collection<? extends Number> next()
{
return integers;
}
}
// Using it:
Foo<Number> foo = new FooInteger();
Collection<? extends Number> next = foo.next();
Number n = next.iterator().next();
如果将返回类型编写为Collection<T>
,则无法返回包含T
子类型的集合。
是否需要这样的返回类型取决于应用程序案例。 在某些情况下,它可能只是必要的。 但如果很容易避免,那么你可以这样做。
编辑:编辑代码以指出不同之处,即您可能并不总是能够在内部选择类型。 然而,在大多数情况下,返回的东西,包括可避免通配符-和我说,如果可能的话,应尽量避免。
上面勾画的例子仍应被视为强调关键点的例子。 虽然,当然,这样的实现将是一种不好的做法,因为它暴露了一个内部状态。
在这种和类似的情况下,人们通常可以返回类似
return Collections.<Number>unmodifiableList(integers);
通过这种方式,将返回类型声明为Colletion<Number>
: unmodifiableList
方法解决了公开内部状态的问题,并且具有允许将类型参数更改为超类型的简洁属性,因为列表是...好吧,无论如何都无法修改。
为了避免警报(例如:Sonar),将Class<?>
替换为Class<? extends Object>
Class<? extends Object>
或根本不使用它。 只需归还一class
。
https://rules.sonarsource.com/java/RSPEC-1452
强烈建议不要使用通配符类型作为返回类型。 因为类型推断规则相当复杂,该 API 的用户不太可能知道如何正确使用它。 让我们以返回“List<? extends Animal>”的方法为例。 是否可以在此列表中添加一只狗、一只猫……我们只是不知道。 编译器也没有,这就是为什么它不允许这样直接使用。 通配符类型的使用应仅限于方法参数。
当方法返回通配符类型时,此规则会引发问题。
不合规的代码示例
List<? extends Animal> getAnimals(){...}
合规解决方案
List<Animal> getAnimals(){...} or List<Dog> getAnimals(){...}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.