通用通配符类型不应在返回参数中使用
是否可以说通用通配符类型不应该用在方法的返回参数中?
换句话说,声明一个如下所示的接口是有意义的:
interface Foo { Collection next(); }
另外,可以说通用通配符类型仅在方法的参数声明中有意义吗?
在方法forms参数中使用通配符类型的主要好处是为用户提供传递的灵活性,比如说任何类型的Collection
, List
或实现Collection的任何东西(假设集合声明为Collection>
) 。 您经常会发现自己在forms参数中使用通配符类型。
但理想情况下,您应该避免将它们用作方法的返回类型。 因为这样,您将强制该方法的用户在调用者端使用通配符类型,即使他们不想这样做。 通过使用通配符类型,你说,嘿! 这个方法可以返回任何类型的Collection
,所以你的工作就是照顾它。 你不应该这样做。 最好使用有界类型参数。 使用有界类型参数,将根据您传递的类型或方法调用的目标类型推断类型。
以下是Effective Java Item 28的引用:
不要将通配符类型用作返回类型。 它不会为用户提供额外的灵活性,而是迫使他们在客户端代码中使用通配符类型。
正确使用的通配符类型对于类的用户几乎是不可见的。 它们使方法接受它们应该接受的参数并拒绝它们应该拒绝的参数。 如果类的用户必须考虑通配符类型,那么类的API可能有问题。
不,说这个是不可行的。
或者这样说:拥有这样的界面确实有意义。
想象一下以下内容
interface Foo { Collection extends T> next(); } class FooInteger implements Foo { private final List integers = new ArrayList (); void useInternally() { integers.add(123); Integer i = integers.get(0); } @Override public Collection extends Number> next() { return integers; } } // Using it: Foo foo = new FooInteger(); Collection extends Number> next = foo.next(); Number n = next.iterator().next();
如果将返回类型写为Collection
,则无法返回包含T
的子类型的集合。
是否需要具有这种返回类型取决于应用案例。 在某些情况下,可能只是必要的 。 但如果容易避免,那么你可以做到这一点。
编辑:编辑代码以指出差异,即您可能无法始终在内部选择类型。 但是,在大多数情况下,可以避免返回涉及通配符的内容 – 正如我所说的,如果可能的话,应该避免使用。
上面描述的示例仍应被视为强调关键点的示例 。 当然,虽然这样的实现是一种不好的做法,因为它暴露了内部状态。
在这个和类似的情况下,人们通常可以返回类似的东西
return Collections.unmodifiableList(integers);
并且,通过这种方式,将返回类型声明为Colletion
: unmodifiableList
方法解决了暴露内部状态的问题,并且具有允许将类型参数更改为超类型的整洁属性,因为列表是……好吧,无论如何都是不可修改的。
为了避免警报(例如:Sonar),将Class>
替换为Class extends Object>
Class extends Object>
或根本不使用它。 只需归还一class
。