Java 是<;T>;列表<;?扩展T>;一个有用的签名

Java 是<;T>;列表<;?扩展T>;一个有用的签名,java,generics,signature,Java,Generics,Signature,IsList我把“它是一个有用的签名”理解为“你能想到它的用例吗?” T是在调用站点确定的,而不是在方法内部,因此您只能从方法返回两件事:null或空列表 假设您可以使用与调用此方法大致相同的代码来创建这两个值,那么使用它并不是一个很好的理由 实际上,另一个可以安全返回的值是一个所有元素都为null的列表。但是这也没有用,因为您只能调用从返回值中添加或删除文本null的方法,因为?在类型绑定中扩展。所以你们所得到的就是计算它包含的空值的数量。这也没用。官员建议不要使用通配符返回类型 这些准则不

Is
List我把“它是一个有用的签名”理解为“你能想到它的用例吗?”

T
是在调用站点确定的,而不是在方法内部,因此您只能从方法返回两件事:null或空列表

假设您可以使用与调用此方法大致相同的代码来创建这两个值,那么使用它并不是一个很好的理由


实际上,另一个可以安全返回的值是一个所有元素都为null的列表。但是这也没有用,因为您只能调用从返回值中添加或删除文本null的方法,因为
?在类型绑定中扩展
。所以你们所得到的就是计算它包含的空值的数量。这也没用。

官员建议不要使用通配符返回类型

这些准则不适用于方法的返回类型。应避免使用通配符作为返回类型,因为它会迫使程序员使用代码来处理通配符。”


虽然给出的推理并不完全令人信服,但是

由于其他答案的原因,它并不是特别有用。然而,在下面这样的类中,它是“有用的”(尽管它可能有点反模式):

公共类存储库{
private List lst=new ArrayList();
公共作废新增(T项){
一、增加(项目);
}
@抑制警告(“未选中”)
public List这个方法签名是“有用的”,因为你可以用它实现非平凡的、非退化的方法(也就是说,返回
null
和抛出错误不是你唯一的选择)。正如下面的例子所示,这种方法对于实现一些代数结构(例如幺半群)是有用的


首先,请注意返回通配符的
列表并没有真正的用处。您仍然可以调用
add(null)
等。使用类型推断,您可以执行
列表。我想采访者得到的是,方法的返回类型包含通配符。摘自《有效Java》,第2版。“您不应返回通配符类型,因为它会强制API的用户处理通配符。“(转述)也许最好的答案是,返回类型适合在系统内的包私有或私有方法中使用,但不应将其用作导出API的一部分。@ArtB不,第二版的建议仍然非常有效:通配符是为了增加参数的灵活性;不应在返回类型中使用通配符。嗯,looking非常渴望有一种人为的方法使其有用,您可以事先在同一对象上调用
setReturnType(Class cls)
方法,然后
f()
将使用该信息返回所需类型的列表。@DodgyCodeException我想-但这将是协议反模式。”假设您可以用与调用此方法大致相同的代码创建这两个值,那么使用它并不是一个很好的理由。“真的吗?调用
.empty()
似乎比调用
((List@AndreyTyukin
List@AndyTurner这是一个语句,而不是表达式。必须使用额外的变量(如
list
)来污染局部范围。实例化空的附加保护列表的简单想法将分布在代码中的两行不同的行上。而且此语句仍然比简单的
.empty()长得多
new List()
是一个
列表通配符列表不是只读的。您可以删除元素,可以将
null
添加到列表中,然后。
public class Repository {
    private List<Object> lst = new ArrayList<>();

    public <T> void add(T item) {
        lst.add(item);
    }

    @SuppressWarnings("unchecked")
    public <T> List<? extends T> f() {
        return (List<? extends T>) lst;
    }

    public static void main(String[] args) {
        Repository rep = new Repository();
        rep.add(BigInteger.ONE);
        rep.add(Double.valueOf(2.0));
        List<? extends Number> list = rep.f();
        System.out.println(list.get(0).doubleValue() + list.get(1).doubleValue());
    }
}
public static <T> List<? extends T> pure(T t) {
  List<T> result = new LinkedList<T>();
  result.add(t);
  return result;
}
public static <T> List<? extends T> toAppendProtected(List<T> original) {
  List<T> result = new LinkedList<T>();
  result.addAll(original);
  return result;
}
public static <T> List<? extends T> combineAppendProtected(
  List<? extends T> a,
  List<? extends T> b
) {
  List<T> result = new LinkedList<T>();
  result.addAll(a);
  result.addAll(b);
  return result;
}
public static <T> List<? extends T> emptyAppendProtected() {
  return new LinkedList<T>();
}
  public static interface Monoid<X> {
    X empty();
    X combine(X a, X b);
  }
  public static <T> Monoid<List<? extends T>> appendProtectedListsMonoid() {
    return new Monoid<List<? extends T>>() {
      public List<? extends T> empty() {
        return ReadOnlyLists.<T>emptyAppendProtected();
      }

      public List<? extends T> combine(
        List<? extends T> a,
        List<? extends T> b
      ) {
        return combineAppendProtected(a, b);
      }
    };
  }
import java.util.*;

class AppendProtectedLists {

  public static <T> List<? extends T> emptyAppendProtected() {
    return new LinkedList<T>();
  }

  public static <T> List<? extends T> combineAppendProtected(
    List<? extends T> a,
    List<? extends T> b
  ) {
    List<T> result = new LinkedList<T>();
    result.addAll(a);
    result.addAll(b);
    return result;
  }

  public static <T> List<? extends T> toAppendProtected(List<T> original) {
    List<T> result = new LinkedList<T>();
    result.addAll(original);
    return result;
  }

  public static <T> List<? extends T> pure(T t) {
    List<T> result = new LinkedList<T>();
    result.add(t);
    return result;
  }

  public static interface Monoid<X> {
    X empty();
    X combine(X a, X b);
  }

  public static <T> Monoid<List<? extends T>> appendProtectedListsMonoid() {
    return new Monoid<List<? extends T>>() {
      public List<? extends T> empty() {
        return AppendProtectedLists.<T>emptyAppendProtected();
      }

      public List<? extends T> combine(
        List<? extends T> a,
        List<? extends T> b
      ) {
        return combineAppendProtected(a, b);
      }
    };
  }

  public static void main(String[] args) {
    Monoid<List<? extends String>> monoid = appendProtectedListsMonoid();
    List<? extends String> e = monoid.empty();
    // e.add("hi"); // refuses to compile, which is good: write protection!
    List<? extends String> a = pure("a");
    List<? extends String> b = pure("b");
    List<? extends String> c = monoid.combine(e, monoid.combine(a, b));
    System.out.println(c); // output: [a, b]
  }

}