Java泛型 编译期检查的分析

Java泛型所给予的编译期检查,是根据该泛型对象的引用类型来定的,如果泛型类对象的引用类型的< >里有具体类型,那么就会执行相应的编译期检查。

此例将使用ArrayList,代码能通过编译。在new ArrayList的时候可以给定具体类型,用来接对象的引用也可以给定具体类型,将从这两个方面来设计例子:

import java.util.ArrayList;

public class test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("str"); //编译通过
        //list.add(1); //编译错误
        String str = list.get(0); //返回类型就是String

        //表现和上一个完全一样
        //相当于ArrayList<String> list1 = new ArrayList<String>()
        ArrayList<String> list1 = new ArrayList();
        list1.add("str"); //编译通过
        //list1.add(1); //编译错误
        String str1 = list1.get(0); //返回类型就是String

        ArrayList list2 = new ArrayList<String>();
        list2.add("str"); //编译通过  
        list2.add(1); //编译通过
        Object object = list2.get(0); //返回类型就是Object

        new ArrayList<String>().add("11"); //编译通过  
        //new ArrayList<String>().add(22); //编译错误
        String str2 = new ArrayList<String>().get(0); //返回类型就是String  
    }
} 
  • ArrayList<String> list = new ArrayList<String>(),初始化和引用都给定了具体类型以String,注意这里必须是一样的。这是最常用的写法,编译器将执行检查(list1.add("str")处编译检查通过,list.add(1)编译检查通不过),并添加隐式的类型转换(String str1 = list1.get(0)处)。另外有个知识点,这种写法编译器会提示有种更简洁的写法:ArrayList<String> list = new ArrayList<>()
  • ArrayList<String> list1 = new ArrayList(),虽然初始化时没有给定具体类型,但由于引用类型给了具体类型以String,所以当使用这个引用时,会执行同样的编译期检查。
  • ArrayList list2 = new ArrayList<String>(),虽然初始化时给定了具体类型以String,但由于引用类型却没有给具体类型,由于之后都是对这个引用的对象调用方法,而这种引用属于原生类型,所以没有了编译期检查(add什么类型进去都可以了),而且原生类型里所有的类型参数被替换以Object,所以get函数返回的是Object类型。
  • 接下来的三行代码,对刚初始化的ArrayList调用方法,此时没有引用,则这里应该直接分析其给定的具体类型。比如new ArrayList<String>()只能add字符串,new ArrayList<String>().get(0)返回的也是字符串。

所以说,泛型类对象的引用类型(是raw type,还是给了类型参数以具体类型)才对编译期检查起作用。
另外,代码有运行时异常,但这无所谓,因为本文关注点在于编译期检查。

发布了171 篇原创文章 · 获赞 130 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/anlian523/article/details/100856526