Ash*_*wal 23 java generics list
你能帮我理解无界通配符类型列表和原始类型列表之间的区别吗?
List<?> b; // unbounded wildcard type
List a; // raw type
Run Code Online (Sandbox Code Playgroud)
除此之外,任何人都可以帮助我理解什么是有界类型参数列表?
List<E extends Number> c;
Run Code Online (Sandbox Code Playgroud)
Joh*_*lla 32
以下是三者的总结:
List:没有类型参数的列表.它是一个列表,其元素是任何类型 - 元素可以是不同类型.
List<?>:具有无界类型参数的列表.它的元素是特定的,但未知的类型; 元素必须都是相同的类型.
List<T extends E>:带有类型参数的列表T.提供的类型T必须是扩展的类型E,或者它不是参数的有效类型.
Tom*_*Tom 19
你应该看看Effective Java,第23项:不要在新代码中使用原始类型.
要使用该书中的示例,请考虑以下示例...如果您有一个不关心其中包含哪些元素类型的集合,该怎么办?例如,您想要查看两个集合之间共有多少个元素.您可能会想出以下内容:
public static int numElementsInCommon(Set s1, Set s2) {
int result = 0;
for (Object o : s1) {
if (s2.contains(o)) {
++result;
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
这个例子虽然有效,但由于使用了原始类型,因此不是一个好主意.原始类型根本不是类型安全的......你最终可能会以一种非类型安全的方式修改集合并破坏你的程序.相反,谨慎一点并使用类型安全替代方案:
public static int numElementsInCommon(Set<?> s1, Set<?> s2) {
int result = 0;
for (Object o : s1) {
if (s2.contains(o)) {
++result;
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
不同之处在于您只能添加null到a Set<?>,并且您不能假设您从a中取出的元素Set<?>.如果您使用raw Set,则可以添加任何内容.该numElementsInCommon方法是一个很好的示例,您甚至不需要添加任何内容,也不需要假设集合中的内容.这就是为什么它是使用?通配符的好选择.
希望这可以帮助.阅读有效Java中的整个项目,它将变得清晰.
要回答你问题的第二部分......记得我说当你使用?通配符时,你不能假设你从集合中取出的元素有什么?如果您确实需要对从集合中删除的对象的接口做出假设,该怎么办?例如,假设您想要跟踪一组Cool事物.
public interface Cool {
// Reports why the object is cool
void cool();
}
Run Code Online (Sandbox Code Playgroud)
然后你可能会有这样的代码:
public static void reportCoolness(Set s) {
for (Object item : s) {
Cool coolItem = (Cool) item;
coolItem.cool();
}
}
Run Code Online (Sandbox Code Playgroud)
这不是类型安全的......你需要确保传入一个只有Cool对象的集合.要解决它,你可能会说:
public static void reportCoolness(Set<Cool> s) {
for (Cool coolItem : s) {
coolItem.cool();
}
}
Run Code Online (Sandbox Code Playgroud)
这很棒!完全符合您的要求并且类型安全.但是,如果以后你有这个:
public interface ReallyCool extends Cool {
// Reports why the object is beyond cool
void reallyCool();
}
Run Code Online (Sandbox Code Playgroud)
由于所有ReallyCool对象都是Cool,您应该能够执行以下操作:
Set<ReallyCool> s = new HashSet<ReallyCool>();
// populate s
reportCoolness(s);
Run Code Online (Sandbox Code Playgroud)
但是你不能这样做,因为泛型具有以下属性:假设B是子类A,然后Set<B>不是它的子类Set<A>.对此的技术讨论是"通用类型是不变的".(与协变相反).
要使最后一个示例起作用,您需要Set<Cool>通过强制转换(安全地)创建每个元素Set<ReallyCool>.为了避免让你的api的客户经历这个讨厌的,不必要的代码,你可以让这个reportCoolness方法更加灵活:
public static void reportCoolness(Set<? extends Cool> s) {
for (Cool coolItem : s) {
coolItem.cool();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您的方法将Set包含任何包含元素Cool或其子类的元素Cool.所有这些类型都遵循Coolapi ...所以我们可以安全地cool()在任何元素上调用该方法
合理?希望这可以帮助.
关于第一个问题,之间的区别List和List<?>:
两者之间的一个显着区别是,当您将通配符作为类型时, 的类型Collection是未知的,因此该add方法将引发编译时错误。
您仍然可以从 中获取值List<?>,但您需要显式转换。
| 归档时间: |
|
| 查看次数: |
5990 次 |
| 最近记录: |