Java泛型

概念

什么是泛型(Generic):

泛型就相当于标签

形式:<>

集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object。
JDK1.5之 后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。

Collection, List, ArrayList 这个就是类型参数,即泛型。

没有泛型的时候使用集合:
public class Test01 {
    //这是main方法,程序的入口
    public static void main(String[] args) {
        //创建一个ArrayList集合,向这个集合中存入学生的成绩:
        ArrayList al = new ArrayList();
        al.add(91);
        al.add(13);
        al.add(39);
        al.add(6);
        al.add(83);
        al.add("张三");
        //对集合遍历查看:
        for(Object obj:al){
            System.out.println(obj);
        }
    }
}

如果不使用泛型的话,有缺点:

一般我们在使用的时候基本上往集合中存入的都是相同类型的数据–》便于管理,所以现在什么引用数据类型都可以存入集合,不方便!

JDK1.5以后开始使用泛型,集合中使用泛型:
public class Test01 {
    //这是main方法,程序的入口
    public static void main(String[] args) {
        //创建一个ArrayList集合,向这个集合中存入学生的成绩:
        //加入泛型的优点:在编译时期就会对类型进行检查,不是泛型对应的类型就不可以添加入这个集合。
        ArrayList<Integer> al = new ArrayList<Integer>();
   al.add(91);
        al.add(13);
        al.add(39);
        al.add(6);
        al.add(83);
        /*al.add("张三");
        al.add(1.8);*/
        //对集合遍历查看:
        /*for(Object obj:al){
            System.out.println(obj);
        }*/
        for(Integer i:al){
            System.out.println(i);
        }
    }
}
泛型总结:
  1. 泛型实际就是 一个<>引起来的 参数类型,这个参数类型 具体在使用的时候才会确定具体的类型。在这里插入图片描述

  2. 使用了泛型以后,可以确定集合中存放数据的类型,在编译时期就可以检查出来。

  3. 使用泛型你可能觉得麻烦,实际使用了泛型才会简单,后续的遍历等操作简单。

  4. 泛型的类型:都是引用数据类型,不能是基本数据类型。

  5. ArrayList al = new ArrayList();在JDK1.7以后可以写为:
    ArrayList al = new ArrayList<>(); --<> —钻石运算符

自定义泛型结构

泛型类,泛型接口
1.泛型类的定义和实例化:
/**
 * GenericTes就是一个普通的类
 * GenericTest<E> 就是一个泛型类
 * <>里面就是一个参数类型,但是这个类型是什么呢?这个类型现在是不确定的,相当于一个占位
 * 但是现在确定的是这个类型一定是一个引用数据类型,而不是基本数据类型
 */
public class GenericTest<E> {
    int age;
    String name;
    E sex;
    public void a(E n){
    }
    public void b(E[] m){
    }
}
class Test{
    //这是main方法,程序的入口
    public static void main(String[] args) {
        //GenericTest进行实例化:
        //(1)实例化的时候不指定泛型:如果实例化的时候不明确的指定类的泛型,那么认为此泛型为Object类型
        GenericTest gt1 = new GenericTest();
        gt1.a("abc");
        gt1.a(17);
        gt1.a(9.8);
        gt1.b(new String[]{"a","b","c"});
        //(2)实例化的时候指定泛型:---》推荐方式
        GenericTest<String> gt2 = new GenericTest<>();
        gt2.sex = "男";
        gt2.a("abc");
        gt2.b(new String[]{"a","b","c"});
        
    }
}
2.继承情况:
  1. 父类指定泛型:

    class SubGenericTest extends GenericTest<Integer>{
    }
    class Demo{
        //这是main方法,程序的入口
        public static void main(String[] args) {
            //指定父类泛型,那么子类就不需要再指定泛型了,可以直接使用
            SubGenericTest sgt = new SubGenericTest();
            sgt.a(19);
        }
    }
    
  2. 父类不指定泛型:如果父类不指定泛型,那么子类也会变成一个泛型类,那这个E的类型可以在创建子类对象的时候确定:

    class SubGenericTest2<E> extends GenericTest<E>{
    }
    
    class Demo2{
        //这是main方法,程序的入口
        public static void main(String[] args) {
            SubGenericTest2<String> s = new  SubGenericTest2<>();
            s.a("abc");
            s.sex = "女";
        }
    }
    
  3. 应用场合:

    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
    }
    
  4. 细节:

    1. 泛型类可以定义多个参数类型

      public class Generic<A, B, C> {
      
      	A age;
      	B name;
      	C sex;
      
      }
      
    2. 泛型类的构造器的写法

      public class Generic<A, B, C> {
      	A age;
      	B name;
      	C sex;
      	public Generic(){
      	}
      }
      
    3. 不同的泛型的引用类型不可以相互赋值:

      	public static void main(String[] args) {
      		ArrayList<Object> ar1= new ArrayList<>();
      		ArrayList<String> ar2= new ArrayList<>();
      		ArrayList<Integer> ar3= new ArrayList<>();
      		//此处编译报错
      		ar1=ar2;
      		ar2=ar3;
      	}
      
    4. 泛型如果不指定,那么就会被擦除,反应对应的类型为Object类型:

      public static void main(String[] args) {
      		Generic c= new Generic();
      		c.a("dafs");
      		c.a(1);
      	}
      
    5. 泛型类中的静态方法不能使用类的泛型:

      public class Generic<E> {
      	E name;
      	public Generic(){
      	}
      	// 此处会编译报错
      	public static void  a(E n){
      	}
      }
      
    6. 不能直接使用E[]的创建:

      public class Generic<E> {
      	E name;
      	public Generic(){
      	}
      	public  void  a(E n){
      		// 此处会编译报错
      		// E[] e=new E[10];
      		E[] e= (E[])new Object[10]; //只能通过Object
      
      	}
      }
      
泛型方法

/**
 * 1.什么是泛型方法:
 * 不是带泛型的方法就是泛型方法
 * 泛型方法有要求:这个方法的泛型的参数类型要和当前的类的泛型无关
 * 换个角度:
 * 泛型方法对应的那个泛型参数类型 和  当前所在的这个类 是否是泛型类,泛型是啥  无关
 * 2.泛型方法定义的时候,前面要加上<T>
 *     原因:如果不加的话,会把T当做一种数据类型,然而代码中没有T类型那么就会报错
 * 3.T的类型是在调用方法的时候确定的
 * 4.泛型方法可否是静态方法?可以是静态方法
 */
public class TestGeneric<E> {
    //不是泛型方法 (不能是静态方法)
    public static void a(E e){
    }
    //是泛型方法
    public static <T>  void b(T t){
    }
}
class Demo{
    //这是main方法,程序的入口
    public static void main(String[] args) {
        TestGeneric<String> tg = new TestGeneric<>();
        tg.a("abc");
        tg.b("abc");
        tg.b(19);
        tg.b(true);
    }
}
泛型参数存在继承关系的情况
public static void main(String[] args) {
		Object o = new Object();
		String s = new String();
		o=s; //多态的一种形式

		Object[] arr= new Object[10];
		String[] strings=new String[10];
		arr= strings;//多态的一种形式

		List<Object> list= new ArrayList<>();
		List<String> list1= new ArrayList<>();
		list=list1; //编译报错
	}

总结:A和B是子类父类的关系,但是G和G 不存在继承关系。是并列关系

通配符
1.在没有通配符的时候:

下面的a方法,相当于方法的重复定义,报错

public class Test {
    /*public void a(List<Object> list){
    }
    public void a(List<String> list){
    }
    public void a(List<Integer> list){
    }*/
}
2.引入通配符:
public class Demo {
    //这是main方法,程序的入口
    public static void main(String[] args) {
        List<Object> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        List<Integer> list3 = new ArrayList<>();
        List<?> list = null;
        list = list1;
        list = list2;
        list = list3;
    }
}

发现: A 和 B是子类父类的关系,G和G不存在子类父类关系,是并列的

加入通配符?后,G<?>就变成了 G和G的父类

3.使用通配符:
public class Test {
    /*public void a(List<Object> list){
    }
    public void a(List<String> list){
    }
    public void a(List<Integer> list){
    }*/
    public void a(List<?> list){
        //内部遍历的时候用Object即可,不用?
        for(Object a:list){
            System.out.println(a);
        }
    }
}
class T{
    //这是main方法,程序的入口
    public static void main(String[] args) {
        Test t = new Test();
        t.a(new ArrayList<Integer>());
        t.a(new ArrayList<String>());
        t.a(new ArrayList<Object>());
    }
}
4.查看API中应用位置:在这里插入图片描述
5.使用通配符细节
public class Test {
    public void a(List<?> list){
        //1.遍历:
        for(Object a:list){
            System.out.println(a);
        }
        //2.数据的写入操作 :
        //list.add("abc");-->出错,不能随意的添加数据
        list.add(null);
        //3.数据的读取操作:
        Object s = list.get(0);
    }
}
class T{
    //这是main方法,程序的入口
    public static void main(String[] args) {
        Test t = new Test();
        t.a(new ArrayList<Integer>());
        t.a(new ArrayList<String>());
        t.a(new ArrayList<Object>());
    }
}

泛型受限

public class Test {
    //这是main方法,程序的入口
    public static void main(String[] args) {
        //a,b,c三个集合是并列的关系:
        List<Object> a = new ArrayList<>();
        List<Person> b = new ArrayList<>();
        List<Student> c = new ArrayList<>();
        /*开始使用泛型受限:泛型的上限
        List<? extends Person>:
        就相当于:
        List<? extends Person>是List<Person>的父类,是List<Person的子类>的父类
         */
        List<? extends Person> list1 = null;
        /*list1 = a;
        list1 = b;
        list1 = c;*/
        /*开始使用泛型受限:泛型的下限
        List<? super Person>
        就相当于:
        List<? super Person>是List<Person>的父类,是List<Person的父类>的父类
         */
        List<? super Person> list2 = null;
        list2 = a;
        list2 = b;
        list3 = c;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编码指南针

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值