Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在对象实例化之前确保参数化类型的有效性_Java_Generics_Type Safety_Raw Types - Fatal编程技术网

Java 如何在对象实例化之前确保参数化类型的有效性

Java 如何在对象实例化之前确保参数化类型的有效性,java,generics,type-safety,raw-types,Java,Generics,Type Safety,Raw Types,在研究《有效Java第二版》的第23项时,我决定尝试用一个构造函数实例化一个对象,该构造函数具有一个原始集合和一个混合对象的参数列表。我假设编译器会发现我试图将原始类型传递给构造函数。但是,编译器只提供一个未经检查的异常警告,“在调用方,而不是被调用方。” 该类编译良好,进一步支持Josh Bloch的语句,在新代码中不使用原始类型。事实上,这对我来说有点不安 问?如何在实例化对象之前确保类的类型安全,而不必在构造函数中手动检查对象的有效性?以下仅提供了来自“主叫方…主要”的未经检查的分配警告,

在研究《有效Java第二版》的第23项时,我决定尝试用一个构造函数实例化一个对象,该构造函数具有一个原始集合和一个混合对象的参数列表。我假设编译器会发现我试图将原始类型传递给构造函数。但是,编译器只提供一个未经检查的异常警告,“在调用方,而不是被调用方。”

该类编译良好,进一步支持Josh Bloch的语句,在新代码中不使用原始类型。事实上,这对我来说有点不安

问?如何在实例化对象之前确保类的类型安全,而不必在构造函数中手动检查对象的有效性?以下仅提供了来自“主叫方…主要”的未经检查的分配警告,一个防御程序如何对此进行防御

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{}

}
公共类RawType{
私人最终收集示例;
公共RawType(集合示例){
这个例子=例子;
}
公共集合getExample(){
返回示例;
}
公共静态void main(字符串[]args){
集合不安全=新建ArrayList();
添加(新示例());
不安全。添加(新损坏());
添加(新示例());
RawType RawType=新的RawType(不安全);//损坏
对于(对象类型:rawType.getExample()){
System.out.println(type.getClass().getName());//混合类。。。
}
}
静态类损坏{}
静态类示例{}
}

为了使java泛型与引入之前编写的代码兼容,您可以在需要类型化集合的任何地方使用非类型化集合。因此,可以将集合(不带类型参数)传递给需要集合的构造函数


因此,作为对集合的回应,只有在向非类型集合添加对象时小心,才能确保安全。如果需要运行时安全性,可以在从集合中检索对象时手动验证对象的类型。

下面几行编译,但也会生成警告

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
Collection unsafe=new ArrayList();//原始类型
不安全。添加(1);//没有编译时错误(只是警告)
收集示例=不安全;//将原始类型指定给参数化类型
示例。添加(1);//编译时错误
最好使用泛型集合来避免这种情况,然后在其中添加值从不混合和参数化类型


请查看以下代码:

Collection<Integer> unsafe = new ArrayList<Integer>();
unsafe.add(1);
Collection<String> example = unsafe; // compile time error
Collection unsafe=new ArrayList();
增加(1);
收集示例=不安全;//编译时错误


如果无法避免原始类型,请在构造函数中使用以下代码:

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);
    }
}
Collection unsafe=new ArrayList();
增加(1);
不安全。添加(“你好”);
//在构造函数中,只需添加来自不安全集合的字符串值
集合示例=新的ArrayList();
for(对象值:不安全){
if(字符串的值实例){
示例.添加((字符串)值);
}
}

不要忽略警告以避免这种情况。警告不在“被调用方”(构造函数)处,因为它没有任何问题。问题在于调用者,您使用的是原始类型,而您应该使用正确的泛型类型。对于警告也在被叫方,它必须说“这个构造函数/方法在其他地方没有正确使用”,而这只是不起作用。我明确地说,“主叫方。在主体”中考虑你正在构建一个API,并且有人发送一个原始类型…在没有手动验证的情况下,您如何防御该程序。这就是问题所在,我不必担心。每一个Java程序员都应该知道,使用原始类型有其自身的风险,如果他们的程序因此而无法工作,那是他们的错,而不是你的错。还请注意,绝大多数类/API也不保护原始参数。“许多API也不保护原始参数”。。。从来没想过。。。有趣。我想了解的是,我如何确保“调用者”在参数中不发送外来类型?似乎不可能在没有验证实现的情况下强制遵从。为什么要使用原始类型?你能避免吗?泛型只适用于编译时检查。所有泛型类型信息在运行时丢失。是的,这不是生产。。。这是一篇关于不要使用原始类型的评论。。。