Java:Raw Types vs. Generics [英] Java: Raw Types vs. Generics

查看:192
本文介绍了Java:Raw Types vs. Generics的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的示例代码

/* The new Java 5 or later Generic code */
class TestInserter {
    public static void main(String[] ar) {
        List<Integer> myList = new ArrayList<Integer>();
        myList.add(20);
        myList.add(42);
        Inserter ins = new Inserter();
        ins.insert(myList);
    }
}

/* Legacy Code */
class Inserter {
    public void insert(List list) {
        list.add(new Integer(55));
    }
}

编译并执行上面的代码会运行得很好,没有任何来自编译器或JVM的投诉。 非类型安全的 insert()方法是在我们的 type-safe ArrayList中插入一个新的Integer对象。但是,如果我将insert方法更改为如下所示:

Compiling and executing the above code will run just fine, without any complaints from the compiler or the JVM. The non type-safe insert() method is inserting a new Integer object in our type-safe ArrayList. However, if I change the insert method to something like this:

public void insert(List list) {
        list.add(new String("55"));
}

说什么?!上面的代码会运行吗?考虑一下,确定它会运行,奇怪但是上面的代码编译并运行得很好。
这与Arrays略有不同,它为您提供编译时和运行时保护,并防止此类事件发生。他们为什么这样做泛型?为什么Java允许泛型放入指定类型以外的值?!

What say?! will the above code run? Think about it, Yes sure it will run, Strange but yes the above code compiles and runs just fine. This is a little different from Arrays, which gives you both compile time and run time protection and prevents such things to happen. Why did they do Generics this way? Why does Java allows Generics to put in a value other than the specified type?!

推荐答案

现在回答。使用 insert 方法将 Integer 添加到我们的列表中是非常安全和允许的,因为它与我们的类型相匹配为我们的 myList 变量指定。但是当我们尝试将 String 插入到 ArrayList 中时,只能保留 Integer 值,那么当你尝试调用 Integer 字符串实例的特定方法。

Now for the answer. Using the insert method to add an Integer to our list is quite safe and permissible, as it matches the type we have specified for our myList variable. But when we try to insert a String into an ArrayList that was meant to hold only Integer values, then there is a problem, not at compile time but at runtime, when you try to invoke an Integer-specific method on your wrongly added String instance.

为了理解,您应该理解一件事整个问题及其目的 - JVM不知道您是否尝试将 String 插入 ArrayList 仅包含整数 s。所有泛型及其类型安全性仅限编译时间。通过名为 type erasure 的过程,编译器从通用代码中删除所有类型参数。换句话说,即使你写了这样的东西:

There is one thing you ought to understand in order to understand this entire question and its purpose - The JVM has no idea that you were trying to insert a String into an ArrayList meant to hold only Integers. All your generics and their type-safety are restricted to compile time only. Through a process called "type erasure", the compiler removes all of the type parameters from the generic code. In other words, even though you wrote something like this:

List<Integer> myList = new ArrayList<>();

编译完成后成为以下内容:

Becomes the following after the compiler is done with it:

List myList = new ArrayList();

然而,他们为什么要像这样保留泛型?

However, why did they keep Generics like this?

答案很简单!如果它不会出现这种奇怪的行为,那么早期Java版本的遗留代码就会被破坏,而且Million Java开发人员必须编辑Trillions的旧Java代码才能让它再次运行!!

The answer is simple! If it wouldn't have been for this weird behavior then the legacy code from earlier versions of Java would have been broken and Million Java developers would have to edit Trillions of their old Java code to make it work again!!

但不要责怪编译器;当您尝试运行代码时,编译器会尝试使用以下警告警告您:

But don't blame the compiler; when you try to run the code, the compiler tries to warn you with the following warning:

$> javac TestInserter.java  
Note: TestInserter.java uses unchecked or unsafe operations.  
Note: Recompile with -Xlint:unchecked for details.

当您执行此操作时,编译器会要求您执行以下操作:

And when you do as the compiler asks you to do as follows:

$> javac -Xlint:unchecked TestInserter.java
TestInserter.java:15: warning: [unchecked] unchecked call to add(E) as a member of the raw type List  
        list.add(new String("55"));  
                 ^  
where E is a type-variable:  
  E extends Object declared in interface List  
1 warning    

就编译器而言,它试图告诉你它怀疑程序中的某些代码可能最终出现问题。

As far as the compiler is concerned, it tries to tell you that it suspects that some code in your program might end up in trouble.

要将其包装起来,将泛型视为编译时保护。编译器使用类型信息(在参数中指定的类型)来确保不将错误的内容插入集合(或用户定义的泛型类型),并且不从错误的引用类型中获取值。 所有通用保护都是编译时间!就是这样。

To wrap it up, Think of generics as just compile time protection. The compiler uses the type information (Type specified in parameter) to make sure that you don't insert the wrong things into a collection (or a user defined generic type) and that you don't fetch values from the wrong reference type. All of the generic protection is compile time! That's it for this.

这篇关于Java:Raw Types vs. Generics的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆