码迷,mamicode.com
首页 > 编程语言 > 详细

Java泛型

时间:2021-03-18 14:34:45      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:java   运行   isp   play   构造器   get   ret   hash   保存   

泛型

1.为什么要使用泛型

集合容器类在设计阶段/声明阶段不能确定这个容器实际上存放的是什么类型的数据,在jdk5.0之前只能设计为Object类型,在jdk5,0之后使用泛型来解决。因为这个时候除了元素的类型是不确定的,其他部分是确定的,比如如何保存、如何管理等。因此此时把元素的类型设计为一个参数,这个类型参数就是泛型。如Collection<E>、List<E>...这里的<E>就是类型参数,即泛型。

2.在集合中使用泛型

  1. 集合接口或者集合类在jdk5.0开始都修改为带泛型的结构。
  2. 我们在实例化集合类时,可以指明具体的泛型类型,在指明完泛型类型之后,在集合类或者接口之中定义类或者接口,内部结构(方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。比如add(E e)------>add(Integer e)。
  3. 泛型的类型必须是一个类,不能是基本数据类型,如果需要使用基本数据类型,需要使用包装类替代。
  4. 如果实例化时没有指定泛型的类型,默认类型为java.lang.Object类型。
技术图片
public class GenericTest {

    @Test
    public void test(){
        //注意:泛型的类型不能是基本数据类型
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(123);
        integers.add(123);
        integers.add(123);
        integers.add(123);
        integers.add(123);
        for (Integer integer : integers) {
            System.out.println(integer);
        }
    }
    @Test
    public void test1(){
        Map<String,Integer> map=new HashMap<>();
        map.put("Tom",120);
        map.put("Jerry",121);
        map.put("Mary",109);
        map.put("Jack",145);
        //泛型的嵌套
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> next = iterator.next();
            String key = next.getKey();
            Integer value = next.getValue();
            System.out.println("key="+key+"--->value="+value);
        }
    }
}
集合中使用泛型1

3.自定义泛型结构

泛型类、泛型接口;泛型方法

泛型类可能有多个参数,多个参数放在尖括号内,中间使用逗号隔开。比如<E1,E2,E3...>

泛型类的构造器为:public GenericClass(){}

泛型的不同引用不能相互赋值。

 

技术图片
@Test
    public void test3(){
        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        //list1=list2;不能相互赋值
    }
泛型的不同引用不能相互赋值

 

泛型如果使用就一直使用,如果不用就一直不用。

如果泛型结构是接口或者抽象类,不能创建泛型对象

jdk7之后泛型可以简化ArrayList<Integer> list=new ArrayList<>():尖括号内的泛型类型可以省略

静态方法中不能使用类的泛型

异常类不能是泛型

 

 

技术图片
public class MyError<T>{
    private int id;
    private String name;
    //类的内部结构就可以使用类的泛型
    private T myErrorT;

    public MyError() {
    }

    public MyError(String name, int id, T myErrorT) {
        this.name = name;
        this.id = id;
        this.myErrorT = myErrorT;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public T getMyErrorT() {
        return myErrorT;
    }

    public void setMyErrorT(T myErrorT) {
        this.myErrorT = myErrorT;
    }

    @Override
    public String toString() {
        return "MyError{" +
                "id=‘" + id + ‘\‘‘ +
                ", name=" + name +
                ", myErrorT=" + myErrorT +
                ‘}‘;
    }
}
自定义泛型类
技术图片
 @Test
    public void test2(){
        //如果自定义了泛型类,实例化没有指明泛型的类型,则认为此泛型类型为object类型
        //要求:如果定义了泛型类,建议在实例化时指明该泛型类型
        MyError<String> myError = new MyError();
        myError.setId(1);
        myError.setName("运行错误");
        myError.setMyErrorT("方法XXXX中出现错误");

        System.out.println(myError);
    }
使用自定义泛型类

泛型方法:

在方法中出现了泛型结构,泛型参数与类的泛型参数没有任何关系关系,换句话说,泛型方法与所属的类是不是泛型类毫无关系。

泛型方法可以声明为static,因为此时泛型参数是在调用方法时确定的,不是在实例化时确定的,和泛型类不同。

技术图片
 //泛型方法
    public <E> List<E> getList(E[] arr){
        ArrayList<E> list = new ArrayList<>();
        for (E e:arr){
            list.add(e);
        }
        return list;
    }
定义泛型方法
技术图片
 @Test
    public void test3(){
        //泛型方法的调用
        MyError<String> myError = new MyError<>();
        Integer[] arr=new Integer[]{1,2,3,4,5,6};
        //泛型方法在调用时,指明泛型参数arr的类型,与泛型类中的泛型参数(MyError<String>)无关;
        List<Integer> list = myError.getList(arr);
        System.out.println(list);
    }
调用泛型方法

 

4.泛型在继承上的体现

虽然类A是类B地父类,但是G<A>和G<B>不具备子父类关系,二者是并列关系。比如:List<Object> list1和List<String>list2,此时list2不能赋给list1.

但是A<G>和B<G>具有子父类关系,比如:List<String>和ArrayList<String>

5.通配符的使用

通配符:?

类A是类B地父类,但是G<A>和G<B>不具备子父类关系,二者是并列关系。二者共用的父类是G<?>.

对于通配符List<?> list不能在向其内部添加数据,除了null值。

 

技术图片
 public void test4(){
        List<Object> list1=null;
        List<String> list2=null;
        //list1=list2;
        //通配符
        List<?> list=null;
        list=list1;
        list=list2;
        //使用通配符之后,数据的读取和写入要求
        list2.add("AA");
        list2.add("BB");
        list2.add("CC");
        list2.add("DD");
        //添加:此时list不能在向其内部添加数据。除了添加null值
        //list.add("QQ");
        //list.add(null);
        //获取(读取):允许读取数据,读取出的数据类型为Object
        Object o = list.get(0);
        System.out.println(o);
    }
测试

 

有限制条件的通配符的使用

G<? ectends 类型A>:可以作为G<A>和G<B>的父类的,其中A是B的父类

G<? super类型A>:可以作为G<A>和G<B>的父类的,其中A是B的子类,此时可以写入数据,兼容A类型和其子类

 

 

 

Java泛型

标签:java   运行   isp   play   构造器   get   ret   hash   保存   

原文地址:https://www.cnblogs.com/summerHou/p/14551845.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!