• java里程碑之泛型--深入理解泛型


    所谓泛型,就是允许在定义类,接口,方法时使用类型形参,这个类型形参将在声明变量,创建对象,调用方法的时候动态的指定。JAVA5之后修改了集合中所有的接口和类,为这些接口和类都提供了泛型的支持。
    关于泛型的底层,我们先来看看一段代码:
    public class Test
    {
    	public static void main(String[] args)
    	{
    		List<String> strList = Lists.newArrayList();
    		List<Integer> intList = Lists.newArrayList();
    		System.out.println(strList.getClass() == intList.getClass());
    	}
    }

    上面的代码new了2个list,然后判断这2个list的类是不是同一个?如果没有深入的了解过泛型,我们很容易以为上面的代码输出是false,但是运行上面的代码,实际输出是true。为什么呢?因为不管泛型的实际类型是什么,他们在运行时总是同样的类。比如下面的代码:
    public class Test<T>
    {
    	public static void main(String[] args)
    	{
    		Test<String> test = new Test<>();
    		List<String> strList = Lists.newArrayList();
    		List<Integer> intList = Lists.newArrayList();
    		System.out.println(strList.getClass() == intList.getClass());
    	}
    }
    我们在编译之后,用反编译打开jar包看一下,代码的源码如下:
    public class Test<T>
    {
      public static void main(String[] args)
      {
        Test test = new Test();
        List strList = Lists.newArrayList();
        List intList = Lists.newArrayList();
        System.out.println(strList.getClass() == intList.getClass());
      }
    }

    从上面的2段代码我们得出一个结论,不管为泛型的类型形参传入哪一种类型实参,对于java来说,他们都被当成了同一个类来处理,在内存中也使用同一块内存空间。所以这里有2个注意的地方;
    1),在静态方法,静态初始化块,静态变量的声明和初始化中都不允许使用类型形参。具体看下面的代码演示:
    public class Test<T>
    {
    	//实例属性,实例方法是可以的,具体的T就是初始化这个类时候传入的形参。以下代码正常
    	T name;
    	public void test(T id)
    	{
    		
    	}
    	//静态属性和静态方法不可以用,这个时候没有实例初始化,也就是说这个T很有可能还没有传入。以下代码出错
    	static T id;
    	public static void test(T id)
    	{
    		
    	}
    }

    2),在系统中并不会生成泛型类,所以instanceof运算符后不能使用泛型类。具体看下面的代码演示:
    public class Test<T>
    {
    	public void test()
    	{
    		Collection<String> list = Lists.newArrayList();
    		//下面代码正常
    		if (list instanceof ArrayList)
    		{
    
    
    		}
    		//下面代码报错,instanceof运算符后不能使用泛型
    		if (list instanceof ArrayList<String>)
    		{
    
    
    		}
    	}
    }

    总结:我们在使用泛型的时候,虽然程序只定义了一个List<E>的接口,但是在实际使用过程中我们可以传入随便的E的类型,这样子就可以产生无数多个List接口,只要为E传入不同的类型实参,系统就会多出一个新的List子接口。特别要注意的是,上面的任何一个子接口都不能被替换成一个固定的接口,比如List<String>不会替换成ListString,系统没有进行源代码复制,二级制代码中没有,磁盘和内存中都没有,也就是说这种子类我们只是可以这样子理解,但是在物理上根本不存在。
  • 相关阅读:
    MySQL缓存分类
    Babel 是干什么的
    npm是干什么的?
    在改变某一项目的svn的地址,relocate
    在搭建服务器的时候,svn最好与项目所部署的服务器分开
    简述负载均衡和CDN技术
    nginx介绍
    NideShop项目的安装部署教程
    Navicat破解
    当返回的不是单独的一种数据格式
  • 原文地址:https://www.cnblogs.com/LinkinPark/p/5232984.html
Copyright © 2020-2023  润新知