JavaSE-泛型(个人笔记,勿喷)

认识泛型

介绍

泛型简单介绍:约束一个类中特定元素的类型。

泛型仅仅是java的语法糖,它不会影响java虚拟机生成的汇编代码,在编译阶段,虚拟机就会把泛型的类型擦除,还原成没有泛型的代码,顶多编译速度稍微慢一些,执行速度是完全没有什么区别的.
所谓泛型指的是,在定义类、接口、方法时,同时声明了一个或者多个类型变量(如:),称为泛型类、泛型接口、泛型方法、它们统称为泛型。

作用

1.约束容器类中元素的类型。

2.如果不进行约束,类型混乱,类型转换上的不确定性和麻烦。

3.指定泛型之后,对集合中的每个元素可以统一的操作。

泛型不支持基本数据类型,只能支持对象类型(引用数据类型)

泛型的好处:在编译阶段可以避免出现一些非法的数据。

泛型的本质:把具体的数据类型传递给类型变量。

ArrayList泛型

比如我们前面学过的ArrayList类就是一个泛型类,我们可以打开API文档看一下ArrayList类的声明。

ArrayList集合的设计者在定义ArrayList集合时,就已经明确ArrayList集合时给别人装数据用的,但是别人用ArrayList集合时候,装什么类型的数据他不知道,所以就用一个表示元素的数据类型。

当别人使用ArrayList集合创建对象时,new ArrayList就表示元素为String类型,new ArrayList表示元素为Integer类型。

自定义泛型类

接下来我们学习一下自定义泛型类,但是有一些话需要给大家提前交代一下:泛型类,在实际工作中一般都是源代码中写好,我们直接用的,就是ArrayList这样的,自己定义泛型类是非常少的。

格式

//这里的其实指的就是类型变量,可以是一个,也可以是多个。
public class 类名{

}

实例

接下来,我们自己定义一个MyArrayList泛型类,模拟一下自定义泛型类的使用。注意这里重点仅仅只是模拟泛型类的使用,所以方法中的一些逻辑是次要的,也不会写得太严谨。

//定义一个泛型类,用来表示一个容器
//容器中存储的数据,它的类型用先代替用着,等调用者来确认的具体类型。
public class MyArrayList{
    private Object[] array = new Object[10];
    //定一个索引,方便对数组进行操作
    private int index;

    //添加元素
    public void add(E e){
        array[index]=e;
        index++;
    }

    //获取元素
    public E get(int index){
        return (E)array[index];
    }
}

接下来,我们写一个测试类,来测试自定义的泛型类MyArrayList是否能够正常使用

public class Test{
    public static void main(String[] args){
        //1.确定MyArrayList集合中,元素类型为String类型
        MyArrayList list = new MyArrayList<>();
        //此时添加元素时,只能添加String类型
        list.add("张三");
        list.add("李四");

         //2.确定MyArrayList集合中,元素类型为Integer类型
        MyArrayList list1 = new MyArrayList<>();
        //此时添加元素时,只能添加String类型
        list.add(100);
        list.add(200);

    }
}

自定义泛型接口

在上一节中,我们已经学习了自定义泛型类,接下来我们学习一下泛型接口。泛型接口其实指的是在接口中把不确定的数据类型用<类型变量>表示。定义格式如下:

//这里的类型变量,一般是一个字母,比如
public interface 接口名<类型变量>{

}

比如,我们现在要做一个系统要处理学生和老师的数据,需要提供2个功能,保存对象数据、根据名称查询数据,要求:这两个功能处理的数据既能是老师对象,也能是学生对象。

首先我们得有一个学生类和老师类

public class Teacher{

}
public class Student{

}

我们定义一个Data泛型接口,T表示接口中要处理数据的类型。

public interface Data{
    public void add(T t);

    public ArrayList getByName(String name);
}

接下来,我们写一个处理Teacher对象的接口实现类

//此时确定Data中的E为Teacher类型,
//接口中add和getByName方法上的T也都会变成Teacher类型
public class TeacherData implements Data{
       public void add(Teacher t){

    }

    public ArrayList getByName(String name){

    }
}

接下来,我们写一个处理Student对象的接口实现类

//此时确定Data中的E为Student类型,
//接口中add和getByName方法上的T也都会变成Student类型
public class StudentData implements Data{
       public void add(Student t){

    }

    public ArrayList getByName(String name){

    }
}

泛型方法

public class Test{
    public static void main(String[] args){
        //调用test方法,传递字符串数据,那么test方法的泛型就是String类型
        String rs = test("test");

        //调用test方法,传递Dog对象,那么test方法的泛型就是Dog类型
        Dog d = test(new Dog()); 
    }

    //这是一个泛型方法表示一个不确定的数据类型,由调用者确定
    public static  test(T t){
        return t;
    }
}

泛型限定

接着,我们来学习一个泛型的特殊用法,叫做泛型限定。泛型限定的意思是对泛型的数据类型进行范围的限制。有如下的三种格式

表示任意类型
表示指定类型或者指定类型的子类
表示指定类型或者指定类型的父类
下面我们演示一下,假设有Car作为父类,BENZ,BWM两个类作为Car的子类,代码如下

class Car{}
class BENZ extends Car{}
class BWN extends Car{}

public class Test{
    public static void main(String[] args){
        //1.集合中的元素不管是什么类型,test1方法都能接收
        ArrayList list1 = new ArrayList<>();
        ArrayList list2 = new ArrayList<>();
        ArrayList list3 = new ArrayList<>();
        test1(list1);
        test1(list2);
        test1(list3);

        //2.集合中的元素只能是Car或者Car的子类类型,才能被test2方法接收
        ArrayList list4 = new ArrayList<>();
        ArrayList list5 = new ArrayList<>();
        test2(list4);
        test2(list5);

        //2.集合中的元素只能是Car或者Car的父类类型,才能被test3方法接收
        ArrayList list6 = new ArrayList<>();
        ArrayList list7 = new ArrayList<>();
        test3(list6);
        test3(list7);
    }

    public static void test1(ArrayList list){

    }

    public static void test2(ArrayList list){

    }

       public static void test3(ArrayList list){

    }
} 
  

泛型擦除


泛型只能编译阶段有效,一旦编译成字节码,字节码中是不包含泛型的。而且泛型只支持引用数据类型,不支持基本数据类型。

你可能感兴趣的:(日常学习笔记,笔记,java)