繁体   English   中英

不应在返回参数中使用通用通配符类型

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM