参考链接:
【零基础 快速学Java】韩顺平 零基础30天学会Java_哔哩哔哩_bilibili
1 实体类Dog实体类
@Getter
@Setter
public class Dog {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
Cat实体类
@Getter
@Setter
public class Cat {
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
2 传统方式
不能对加入到集合ArrayList中的数据类型进行约束(不安全)
遍历的时候,需要进行类型转换,如果集合中的数据量较大。对效率有影响
@SuppressWarnings({"all"})
public class TestGeneric {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(new Dog("旺财", 4));
arrayList.add(new Dog("发财", 5));
arrayList.add(new Dog("老财", 6));
//遍历
for (Object o : arrayList) {
// 向下转型 Object ---->Dog
Dog dog=(Dog)o;
System.out.println(dog.getName()+"---->"+dog.getAge()+"岁");
}
}
}
旺财---->4岁 发财---->5岁 老财---->6岁
有细心的同学可能就发现了,我这里为什么遍历的是一个Object。
继续往下讲
但是当你程序员不小心将一只猫给添加到这个ArrayList中时:
@SuppressWarnings({"all"})
public class TestGeneric {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(new Dog("旺财", 4));
arrayList.add(new Dog("发财", 5));
arrayList.add(new Dog("老财", 6));
// 假如我们的程序员不小心加入了一只猫
arrayList.add(new Cat("汤姆猫", 10));
//遍历
for (Object o : arrayList) {
// 向下转型 Object ---->Dog
// 此时这个列表中是一只猫,强行转Dog类型必然导致ClassCastException类型转换异常
Dog dog = (Dog) o;
System.out.println(dog.getName() + "---->" + dog.getAge() + "岁");
}
}
}
3 泛型快速体验-用泛型来解决前面的问题
泛型来了
4 泛型说明
Person类
@Getter @Setter public class Person{ private E s;//E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型 public Person(E s) {// E 也可以是参数类型 this.s = s; } public E f() { return s;//返回类型也可以使用 E } public void getClassType(){ // 输出真正的运行类型 System.out.println("我的运行类型是:"+s.getClass()); } }
TestPerson类
public class TestPerson {
public static void main(String[] args) {
//注意,特别强调:E具体的数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型
Person person = new Person("我是Student");
person.getClassType();
Person integerPerson = new Person<>(100);
integerPerson.getClassType();
}
}
运行结果:
5 Java泛型应用实例
@SuppressWarnings({"all"})
public class GenericExercise {
public static void main(String[] args) {
// 使用泛型方式给HashSet 放入三个学生对象
HashSet students = new HashSet();
students.add(new Student("jack", 18));
students.add(new Student("marry", 19));
students.add(new Student("liming", 20));
for (Student student : students) {
System.out.println(student);
}
System.out.println("=============================");
// 使用泛型方式给HashMap 放入三个学生对象
HashMap stringStudentHashMap = new HashMap();
stringStudentHashMap.put("lisa", new Student("lisa", 50));
stringStudentHashMap.put("pisa", new Student("pisa", 55));
stringStudentHashMap.put("simisi", new Student("simisi", 60));
// 迭代器 EntrySet
Set> entries = stringStudentHashMap.entrySet();
Iterator> iterator = entries.iterator();
while(iterator.hasNext()){
Map.Entry next = iterator.next();
System.out.println(next.getKey() + "-" + next.getValue());
}
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Student {
private String name;
private int age;
}
运行结果
Student(name=liming, age=20) Student(name=marry, age=19) Student(name=jack, age=18) ============================= simisi-Student(name=simisi, age=60) pisa-Student(name=pisa, age=55) lisa-Student(name=lisa, age=50)
快捷操作
Set> entries = stringStudentHashMap.entrySet();
Iterator6 Java泛型使用细节 1 2> iterator = entries.iterator();
3public class GenericDetail {
public static void main(String[] args) {
// 1.给泛型指向的数据类型是,要求是引用类型,不能是基本数据类型
List list = new ArrayList();
// List list2 = new ArrayList();
// 2.在给泛型指定类型后,可以传入该类型或者其子类类型
// E 指定了 A 类型,构造器传入了 new A()
Pig aPig = new Pig(new A());
aPig.f();
Pig bPig = new Pig(new B());
bPig.f();
}
}
class A {}
class B extends A {}
class Pig {
E e;
Pig(E e) {
this.e = e;
}
void f(){
System.out.println("运行时类型==>"+e.getClass());
}
}
运行程序:
运行时类型==>class com.example.demo.TestPackage2.A 运行时类型==>class com.example.demo.TestPackage2.B4 完整代码
public class GenericDetail {
public static void main(String[] args) {
// 1.给泛型指向的数据类型是,要求是引用类型,不能是基本数据类型
List list = new ArrayList();
// List list2 = new ArrayList();
// 2.在给泛型指定类型后,可以传入该类型或者其子类类型
// E 指定了 A 类型,构造器传入了 new A()
Pig aPig = new Pig(new A());
aPig.f();
Pig bPig = new Pig(new B());
bPig.f();
// 3.泛型的使用形式
ArrayList list1 = new ArrayList();
List list2=new ArrayList();
// 在实际开发中我们往往可以简写 编译器进行类型推断
ArrayList list3 = new ArrayList<>();
List list4=new ArrayList<>();
// 4.如果是这样写 泛型默认是Object
ArrayList l = new ArrayList();// 等价 ArrayList
运行时类型==>class com.example.demo.TestPackage2.A 运行时类型==>class com.example.demo.TestPackage2.B7 泛型课堂练习 8 自定义泛型类 1 自定义泛型
public class CustomGeneric {
public static void main(String[] args) {
}
}
// 1.自定义泛型类
// 2.泛型标识符 T R M
// 3.泛型标识符可以有多个
// 4.普通成员可以使用泛型(属性,方法)
// 5.使用了泛型的数组不能初始化
// 6.
@SuppressWarnings({"all"})
class Tiger{
String name;
T t;
R r;
M m;
// 使用了泛型的构造器
public Tiger(String name,T t,R r,M m){
this.name=name;
this.t=t;
this.r=r;
this.m=m;
}
// 静态跟对象没有关系的,它是跟类本身相关的,这个时候引入泛型,泛型是不能确定的。
// 在类加载时,对象还没有创建,它去初始化这个 static R r2的时候他就不知道怎么办了
// 所以,如果静态方法和静态属性使用了泛型,JVM就无法完成初始化。这个R只是一个标识符而已。
// 这个R在对象定义的时候它才知道是什么。
//static R r2;
//public static void method(M m){}
//使用了泛型的数组不能初始化
// 因为:数组在new的时候不能确定T的类型,就无法在内存开辟空间。
//T[] ts=new T[8];
T[] ts2;//只能在这里定义,不能初始化。
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 使用了泛型的方法
public void setT(T t) {
this.t = t;
}
// 返回类型也可以有泛型
public T getT() {
return t;
}
}
2 判断正误:
9 自定义泛型接口 10 自定义泛型方法 11 泛型方法练习 12 泛型继承和通配



