前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >再谈泛型java---上

再谈泛型java---上

作者头像
田维常
发布2019-07-16 10:06:05
3580
发布2019-07-16 10:06:05
举报

泛型入门

在JDK1.5以前是没有泛型的,那么我们通常是怎么做的呢?

代码语言:javascript
复制
public class LessJDK5Demo {
    public static void main(String[] args) {
        List list=new ArrayList();
        User user=new User(1,"zhangsan");
        list.add(user);
        User u=(User)list.get(0);
        System.out.println(u);
    }
}

可以看得出来,每次从list里取数据的时候,需要强制转换,所以这里就很容易报异常:ClassCastException.

1

编译时不检查类型的异常

代码语言:javascript
复制
public static void main(String[] args) {
        List list=new ArrayList();
        list.add("Java后端技术栈");
        list.add(1);
        System.out.println((String) list.get(1));
    }

运行:

代码语言:javascript
复制
Exception in thread "main" java.lang.ClassCastException: 
  java.lang.Integer cannot be cast to java.lang.String
  at com.lawt.swaggerdemo.generic.LessJDK5Demo.main(LessJDK5Demo.java:18)

2

使用泛型

JDK1.5以后引入了“参数化类型”的概念,运行程序在创建集合的时候指定集合元素的类型,比如:List<String> 说明这个list只能存放字符类型的对象,Java的参数化类型被称为泛型

代码语言:javascript
复制
public class LessJDK5Demo {
    public static void main(String[] args) {
        List<String> list=new ArrayList<String>();
        list.add("Java后端技术栈");
        list.add(1);
        list.forEach(str-> System.out.println(str.length()));
    }
}

这样就保证了不会出现类型强转异常。

3

增强的菱形语法

在JDK1.7以前,如果使用带泛型的接口、类定义变量,那么调用构造器创建对象时构造器的后面必须带泛型,这样有点闲的多余,比如以下两个使用案例:

代码语言:javascript
复制
List<String> strings=new ArrayList<String>();
Map<String ,Integer> map=new HashMap<String ,Integer>(2);

从JDK1.7开始,上面的两个使用案例可以改写成:

代码语言:javascript
复制
//Java自动推断出ArrayList的<>里应该是String
List<String> strings=new ArrayList<>();
Map<String ,Integer> map=new HashMap<>(2);

以上把两个尖括号并排放在一起非常想菱形,所以这里也就被称之为“菱形”语法。

JDK1.8对菱形语法做了增加,它甚至允许在创建匿名内部类的时候使用菱形语法,Java课根据上下问推断匿名内部类中泛型的类型,比如:

代码语言:javascript
复制
interface Foo<T>{
   void  test(T t);
}
public class Test {
    public static void main(String[] args) {
        Foo<String> f=new Foo<String>() {
            @Override
            public void test(String s) {
                System.out.println(s);
            }
        };
        Foo<?> foo1=new Foo<Object>() {
            @Override
            public void test(Object o) {
                System.out.println(o);
            }
        };
        Foo<? extends Number> fn=new Foo<Number>() {
            @Override
            public void test(Number number) {
                System.out.println(number);
            }
        };
    }
}

深入泛型

所谓泛型:就是允许在定义类、接口、方法时使用类型参数,这个类型参数(泛型)将在声明变量、创建对象、调用方法时动态指定(即时传入实际的类型参数)。

1

定义泛型接口、类

以下是JDK1.5版本改写后List/Set/Map的代码片段:

代码语言:javascript
复制
//定义接口时指定了一个泛型形参,该形参为E
public interface List<E> {
  //在该接口里,E可作为类型使用
   Iterator<E> iterator();
    <T> T[] toArray(T[] a);
    //...
}
public interface Set<E> {
   boolean add(E e);
   //.....
}
public interface Map<K,V> {
  V put(K key, V value);
  //....
}

上面三个接口声明是比较简单的,除了尖括号中内容---这就是泛型的实质:允许在定义接口、类时声明泛型形参,泛型形参在整个接口、类体重可当成类型使用,几乎所有可使用普通类型的地方都可以使用这种泛型参型。

比如:前面的List类型时,,如果E形参传入String类型实参,则可以理解为产生了一个新类:List<String>类型,或者可以想象成生成了一个逻辑上的子类。比如:

代码语言:javascript
复制
public interface ListString  extends List{
    void add(String str);
    //.....
}

这里只是逻辑上子类,并不是物理上的。

注意

包含泛型声明的类型可以在定义变量、创建对象时传入一个类型实参,从而可以动态低生成多个逻辑上的子类,但是这种子类在物理上并不存在。

2

从泛型派生子类

代码语言:javascript
复制
public class Person<T> {
    private T info;

    public Person(T info) {
        this.info = info;
    }
    //get set ....
}

第一种方式:原始类型

代码语言:javascript
复制
public class Sub extends Person {
    public Sub(Object info) {
        super(info);
    }
}

就是说不为其指定类型也是可以的。

第二种:指定泛型参数

代码语言:javascript
复制
public class Doc extends Person<String> {
    public Doc(String info) {
        super(info);
    }
}

以上是指定泛型类型为String类型。

3

并不存在泛型类

前面说过List<String>,可以理解为List生成了一个子类List<String>,事实上也很像一个特殊List类,该List只能添加Sting的集合。但是实际上系统根本没有生成什么子类class文件,而且也不把List<String>当做一个新类来处理。为什么呢?下面的代码就是很好解释:

代码语言:javascript
复制
 List<String> strings=new ArrayList<>();
 List<Integer> integers=new ArrayList<>();
 System.out.println(strings.getClass()==integers.getClass());

如果真的生成了一个新class类,那么,上面应该输出false,但是实际上输出的是true。

全部写完篇幅会很长,所以留到《再谈Java泛型---下》中继续扯;

既然在看了,就点一下吧!!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档