泛型的定义,继承,通配符和综合练习(含笔记)

泛型的定义,继承,通配符和综合练习(含笔记) 1、泛型1引入在没有泛型的时候当你把一个对象放进java的集合中集合就会忘记对象的类型把所有的对象当做Object类型处理这时可以把所有的类型放进集合。因此取出集合元素后通常还需要进行强制类型转换调用子类特有功能时这种强制类型转换不仅增加了编程的复杂度还可能引发ClassCastException类型转换异常。所以java5引入了“参数化类型”即泛型Generic泛型可以在编译阶段约束操作的数据类型并进行检查。泛型的格式数据类型注意泛型只能支持引用数据类型如果要操作基本数据类型则需转换为对应包装类。扩展知识java中的泛型是伪泛型。即这个泛型只在编译期间有效它会在编译期间检查是否为该约束数据类型而当编译结束数据添加成功时集合还是会把这些数据当做Object类型来处理只不过当再次获取数据时集合的底层会把这些 Object类型的数据按照泛型进行强制转换。该行为叫做泛型的擦除。细节泛型中不能写基本数据类型只有写对应的包装类才可以.自定义类属于引用数据类型指定泛型的具体类型后传递数据时可以传入该类类型或者其子类类型.如果不写泛型默认类型是Object,泛型定义定义在类后面 泛型类定义在方法上面 泛型方法定义在接口后面 泛型接口2、泛型的定义1泛型类使用场景当一个类中某个变量的数据类型不能确定时就可以定义带有泛型的类定义泛型类时可以声明多个类型class MyClassT,E{ }格式修饰符 class 类名类型 {}举例public class ArrayListE {}创建该类对象时E就确定类型此处的E可以理解为变量但是它不是用来记录数据的而是记录数据的类型可以写成T、E、K、V等定义是不知道存什么类型下面的代码就是在你创建泛型类对象的时候把你定义的数据类型传递给E。注泛型类型个数可以是多个class MyClassT,E{ }import java.util.Arrays; import java.util.Iterator; public class Main { public static void main(String[] args) { /*MyArrayListString list new MyArrayList(); list.add(aaa); list.add(bbb); list.add(ccc); System.out.println(list);*/ MyArrayListInteger list new MyArrayList(); list.add(123); list.add(234); list.add(345); int i list.get(1).intValue(); Integer j Integer.valueOf(i); System.out.println(list.toString()); } } class MyArrayListE { Object[] obj new Object[10]; int size; //E:表示不确定的类型该类型在类名后面已经定义过了。 //e:形参的名字变量名 public boolean add(E e){ obj[size]e; return true; } public E get(int index) { return (E)obj[index]; } Override public String toString() { return Arrays.toString(obj); } }2泛型方法方法中形参类型不能确定时可以使用类名后面定义的泛型E 所有方法都能用可以在方法申明上定义自己的泛型 只有本方法能用格式修饰符类型 返回值类型 方法名(类型 变量名) {}举例当调用add方法的时候才会确定T类型public class MyArrayList {publicT boolean add(T e) {obj[size] e;return true;}}import java.util.ArrayList; public class GenericsDemo1 { public static void main(String[] args){ ArrayListString list new ArrayList(); ListUtil.addAll(list,aaa,bbb,ccc); System.out.println(list); ArrayListInteger list1 new ArrayList(); ListUtil.addAll(list1,123,234,345,456,567,678,789); System.out.println(list1); } } class ListUtil { private ListUtil(){} //E...e可变参数底层是一个数组可以通过遍历获取每个元素。 public staticE void addAll(ArrayListE list, E...e){ for (E element : e) { list.add(element); } } }3泛型接口当一个接口中类型不确定时可以用在接口名后面加泛型格式修饰符 interface 接口名类型 {}举例public interface ListE {}重点如何使用一个带泛型的接口方式一实现类给出具体类型方式二实现类延续泛型创建对象时在确定方式一import java.util.*; public class GenericsDemo2 { public static void main(String[] args){ MyArrayList2 list new MyArrayList2();//实现类已经告诉具体类型所以这里不用再用泛型 list.add(aaa); list.add(bbb); list.add(ccc); System.out.println(list); } } class MyArrayList2 implements ListString { Override public boolean add(String stirng) { return false; } }方法二import java.util.*; public class GenericsDemo3 { public static void main(String[] args) { //实现类延续接口泛型不确定实现类是什么类型此时需传入类型使用泛型 MyArrayList3String list new MyArrayList3(); list.add(aaa); list.add(bbb); list.add(ccc); System.out.println(list); } } class MyArrayList3E implements ListE { Override public boolean add(E e) { return false; } }3、泛型的继承和通配符1泛型的继承泛型不具备继承性但是数据具备继承性。所以说指定泛型的具体类型后传递数据时可以传入该类类型或者其子类类型.因为数据具备继承性。import java.time.Year; import java.util.ArrayList; public class GenericsDemo4 { public static void main(String[] args){ ArrayListYe list1 new ArrayList(); ArrayListFu list2 new ArrayList(); ArrayListZi list3 new ArrayList(); method(list1); //下面调用方法会报错因为泛型不具备继承性 // method(list2); // method(list3); //下面说明数据具备继承性 list1.add(new Ye()); list1.add(new Fu()); list1.add(new Zi()); } //此时泛型里面写的是什么类型那么只能传递什么类型的数据。 public static void method(ArrayListYe list){ } } class Ye { } class Fu extends Ye { } class Zi extends Fu { }2泛型的通配符引入下面代码中泛型方法有一个小弊端此时他可以接受任意的数据类型此时我们想要限定该方法的类型所以就可以用泛型里面的通配符“”实现。通配符也表示不确定的类型它可以进行类型的限定 extends E 表示可以传递E或者E所有的子类型 super E表示可以传递E或者E所有的父类类型举例1public static void method(ArrayList? list){}等价于public staticE void method(ArrayListE list){}因为表示不确定的类型2public static void method(ArrayList? Extends Ye list){} 表示可以传递E或者E所有的子类3public static void method(ArrayList? super Zi list){} 表示可以传递Zi或者Zi所有的父类应用场景如果我们定义类、方法、接口的时候如果类型不确定、就可以定义泛型类、泛型方法。泛型接口。如果类型不确定但是能知道以后只能传递某个继承体系中的就可以使用泛型的通配符。泛型的通配符关键点可以限定类型的范围。import java.util.ArrayList; public class GenericsDemo5 { public static void main(String[] args) { ArrayListYee list1 new ArrayList(); ArrayListFuu list2 new ArrayList(); ArrayListZii list3 new ArrayList(); ArrayListStudent list4 new ArrayList(); method(list1); method(list2); method(list3); method(list4); } //泛型方法有一个小弊端此时他可以接受任意的数据类型。 public staticE void method(ArrayListE list){ } //可以传递Ye和其所有的子类型FuZi. public static void method(ArrayList? Extends Ye list){ } //可以传递Zi和其所有的父类型FuYe public static void method(ArrayList? super Zi list){ } } class Yee { } class Fuu extends Yee { } class Zii extends Fuu { } class Student { }3综合练习import java.util.ArrayList; public class GenericsDemo6 { public static void main(String[] args) { ArrayListBossCat list1 new ArrayList(); ArrayListLihuaCat list2 new ArrayList(); ArrayListTaidiDog list3 new ArrayList(); ArrayListHashiDog list4 new ArrayList(); keepPer(list1); keepPer(list2); keepPer(list3); keepPer(list4); } public static void keepPer(ArrayList? extends Animal list){ } public static void keepPer(ArrayList? extends Cat list){ } public static void keepPer(ArrayList? extends Dog list){ } public static void keepPer(ArrayList? super BossCat list){ } public static void keepPer(ArrayList? super TaidiDog list){ } } class Animal { private String name; private int age; public Animal(){} public Animal(String name, int age) { this.name name; this.age age; } public int getAge() { return age; } public void setAge(int age) { this.age age; } public String getName() { return name; } public void setName(String name) { this.name name; } public void eat() { } } class Cat extends Animal { public Cat(String name, int age) { super(name, age); } } class Dog extends Animal { public Dog(String name, int age) { super(name, age); } } class BossCat extends Cat { public BossCat(String name, int age) { super(name, age); } Override public void eat() { System.out.println(一只叫做 getName() 的 getAge() 岁的波斯猫正在吃小饼干); } } class LihuaCat extends Cat { public LihuaCat(String name, int age) { super(name, age); } Override public void eat() { System.out.println(一只叫做 getName() 的 getAge() 岁的狸花猫正在吃鱼); } } class TaidiDog extends Dog { public TaidiDog(String name, int age) { super(name,age); } Override public void eat() { System.out.println(一只叫做 getName() 的 getAge() 岁的泰迪狗正在吃骨头); } } class HashiDog extends Dog { public HashiDog(String name, int age) { super(name, age); } Override public void eat() { System.out.println(一只叫做 getName() 的 getAge() 岁的哈士奇正在吃肉); } }