第09章_java泛型

9.泛型

9.1 泛型的理解

/*
1.泛型的定义:允许在定义类、接口时通过一个标识表示类中某些结构的类型(属性、方法形参、方法的返回值等)
			习惯上,我们把这个类/接口称为泛型类/泛型接口,把这个标识称为泛型,泛型类型将在使用时确定
2.泛型的引入背景:
	2.1 在JDK1.5之前,集合在声明的时候不能确定存什么类型的元素,所以只能把元素类型设为Object。
	2.2 JDK1.5之后,我们可以把元素类型设为泛型,这个时候除了元素的类型不确定,其他的部分是确定的,例如:关于这个元素如何保存,如何管理等是确定的。
 */

9.2 在集合中的使用泛型

public class Main {
/*
1.在集合中使用泛型的总结:
    1.1 集合接口或集合类在jdk5.0时都修改为了泛型类/泛型接口
    1.2 在实例化集合类时,可以指明泛型类型。泛型类型必须是类,不能是基本数据类型,需要使用基本数据类型就拿对应包装类替换
    1.3 如果实例化集合类时,没有指明泛型类型,那么泛型类型默认为java.lang.Object
2.没有泛型之前集合的使用
 */
    @Test
    public void  test1(){
        ArrayList arrayList = new ArrayList();
        //需求:存放学生的成绩
        arrayList.add(78);
        arrayList.add(76);
        arrayList.add(89);
        arrayList.add(88);
        //问题一:类型不安全
        arrayList.add("Tom");
        for (Object score : arrayList) {
            //问题二:强转时,可能出现ClassCastException
            Integer stuScore = (Integer) score;
            System.out.println(stuScore);
        }
    }
/*
3.在集合中使用泛型:
	3.1 例子1
 */
    @Test
    public void test2(){
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(78);
        arrayList.add(76);
        arrayList.add(89);
        arrayList.add(88);
        //编译时,就会进行类型检查,保证数据的安全
        //编译错误
//        arrayList.add("Tom");
        //方式一:
        for (Integer integer : arrayList) {
            //避免了强转操作
            System.out.println(integer);
        }
        //方式二:
        Iterator<Integer> iterator = arrayList.iterator();
        while (iterator.hasNext()){
            Integer next = iterator.next();
            System.out.println(next);
        }
    }
/*
	3.2 例子2
 */
    @Test
    public void test3(){
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Tom",87);
        map.put("Jerry",87);
        map.put("Jack",67);
        //编译时,就会进行类型检查,保证数据的安全
        //编译错误
//        map.put(123,"ABC");
        //泛型的嵌套
        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+"---"+value);
        }
    }
}
public class Main {
/*
5.练习:定义一个Employee类,该类包含:
       private成员变量name,age,birthday,其中birthday为MyDate类的对象;
       并为每一个属性定义getter, setter方法;
       并重写toString方法输出name, age, birthday
    5.1 使用Employee实现Comparable接口,并按name排序
 */
    @Test
    public void test1(){
        TreeSet<Employee> employees = new TreeSet<>();
        employees.add(new Employee("AA",25,new MyDate(1981,1,1)));
        employees.add(new Employee("BB",35,new MyDate(2001,2,1)));
        employees.add(new Employee("CC",15,new MyDate(2006,3,1)));
        employees.add(new Employee("DD",45,new MyDate(2007,4,1)));
        Iterator<Employee> iterator = employees.iterator();
        while (iterator.hasNext()){
            Employee next = iterator.next();
            System.out.println(next);
        }
    }
/*
    5.2 创建TreeSet时传入Comparator对象,按照生日日期的先后排序
 */
    @Test
    public void test2(){
        TreeSet<Employee> employees = new TreeSet<>(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                int year1 = o1.getBirthday().getYear();
                int year2 = o2.getBirthday().getYear();
                int y = year1 - year2;
                if (y != 0) {
                    return y;
                }
                int month1 = o1.getBirthday().getMonth();
                int month2 = o2.getBirthday().getMonth();
                int m = month1 - month2;
                if (m != 0) {
                    return m;
                }
                int day1 = o1.getBirthday().getDay();
                int day2 = o2.getBirthday().getDay();
                return day1 - day2;
            }
        });
        employees.add(new Employee("AA",25,new MyDate(1981,1,1)));
        employees.add(new Employee("BB",35,new MyDate(2001,2,1)));
        employees.add(new Employee("CC",15,new MyDate(2006,3,1)));
        employees.add(new Employee("DD",45,new MyDate(2007,4,1)));
        Iterator<Employee> iterator = employees.iterator();
        while (iterator.hasNext()){
            Employee next = iterator.next();
            System.out.println(next);
        }
    }
}
class Employee implements Comparable<Employee>{
    String name;
    int age;
    MyDate birthday;

    public Employee(String name, int age, MyDate birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public MyDate getBirthday() {
        return birthday;
    }

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

    public void setAge(int age) {
        this.age = age;
    }

    public void setBirthday(MyDate birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }

    @Override
    public int compareTo(Employee o) {
        return this.name.compareTo(o.name);
    }
}
class MyDate{
    private int year;
    private int month;
    private int day;

    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public int getYear() {
        return year;
    }

    public int getMonth() {
        return month;
    }

    public int getDay() {
        return day;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public void setDay(int day) {
        this.day = day;
    }

    @Override
    public String toString() {
        return "MyDate{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }
}

9.3 自定义泛型类、泛型接口、泛型方法

/*
1.自定义泛型类、泛型接口
 */
class Order<T>{
    String name;
    int id;
    T orderT;

    public Order() {
    }

    public Order(String name, int id, T orderT) {
        this.name = name;
        this.id = id;
        this.orderT = orderT;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public T getOrderT() {
        return orderT;
    }

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

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

    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }

    @Override
    public String toString() {
        return "Order{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", orderT=" + orderT +
                '}';
    }
}
class SubOrder extends Order<Integer>{//SubOrder不是泛型类
}
class SubOrder1<T> extends Order<T>{//SubOrder1<T>仍然是泛型类

}
public class Main {
    @Test
    public void test1(){
        //1.1 如果定义的是泛型类,建议在实例化时指明泛型类型
        Order<String> order1 = new Order<>("AA", 1001, "order:AA");
        order1.setOrderT("AA:order");
        String orderT = order1.getOrderT();
    }
    @Test
    public void test2(){
        //1.2 子类在继承指明了泛型类型的父类时,则实例化子类对象时就不需要再指明泛型类型
        SubOrder subOrder = new SubOrder();
        subOrder.setOrderT(123);
        Integer orderT = subOrder.getOrderT();
        //1.3 子类在继承未指明泛型类型的父类时,则实例化子类对象时可以自行指明泛型类型
        SubOrder1<String> subOrder1 = new SubOrder1<>();
        subOrder1.setOrderT("order2...");
        String orderT1 = subOrder1.getOrderT();
    }
}
/*
2.类的泛型的使用细节
 */
class Order<T>{
    String name;
    int id;
    T orderT;
    //类的静态结构不能使用类的泛型:因为类的泛型类型是在实例化类时才确定的,而静态结构的加载在类的实例化之前
//    static T gender;
//    static {
//        T gender;
//    }
//    public static void show(T gender){
//        System.out.println(gender);
//    }
    public Order(){
        //类的非静态结构都可以使用类的泛型
        //编译不通过
//       T[] arr=new T[10];
        //编译通过
        T[] arr= (T[]) new Object[10];
    }
    public Order(String name, int id, T orderT) {
        this.name = name;
        this.id = id;
        this.orderT = orderT;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public T getOrderT() {
        return orderT;
    }

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

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

    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }

    @Override
    public String toString() {
        return "Order{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", orderT=" + orderT +
                '}';
    }
    public void test(){
        ArrayList<String> list1=null;
        ArrayList<Integer> list2=null;
        //相同类,不同泛型类型的引用不能相互赋值
//        list1=list2;
    }
    public void show(){
        //编译不通过
//        try {
//
//        }catch (T t){
//
//        }
    }

}
//异常类不能使用泛型
/*
class MyException<T> extends Exception{

}
*/
/*
3.自定义泛型方法
 */
class Order<T>{
    String name;
    int id;
    T orderT;

    public Order() {
    }

    public Order(String name, int id, T orderT) {
        this.name = name;
        this.id = id;
        this.orderT = orderT;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public T getOrderT() {
        return orderT;
    }

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

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

    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }

    @Override
    public String toString() {
        return "Order{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", orderT=" + orderT +
                '}';
    }
    //3.1 泛型方法有它自己的泛型,如果没有,那就不是泛型方法
    //3.2 泛型方法的泛型与其所在的类的泛型没有任何关系。换句话说,泛型方法所属的类是不是泛型类都没有关系
    //3.1和3.2保证了泛型方法的泛型类型可以在被调用时才确定,且与类的泛型类型是否确定无关
    public <E> List<E> copyFromArrayToList(E[] arr){
        ArrayList<E> list = new ArrayList<>();
        for (E e : arr) {
            list.add(e);
        }
        return list;
    }
}
public class Main {
    @Test
    public void test1(){
        Order<String> order = new Order<>();
        Integer[] arr=new Integer[]{1,2,3,4};
        //3.3 泛型方法的泛型类型在被调用时指明
        List<Integer> list = order.copyFromArrayToList(arr);
    }
}
class Order<T>{
    String name;
    int id;
    T orderT;

    public Order() {
    }

    public Order(String name, int id, T orderT) {
        this.name = name;
        this.id = id;
        this.orderT = orderT;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public T getOrderT() {
        return orderT;
    }

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

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

    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }

    @Override
    public String toString() {
        return "Order{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", orderT=" + orderT +
                '}';
    }
    //非静态的泛型方法可以使用类的泛型:因为类的泛型类型是在实例化类时确定的,而非静态的泛型方法的加载在类的实例化之后
    public <E> List<E> copyFromArrayToList1(E[] arr,T orderT){
        System.out.println(orderT);
        ArrayList<E> list = new ArrayList<>();
        for (E e : arr) {
            list.add(e);
        }
        return list;
    }
    //泛型方法可以是静态的,因为:3.1和3.2保证了泛型方法的泛型类型可以在被调用时才确定,且与类的泛型类型是否确定无关
    public static <E> List<E> copyFromArrayToList2(E[] arr){
        ArrayList<E> list = new ArrayList<>();
        for (E e : arr) {
            list.add(e);
        }
        return list;
    }
    //但是静态的泛型方法不可以使用类的泛型:因为类的泛型类型是在实例化类时确定的,而静态的泛型方法的加载在类的实例化之前
//    public static <E> List<E> copyFromArrayToList3(E[] arr,T orderT){
//        System.out.println(orderT);
//        ArrayList<E> list = new ArrayList<>();
//        for (E e : arr) {
//            list.add(e);
//        }
//        return list;
//    }
}

9.4 泛型在继承上的体现

/*
1.类A是类B的父类时,G<A>和G<B>二者不具备子父类关系,二者是并列关系,而A<G>是B<G>的父类
 */
public class Main {
    @Test
    public void test1(){
        Object obj=new Object();
        String str=new String();
        obj=str;

        Object[] arr1=new Object[10];
        String[] arr2=new String[10];
        arr1=arr2;

        //ArrayList<Object>和ArrayList<String>不具备子父类关系
        ArrayList<Object> list1=new ArrayList<>();
        ArrayList<String> list2=new ArrayList<>();
        //编译不通过
//        list1=list2;

        //HashMap<String, Integer>是LinkedHashMap<String, Integer>的父类
        HashMap<String, Integer> hashMap = new HashMap<>();
        LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<>();
        hashMap=linkedHashMap;
		//下面两个例子也是该种情况,只不过Map和List是接口
        Map<String, Integer> map = new HashMap<>();//等价于Map<String, Integer> map = new HashMap<String, Integer>();
        List<String> list = new ArrayList<>();//等价于List<String> list = new ArrayList<String>();
    }
}

9.5 通配符

public class Main {
/*
1.通配符:?
2.类A是类B的父类,G<A>和G<B>二者共同的父类是:G<?>
 */
    @Test
    public void test1(){
        ArrayList<Object> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>();
        ArrayList<?> list3;
        list3=list1;
        list3=list2;
    }
/*
3.通配符的使用注意事项
 */
    @Test
    public void test2(){
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("AA");
        list1.add("BB");
        list1.add("CC");
        ArrayList<?> list2=list1;
/*
	3.1 添加:ArrayList<?>的对象不能向其内部添加除了null之外的数据
 */
        //编译不通过
//        list2.add("DD");
        list2.add(null);

/*
	3.2 获取:ArrayList<?>的对象允许获取数据,获取的数据类型为Object
 */
        Object o = list2.get(0);
        System.out.println(o);//AA
        System.out.println(list2.get(3));//null
    }
/*
4.有限制条件的通配符的使用
    4.1 ? extends A:G<? extends A>可以是G<A>或G<A>的子类
    4.2 ? super A:G<? super A>可以是G<A>或G<A>的父类
 */
    @Test
    public void test3(){
        ArrayList<? extends Person> list1;
        ArrayList<? super Person> list2;

        ArrayList<Student> student = new ArrayList<>();
        ArrayList<Person> person = new ArrayList<>();
        ArrayList<Object> object = new ArrayList<>();

        list1=student;
        list1=person;
        //编译不通过
//        list1=object;

        //编译不通过
//        list2=student;
        list2=person;
        list2=object;

/*
    4.3 添加:
 */
        //4.3.1 list1:无论如何编译都不通过
//        list1.add(new Student());
//        list1.add(new Student());

        //4.3.2 list2:Person及其子类编译通过
        list2.add(new Person());
        list2.add(new Student());
     
/*
    4.4 获取:
 */
        //4.4.1 list1:Person及其父类编译通过,其余编译不通过
        Object object1 = list1.get(0);
        Person p=list1.get(0);

        //4.4.2 list2:Object编译通过,其余编译不通过
        Object object2 = list2.get(0);
        
    }
}
class Person{
    String name;
    int age;
}
class Student extends Person{

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值