目录
一.泛型的语法
1.传统的方法遍历集合存在的问题
需求
传统代码实现需求
package com.Generics;
import java.util.ArrayList;
public class Generics01 {
public static void main(String[] args) {
// 使用传统的方法来解决
ArrayList list = new ArrayList();
list.add(new Dog("旺财",10));
list.add(new Dog("发财",1));
list.add(new Dog("小黄",5));
for (Object o : list) {
// 进行类型的强转
Dog dog = (Dog)o;
// 输出
System.out.println("年龄:"+dog.getAge()+" 名字:"+dog.getName());
}
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
运行结果
年龄:10名字:旺财
年龄:1名字:发财
年龄:5名字:小黄
问题:如果程序员不小心加入了不同类型的数据,会发生类型转换异常ClassCastException,存在一定的隐患,但是编译器不会识别出来,不能对集合当中的数据进行约束。
效率:向下转型的效率也很低
可能出现的问题代码
package com.Generics;
import java.util.ArrayList;
public class Generics01 {
public static void main(String[] args) {
// 使用传统的方法来解决
ArrayList list = new ArrayList();
list.add(new Dog("旺财",10));
list.add(new Dog("发财",1));
list.add(new Dog("小黄",5));
// 程序员不小心加入了一只猫
list.add(new Cat("小白",2));
for (Object o : list) {
// 这里的强转会出现问题 数据量太大的话,转型会消耗大量的内存 效率很低
Dog dog = (Dog)o;
System.out.println("年龄:"+dog.getAge()+" 名字:"+dog.getName());
}
//
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Cat{
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
运行结果
年龄:10 名字:旺财
年龄:1 名字:发财
年龄:5 名字:小黄
Exception in thread "main" java.lang.ClassCastException: com.Generics.Cat cannot be cast to com.Generics.Dog
at com.Generics.Generics01.main(Generics01.java:17)
总结
2.使用泛型来解决传统集合添加元素带来的问题
泛型优化之后的代码
package com.Generics;
import java.util.ArrayList;
public class Generics02 {
public static void main(String[] args) {
ArrayList<Dog> dogs = new ArrayList<>();
// 使用泛型来解决问题
dogs.add(new Dog("旺财",10));
dogs.add(new Dog("发财",1));
dogs.add(new Dog("小黄",5));
// 加入其他类型的数据会有编译错误提示 也就是说 我们这个集合当中只能存放我们指定的对象
// dogs.add(new Cat("小白",2));
for (Dog dog : dogs) {
// 访问集合当中的数据也不用进行类型的转换效率提高
System.out.println("年龄 :"+dog.getAge()+" 名字:"+dog.getName());
}
}
}
运行结果
年龄 :10 名字:旺财
年龄 :1 名字:发财
年龄 :5 名字:小黄
3.泛型使用介绍
3.1基本使用
解释泛型的代码
package com.Generics;
public class Generics03 {
public static void main(String[] args) {
// 如何理解 明明没有构造器 E可以看成是一个变量 一个关于类的变量 和int与整数一样
Person<String> p1 = new Person<>("韩顺平教育");
System.out.println(p1.f());
// 等效于 在编译期间确定E的类型
// class Person{
// String e;
//
// public Person(String e) {
// this.e = e;
// }
//
// public String f(){
// return e;
// }
// }
// 像是一个万能的关于类类型的变量
Person<Integer> integerPerson = new Person<>(100);
System.out.println(integerPerson.f());
}
}
//泛型:在类声明是通过某一个标识,来标识类当中某一个属性的值。
// 或者是某个方法的返回值类型,或者是参数类型
class Person<E>{
// E表示e的数据类型,该数据类型在定义person对象的时候指定,即在编译期间就知道e是什么类型了
// 感觉像是类当中一个很奇怪的属性
E e;
public Person(E e) { //E可以是参数类型
this.e = e;
}
public E f(){ //E也可以是返回值类型
return e;
}
}
运行的结果
韩顺平教育
100
3.2泛型的语法应用
练习
代码
package com.Generics;
import java.util.*;
public class GenericsExercise {
public static void main(String[] args) {
HashSet<Student> students = new HashSet<>();
students.add(new Student(