目录
一、泛型入门
1.使用传统方式
package com.feiyang.basic14;
import com.feiyang.static1.main;
import java.util.ArrayList;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:泛型
*/
public class Generic01 {
public static void main(String[] args) {
//使用传统方式解决
ArrayList arrayList = new ArrayList();
arrayList.add(new Dog("大黄",5));
arrayList.add(new Dog("黑子",6));
arrayList.add(new Dog("小花",2));
//加入不小心添加了只猫
arrayList.add(new Cat("咪咪",3));
for (Object o : arrayList) {
//向下转型(影响效率)
Dog o1 = (Dog) o;
System.out.println(o1.getName() + "-" + o1.getAge());
}
}
}
class Dog{
private String name;
private Integer age;
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
class Cat{
private String name;
private Integer age;
public Cat(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
打印输出:
大黄-5
黑子-6
小花-2
Exception in thread "main" java.lang.ClassCastException: com.feiyang.basic14.Cat cannot be cast to com.feiyang.basic14.Dog
at com.feiyang.basic14.Generic01.main(Generic01.java:22)
2.用泛型解决上面的问题
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:泛型
*/
public class Generic02 {
public static void main(String[] args) {
//使用传统方式解决
ArrayList<Dog> arrayList = new ArrayList<Dog>();
arrayList.add(new Dog("大黄",5));
arrayList.add(new Dog("黑子",6));
arrayList.add(new Dog("小花",2));
//加入不小心添加了只猫
//arrayList.add(new Cat("咪咪",3));
// for (Object o : arrayList) {
// //向下转型(影响效率)
// Dog o1 = (Dog) o;
// System.out.println(o1.getName() + "-" + o1.getAge());
// }
for (Dog o : arrayList) {
System.out.println(o.getName() + "-" + o.getAge());
}
}
}
打印输出:
大黄-5
黑子-6
小花-2
二、泛型介绍
package com.feiyang.basic14;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:泛型介绍
*/
public class Generic03 {
public static void main(String[] args) {
}
}
class Person<E>{
//属性类型泛型化
E s;//E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译时就确定E是什么类型。
//参数类型泛型化
public Person(E s) {
this.s = s;
}
//返回值类型泛型化
public E func(){
return s;
}
}
三、泛型语法和应用
1.泛型语法
2.泛型案例
package com.feiyang.basic14;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:泛型应用案例
*/
public class GenericExercise {
public static void main(String[] args) {
HashSet<Student> hashSet = new HashSet<>();
hashSet.add(new Student("tom",35));
hashSet.add(new Student("jack",16));
hashSet.add(new Student("feiyang",28));
for (Student student : hashSet) {
System.out.println(student.getName() + "-" + student.getAge());
}
HashMap<String, Student> hm = new HashMap<>();
hm.put("tom",new Student("tom",35));
hm.put("jack",new Student("jack",16));
hm.put("feiyang",new Student("feiyang",28));
Set<Map.Entry<String, Student>> entries = hm.entrySet();
for (Map.Entry<String, Student> entry : entries) {
System.out.println(entry.getKey() + "-" + entry.getValue());
}
}
}
class Student{
private String name;
private int age;
public Student(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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
打印输出:
jack-16
tom-35
feiyang-28
tom-Student{name='tom', age=35}
jack-Student{name='jack', age=16}
feiyang-Student{name='feiyang', age=28}
3.泛型使用细节
package com.feiyang.basic14;
import java.util.ArrayList;
import java.util.List;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:泛型使用细节
*/
public class GenericDetail {
public static void main(String[] args) {
//1.给泛型指定数据类型,要求是引用数据类型,不能是基本数据类型
ArrayList<Integer> arrayList = new ArrayList<Integer>();//OK
//ArrayList<int> arrayList2 = new ArrayList<int>();//error
//2.给泛型指定具体类型后,可以传入该类型或其子类型
Pig<A> aPig = new Pig<A>(new A());
aPig.f();
//Pig<B> bPig = new Pig<A>(new B());//error
Pig<A> bPig2 = new Pig<A>(new B());//
bPig2.f();
//3.泛型的使用
ArrayList<Integer> list = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
//也可以简写(推荐),编译器会进行类型推断
ArrayList<Integer> list3 = new ArrayList<>();
List<Integer> list4 = new ArrayList<>();
List<Pig> pig = new ArrayList<>();
//如果这样写,泛型默认是Object,
ArrayList list5 = new ArrayList();//等价与=>ArrayList<Object> arrayList1 = new ArrayList<Object>();
}
}
class A{}
//class B{}
class B extends A{}
class Pig<E>{
E e;
public Pig(E e) {
this.e = e;
}
public void f(){
System.out.println(e.getClass());
}
}
4.泛型经典练习题
package com.feiyang.basic14;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:生日日期类
*/
public class MyDate implements Comparable<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 void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
@Override
public String toString() {
return "MyDate{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
//把对日期的排序抽取出来放到MyDate类
@Override
public int compareTo(MyDate o) {
int yearMinus = this.year - o.getYear();
if(yearMinus !=0){
return yearMinus;
}
int monthMinus = this.month - o.getMonth();
if(monthMinus !=0){
return monthMinus;
}
return this.day - o.getDay();
}
}
package com.feiyang.basic14;
/**
* @author:程序员飞扬
* @公众hao:程序员飞扬
* @description:雇员类
*/
public class Employee {
private String name;
private Double sal;
private MyDate birthday;
public Employee(String name, Double sal, MyDate birthday) {
this.name = name;
this.sal = sal;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getSal() {
return sal;
}
public void setSal(Double sal) {
this.sal = sal;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", sal=" + sal +
", birthday=" + birthday +
'}';
}
}
package com.feiyang.basic14;
import java.util.ArrayList;
import java.util.Comparator;
/**
* @author:程序员飞扬
* @公众hao:程序员飞扬
* @description:泛型案例
*/
public class GenericExercise02 {
public static void main(String[] args) {
ArrayList<Employee> employees = new ArrayList<Employee>();
employees.add(new Employee("alice",2000.00,new MyDate(1980,10,21)));
employees.add(new Employee("bob",1800.00,new MyDate(2002,6,18)));
employees.add(new Employee("alice",3500.00,new MyDate(1980,10,22)));
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
int i = o1.getName().compareTo(o2.getName());
if(i != 0 ){
return i;
}
int i1 = o1.getBirthday().compareTo(o2.getBirthday());
return i1;
}
});
//lambda写法
employees.sort((o1, o2) -> {
int i = o1.getName().compareTo(o2.getName());
if(i != 0 ){
return i;
}
int i1 = o1.getBirthday().compareTo(o2.getBirthday());
return i1;
});
employees.forEach(employee -> System.out.println(employee));
}
}
打印输出:
Employee{name='alice', sal=2000.0, birthday=MyDate{year=1980, month=10, day=21}}
Employee{name='alice', sal=3500.0, birthday=MyDate{year=1980, month=10, day=22}}
Employee{name='bob', sal=1800.0, birthday=MyDate{year=2002, month=6, day=18}}
四、自定义泛型
1.自定义泛型类
package com.feiyang.basic14;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:自定义泛型类
*/
public class CustomGeneric_ {
public static void main(String[] args) {
}
}
/**
* 1.Tiger后面有泛型,所以我们把Tiger成为自定义泛型类
* 2. T,R,M是泛型的标识类,一般是单个大写字母
* 3. 泛型标识符可以有多个
* 4. 普通成员可以使用泛型(属性,方法)
* 5,使用泛型的数据不能初始化
* @param <T>
* @param <R>
* @param <M>
*/
class Tiger<T, R, M>{
String name;
T t; //属性使用泛型
R r;
M m;
//T[] tarr = new T[8]; //不可以,因为数组在 new时不能确定T的类型,所有不能开辟内存空间
//1. 静态和类相关,在类加载时对象还未创建
//2. 所以静态方法和静态属性使用了泛型,JVM就无法完成初始化
//static R r2;
//public static void m1(M m){
//
//}
public Tiger(String name, T t, R r, M m) { //构造器使用泛型
this.name = name;
this.t = t;
this.r = r;
this.m = m;
}
}
案例1
package com.feiyang.basic14;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:自定义泛型类
*/
public class CustomGeneric_ {
public static void main(String[] args) {
Tiger<Double, String, Integer> g = new Tiger<>("john");
g.setT(10.9);//OK
//g.setT("yy");//错误,类型不对
System.out.println(g);
Tiger g2 = new Tiger("john~~");//OK,默认T=Object,R=Object,M=Object
g2.setT("yy");//OK,因为此时T=Object,而"yy"=String,是Object的子类
System.out.println(g2);
}
}
/**
* 1.Tiger后面有泛型,所以我们把Tiger成为自定义泛型类
* 2. T,R,M是泛型的标识类,一般是单个大写字母
* 3. 泛型标识符可以有多个
* 4. 普通成员可以使用泛型(属性,方法)
* 5,使用泛型的数据不能初始化
* @param <T>
* @param <R>
* @param <M>
*/
class Tiger<T, R, M>{
String name;
T t; //属性使用泛型
R r;
M m;
//T[] tarr = new T[8]; //不可以,因为数组在 new时不能确定T的类型,所有不能开辟内存空间
//1. 静态和类相关,在类加载时对象还未创建
//2. 所以静态方法和静态属性使用了泛型,JVM就无法完成初始化
//static R r2;
//public static void m1(M m){
//
//}
public Tiger(String name, T t, R r, M m) { //构造器使用泛型
this.name = name;
this.t = t;
this.r = r;
this.m = m;
}
public Tiger(String john) {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public R getR() {
return r;
}
public void setR(R r) {
this.r = r;
}
public M getM() {
return m;
}
public void setM(M m) {
this.m = m;
}
@Override
public String toString() {
return "Tiger{" +
"name='" + name + '\'' +
", t=" + t +
", r=" + r +
", m=" + m +
'}';
}
}
输出:
Tiger{name='null', t=10.9, r=null, m=null}
Tiger{name='null', t=yy, r=null, m=null}
2.自定义泛型接口
package com.feiyang.basic14;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class CustomInterfaceGeneric_ {
}
interface IUsb<U, R>{
//普通方法中可以使用接口泛型
R get(U u);
void hi(R r);
void run(R r1,R r2,U u1,U u2);
//在jdk8中,可以在接口中使用默认方法,也是可以使用泛型
default R method(U u){
return null;
}
/**
* 泛型接口使用说明:
* 1. 接口中,静态成员不能使用泛型
*/
int n = 10;
//U name;//静态成员不能使用泛型
}
//在继承接口时,指定泛型接口的类型
interface IA extends IUsb<String,Double>{
}
//当我们继承IA接口时,因为IA接口继承IUsb接口时指定了U为String,R为Double,
//所以重写IUsb接口的方法时,用String替换了U,用Double替换了R。
class AA implements IA{
@Override
public Double get(String s) {
return null;
}
@Override
public void hi(Double aDouble) {
}
@Override
public void run(Double r1, Double r2, String u1, String u2) {
}
}
//在实现接口时直接指定泛型接口的类型
//给U指定Integer,给R指定Float
//所以当我们实现IUsb接口时,会用Integer替换U,用Float替换R
class BB implements IUsb<Integer,Float>{
@Override
public Float get(Integer integer) {
return null;
}
@Override
public void hi(Float aFloat) {
}
@Override
public void run(Float r1, Float r2, Integer u1, Integer u2) {
}
}
3.自定义泛型方法
自定义泛型方法练习
package com.feiyang.basic14;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class CustomMethodGenericExercise {
public static void main(String[] args) {
Apple<String, Integer, Double> apple = new Apple<>();
apple.fly(10);
apple.fly(new Dog2());
}
}
class Dog2{}
class Apple<T,R,M>{
public <E> void fly(E e){
System.out.println(e.getClass().getSimpleName());
}
//错误,下面的方法并不是泛型方法,只是想使用类声明的泛型,然而类并没有声明泛型U
//public void eat(U u){}
//使用了泛型类声明的泛型M
public void rnn(M m){}
}
输出:
Integer
Dog2
五、泛型的继承和通配符
package com.feiyang.basic14;
import java.util.ArrayList;
import java.util.List;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class GenericExtends {
public static void main(String[] args) {
Object xx = new String("xx");//这样可以
List list = new ArrayList();//可以,多态的体现
//List<Object> list0 = new ArrayList<String>();//不可以,泛型不具有继承性
//举例说明几个方法的使用
List<Object> list1 = new ArrayList();
List<String> list2 = new ArrayList();
List<AAA> list3 = new ArrayList();
List<BBB> list4 = new ArrayList();
List<CCC> list5 = new ArrayList();
//List<?>
printCollection1(list1);
printCollection1(list2);
printCollection1(list3);
printCollection1(list4);
printCollection1(list5);
//List<? extends AAA>
// printCollection2(list1);//×
// printCollection2(list2);//×
// printCollection2(list3);//√
// printCollection2(list4);//√
// printCollection2(list5);//√
//List<? super CCC>
// printCollection3(list1);//√
// printCollection3(list2);//×
// printCollection3(list3);//√
// printCollection3(list4);//×
// printCollection3(list5);//×
}
//几个方法说明:
//List<?>表示任意的泛型类型都可以接受
public static void printCollection1(List<?> c){
for (Object o : c) {
System.out.println(o);
}
}
//List<? extends AAA>表示上限,可以接受AAA或AAA的子类
public static void printCollection2(List<? extends AAA> c){
for (Object o : c) {
System.out.println(o);
}
}
//List<? super CCC>表示下限,可以接受AAA类或AAA类的父类
public static void printCollection3(List<? super AAA> c){
for (Object o : c) {
System.out.println(o);
}
}
}
class AAA{
}
class BBB extends AAA{
}
class CCC extends BBB{
}
六、泛型作业(练习)
package com.feiyang.basic14;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class User {
private int id;
private int age;
private String name;
public User() {
}
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
package com.feiyang.basic14;
import org.junit.jupiter.api.Test;
import java.util.*;
/**
* @author:飞扬
* @公众hao:程序员飞扬
* @description:泛型作业练习
*/
public class HomeWork01 {
public static void main(String[] args) {
}
@Test
public void testList(){
DAO<User> dao = new DAO<>();
dao.save("01",new User(1,10,"tom"));
dao.save("02",new User(2,15,"rose"));
dao.save("03",new User(3,18,"jack"));
//返回所有对象
List<User> list = dao.list();
System.out.println(list);
//更新
dao.update("03",new User(4,20,"bella"));
List<User> list2 = dao.list();
System.out.println(list2);
//删除
dao.delete("01");
List<User> list3 = dao.list();
System.out.println(list3);
//根据id获得
System.out.println("02===" + dao.get("02"));
}
}
class DAO<T> {
private Map<String,T> map = new HashMap<>();
public T get(String id){
return map.get(id);
}
public void update(String id,T entity){
map.put(id,entity);
}
//返回map中存放的所有T对象
public List<T> list(){
List<T> list = new ArrayList();
Set<String> keySet = map.keySet();
for (String key : keySet) {
list.add(get(key));
}
return list;
}
public void save(String id,T entity){
map.put(id,entity);
}
public void delete(String id){
map.remove(id);
}
}