在研究Effective Java 2nd Edition的第23项时,我决定尝试使用具有带有混合对象的参数列表的原始集合的构造函数来实例化对象。我假设编译器会发现我试图将原始类型传递给构造函数。但是,编译器仅提供未经检查的异常警告,“在调用者处,而不是被调用者”。
该类编译得很好,进一步支持Josh Bloch的声明,不要在新代码中使用原始类型。编译的事实对我来说有点令人不安。
Q&如何在实例化对象之前确保类的类型安全,而不必在构造函数中手动检查对象的有效性?以下仅提供了一个未经检查的分配警告,来自“主要呼叫者......”如何防御性地对此进行编程。
public class RawType {
private final Collection<Example> example;
public RawType( Collection<Example> example ) {
this.example = example;
}
public Collection<Example> getExample() {
return example;
}
public static void main( String[] args ) {
Collection unsafe = new ArrayList();
unsafe.add( new Example() );
unsafe.add( new Corruption() );
unsafe.add( new Example() );
RawType rawType = new RawType( unsafe ); // Corruption
for(Object type : rawType.getExample()) {
System.out.println(type.getClass().getName()); // Mixed Classes...
}
}
static class Corruption {}
static class Example{}
}
答案 0 :(得分:1)
下面的行编译但也生成警告。
Collection unsafe = new ArrayList(); // RAW type
unsafe.add(1); // no compile time error (just warning)
Collection<String> example = unsafe; // assign RAW type to parametrized type
example.add(1); // compile time error
最好使用Generic集合来避免这种情况,然后在其中添加值。 从不混合RAW和参数化类型。
看看下面的代码:
Collection<Integer> unsafe = new ArrayList<Integer>();
unsafe.add(1);
Collection<String> example = unsafe; // compile time error
如果您无法避免使用RAW类型,请在构造函数中使用以下代码:
Collection unsafe = new ArrayList();
unsafe.add(1);
unsafe.add("hello");
// in the constructor, just add String values from the unsafe collection
Collection<String> example = new ArrayList<String>();
for(Object value:unsafe){
if(value instanceof String){
example.add((String)value);
}
}
答案 1 :(得分:0)
为了使java泛型与引入之前编写的代码兼容,您可以在期望类型集合的任何位置使用无类型集合。因此,可以将Collection(没有类型参数)传递给期望Collection的构造函数。
因此,在回答您的收藏时,只有在将对象添加到无类型的连接时,才能保证安全。如果您想要运行时悲伤,可以在从集合中检索对象时手动验证对象的类型。