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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22815023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 18:06:09  来源:igfitidea点击:

Generic wildcard types should not be used in return parameters

javagenerics

提问by jilt3d

Is it feasible to say that generic wildcard types should not be used in return parameters of a method?

说通用通配符类型不应用于方法的返回参数是否可行?

In other words, does make sense to declare an interface like the following:

换句话说,像下面这样声明一个接口是有意义的:

interface Foo<T> {
  Collection<? extends T> next();
}

Additionally, is it ok to say that generic wildcard types does make sense only at method's parameter declaration?

此外,可以说泛型通配符类型仅在方法的参数声明中才有意义吗?

采纳答案by Rohit Jain

The main benefit of using wildcard types, say in method formal parameter, is to provide flexibility to the user to pass, say any type of Collection, or Listor anything that implements Collection (assuming that the collection is declared like Collection<?>). You would often find yourself using wildcard types in formal parameters.

使用通配符类型的主要好处,比如在方法形式参数中,是为用户提供灵活性,可以传递任何类型的CollectionList或任何实现集合的东西(假设集合声明为Collection<?>)。您经常会发现自己在形式参数中使用通配符类型。

But ideally you should avoid using them as return type of your method. Because that way, you would force the user of that method to use wildcard types at the caller end, even if they didn't want to. By using wildcard types, you're saying that, hey! this method can return any type of Collection, so it's your job to take care of that. You shouldn't do that. Better to use bounded type parameter. With bounded type parameter, the type will be inferred based on the type you pass, or the target type of the method invocation.

但理想情况下,您应该避免将它们用作方法的返回类型。因为那样,您将强制该方法的用户在调用方端使用通配符类型,即使他们不想这样做。通过使用通配符类型,您就是在说,嘿!此方法可以返回任何类型的Collection,因此您的工作是处理它。你不应该那样做。最好使用有界类型参数。使用有界类型参数,将根据您传递的类型或方法调用的目标类型推断类型。

And here's a quote from Effective Java Item 28:

这是Effective Java Item 28的引用

Do not use wildcard types as return types.Rather than providing additional flexibility for your users, it would force them to use wildcard types in client code.
Properly used, wildcard types are nearly invisible to users of a class. They cause methods to accept the parameters they should accept and reject those they should reject. If the user of a class has to think about wildcard types, there is probably something wrong with the class's API.

不要使用通配符类型作为返回类型。它不会为您的用户提供额外的灵活性,而是强制他们在客户端代码中使用通配符类型。
如果使用得当,通配符类型对于类的用户几乎是不可见的。它们导致方法接受他们应该接受的参数并拒绝他们应该拒绝的参数。如果类的用户必须考虑通配符类型,则类的 API 可能有问题。

回答by Marco13

No, it is not feasible to say this.

不,这样说是不可行的。

Or to put it that way: It doesmake sense to have such an interface.

或者这样说:拥有这样的界面确实有意义。

Imagine the following

想象以下

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();

If you wrote the return type as Collection<T>, you could not return a collection containing a subtype of T.

如果将返回类型编写为Collection<T>,则无法返回包含子类型 的集合T

Whether or not it is desirable to have such a return type depends on the application case. In some cases, it may simply be necessary. But if it is easy to avoid, then you can do this.

是否需要这样的返回类型取决于应用程序案例。在某些情况下,它可能只是必要的。但如果很容易避免,那么你可以这样做。



EDIT: Edited the code to point out the difference, namely that you might not always be able to choose the type internally. However, in most cases returning something that involves a wildcard canbe avoided - and as I said, if possible, it should be avoided.

编辑:编辑代码以指出不同之处,即您可能并不总是能够在内部选择类型。然而,在大多数情况下,返回的东西,包括一个通配符可以被避免的-正如我说的,如果可能的话,应尽量避免。

The example sketched above should still be considered as an exampleto emphasize the key point. Although, of course, such an implementation would be a bad practice, because it is exposing an internal state.

上面勾画的例子仍应被视为强调关键点的例子。虽然,当然,这样的实现将是一种不好的做法,因为它暴露了一个内部状态。

In this and similar cases, one can often return something like a

在这种和类似的情况下,人们通常可以返回类似

return Collections.<Number>unmodifiableList(integers);

and by this, declare the return type as Colletion<Number>: The unmodifiableListmethod solves the problem of the exposed internal state, and has the neat property that it allows changing the type parameter to a supertype, because the list is then... well, unmodifiable anyhow.

通过这种方式,将返回类型声明为Colletion<Number>: 该unmodifiableList方法解决了暴露的内部状态的问题,并且具有允许将类型参数更改为超类型的简洁属性,因为该列表是……好吧,无论如何都不可修改。

回答by EliuX

To avoid alerts (Ex.: Sonar) replace Class<?>for Class<? extends Object>or not use it at all. Just return a class.

为了避免警报(例:声纳)代替Class<?>Class<? extends Object>或根本不使用它。只需返回一个class.

回答by Abhishek Kumar

It is highly recommended not to use wildcard types as return types. Because the type inference rules are fairly complex it is unlikely the user of that API will know how to use it correctly. Let's take the example of method returning a "List". Is it possible on this list to add a Dog, a Cat, ... we simply don't know. And neither does the compiler, which is why it will not allow such a direct use. The use of wildcard types should be limited to method parameters.

强烈建议不要使用通配符类型作为返回类型。因为类型推断规则相当复杂,该 API 的用户不太可能知道如何正确使用它。让我们以返回“列表”的方法为例。是否可以在此列表中添加一只狗、一只猫……我们只是不知道。编译器也没有,这就是为什么它不允许这样直接使用。通配符类型的使用应仅限于方法参数。

This rule raises an issue when a method returns a wildcard type.

当方法返回通配符类型时,此规则会引发问题。

Noncompliant Code Example

不合规的代码示例

 ?List<? extends Animal> getAnimals(){...} ?

Compliant Solution

合规解决方案

 ?List<Animal> getAnimals(){...} 

? or

? 或者

 ?List<Dog> getAnimals(){...}

EDIT

编辑

SOURCE - https://rules.sonarsource.com/java/RSPEC-1452

来源 - https://rules.sonarsource.com/java/RSPEC-1452