Java之泛型
文章目录
- 首先接着上一篇(集合)文章,来个非常牛逼的易错题
- 传统集合问题分析
- 泛型快速入门案例
- 泛型介绍
- 泛型的好处
- 泛型的语法
- 泛型的声明
- 泛型的实例化
- 泛型使用举例
- 泛型使用的注意事项和细节
- 自定义泛型
- 自定义泛型方法
- 自定义泛型接口
- 自定义泛型方法
- 泛型的继承和通配符
- JUnit
温馨提示,师从韩顺平
首先接着上一篇(集合)文章,来个非常牛逼的易错题
传统集合问题分析
泛型快速入门案例
package 泛型;
import 集合.Set.Dog;
import java.util.ArrayList;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo01 {
public static void main(String[] args) {
//使用传统的方法来解决===> 使用泛型
//老韩解读
//1. 当我们 ArrayList<Dog> 表示存放到 ArrayList 集合中的元素是 Dog 类型 (细节后面说...)
//2. 如果编译器发现添加的类型,不满足要求,就会报错
//3. 在遍历的时候,可以直接取出 Dog 类型而不是 Object
//4. public class ArrayList<E> {} E 称为泛型,那么 Dog->E
ArrayList<Dog> arrayList = new ArrayList<Dog>();
arrayList.add(new Dog("旺财", 10));
arrayList.add(new Dog("发财", 1));
arrayList.add(new Dog("小黄", 5));
//假如我们的程序员,不小心,添加了一只猫
//arrayList.add(new Cat("招财猫", 8));
System.out.println("===使用泛型====");
for (Dog dog : arrayList) {
System.out.println(dog.getName() + "-" + dog.getAge());
}
}
}
泛型介绍
package 泛型;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo01 {
public static void main(String[] args) {
Person<String> stringPerson = new Person<String>("小韩很牛逼!");
stringPerson.showType(); //class java.lang.String
Person<Integer> integerPerson = new Person<Integer>(100);
integerPerson.showType(); //class java.lang.Integer
}
}
//泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型
//或者是某个方法的返回值类型,或者是参数类型
class Person<E>{
E s;
public Person(E s) {
this.s = s;
}
public E getS() {
return s;
}
public void setS(E s) {
this.s = s;
}
public void showType() {
System.out.println(s.getClass()); //输出s的运行类型
}
}
泛型的好处
泛型的语法
泛型的声明
泛型的实例化
泛型使用举例
package 泛型;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo02 {
public static void main(String[] args) {
Student student1 = new Student("小韩");
Student student2 = new Student("小画");
HashMap<String, Student> kvHashMap = new HashMap<String, Student>();
/*
public class HashMap<K,V>{}
*/
kvHashMap.put("小韩",student1);
kvHashMap.put("小画",student2);
System.out.println(kvHashMap);
//第一种遍历方式
Set<String> strings = kvHashMap.keySet();
for (String key : strings) {
System.out.println(kvHashMap.get(key));
}
//第二种遍历方式
/*
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
*/
Set<Map.Entry<String, Student>> entries = kvHashMap.entrySet();
for (Map.Entry<String, Student> entry : entries) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
class Student{
String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
泛型使用的注意事项和细节
package 泛型;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo03 {
public static void main(String[] args) {
// 1. 泛型指向数据类型是引用类型,不能是基本数据类型
ArrayList<Integer> integers = new ArrayList<Integer>();
//2. ArrayList<int> ints = new ArrayList<int>();
Pig<A> as = new Pig<A>(new A());
as.f(); //class 泛型.A
Pig<A> bs = new Pig<A>(new B());
bs.f(); //class 泛型.B
//3. 泛型的使用形式
ArrayList<Integer> integers1 = new ArrayList<Integer>();
List<Integer> integers2 = new ArrayList<Integer>();
//在实际开发中,我们往往简写
ArrayList<Integer> integers3 = new ArrayList<>();
//4. 如果这样写,泛型默认是Object
ArrayList list = new ArrayList();
// 等价于 ArrayList<Object> objects = new ArrayList<>();
Tiger tiger = new Tiger();
// 等价于Tiger类的E为Object
}
}
class A{}
class B extends A{}
class Pig<E>{
E e;
public Pig() {
}
public Pig(E e) {
this.e = e;
}
public void f(){
System.out.println(e.getClass());
}
}
class Tiger<E>{
E e;
public Tiger() {
}
public Tiger(E e) {
this.e = e;
}
}
自定义泛型
自定义泛型方法
package 泛型;
import java.util.Arrays;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo05 {
public static void main(String[] args) {
//T=Double, R=String, M=Integer
Tige<Double,String,Integer> g = new Tige<>("john");
g.setT(10.9); //OK
//g.setT("yy"); //错误,类型不对 T=Double
System.out.println(g); //Tiger{name='john', r=null, m=null, t=10.9, ts=null}
Tige g2 = new Tige("john~~");//OK T=Object R=Object M=Object
g2.setT("yy"); //OK ,因为 T=Object "yy"=String 是 Object 子类
System.out.println("g2=" + g2);
//g2=Tiger{name='john~~', r=null, m=null, t=yy, ts=null}
}
}
//老韩解读
//1. Tiger 后面泛型,所以我们把 Tiger 就称为自定义泛型类
//2, T, R, M 泛型的标识符, 一般是单个大写字母
//3. 泛型标识符可以有多个.
//4. 普通成员可以使用泛型 (属性、方法)
//5. 使用泛型的数组,不能初始化
//6. 静态方法中不能使用类的泛型
class Tige<T, R, M> {
String name;
R r; //属性使用到泛型
M m;
T t;
//因为数组在 new 不能确定 T 的类型,就无法在内存开空间
//不允许:T[] ts=new T[8];
T[] ts;
//因为静态是和类相关的,在类加载时,对象还没有创建,泛型是在类定义的时候,才会被指定的
//所以,如果静态方法和静态属性使用了泛型,JVM 就无法完成初始化
// static R r2;
// public static void m1(M m) {
// }
public Tige(String name) {
this.name = name;
}
public Tige(R r, M m, T t) {//构造器使用泛型
this.r = r;
this.m = m;
this.t = t;
}
public Tige(String name, R r, M m, T t) {//构造器使用泛型
this.name = name;
this.r = r;
this.m = m;
this.t = t;
}
//方法使用泛型
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
@Override
public String toString() {
return "Tiger{" +
"name='" + name + '\'' +
", r=" + r +
", m=" + m +
", t=" + t +
", ts=" + Arrays.toString(ts) +
'}';
}
}
自定义泛型接口
package 泛型;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo06 {
public static void main(String[] args) {
}
}
/*
泛型接口使用注意事项
1. 接口中静态成员也不能使用泛型
2. 泛型接口的类型,在继承接口或者实现接口时确定
3. 没有指定类型默认为Object
*/
interface IUSb<U,R>{
int n = 10;
//U name 不能 这样使用
//普通方法中,可以使用接口泛型
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;
}
}
//在实现接口时直接指定泛型接口的类型
class BB implements IUSb<Integer,Float>{
@Override
public Float get(Integer integer) {
return 0f;
}
@Override
public void hi(Float aFloat) {
}
@Override
public void run(Float r1, Float r2, Integer u1, Integer u2) {
}
}
//在继承接口时,指定接口的类型
interface IA extends IUSb<String,Double>{}
//当我们去实现IA接口时,因为IA在继承IUSB接口时,指定了U为String R为Double
//因此在实现IUsu接口的方法时,使用Strin替换U,Double替换R
class AA implements IA{
@Override
public Double get(String s) {
return 0.0;
}
@Override
public void hi(Double aDouble) {
}
@Override
public void run(Double r1, Double r2, String u1, String u2) {
}
}
//等价于class CC implements IUSb<Object,Object>{}
class CC implements IUSb{
@Override
public Object get(Object o) {
return null;
}
@Override
public void hi(Object o) {
}
@Override
public void run(Object r1, Object r2, Object u1, Object u2) {
}
}
自定义泛型方法
package 泛型;
import java.util.ArrayList;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo07 {
public static void main(String[] args) {
Car car = new Car();
car.fly("宝马",100); //当调用方法时,传入参数,编译器,就会确定类型
//测试
Fish<String, ArrayList> fish = new Fish<>();
fish.hello(new ArrayList(),11.3);
}
}
//泛型方法可以定义在普通类中,也可以定义在泛型类中
class Car{ //普通类
public void run(){ } //普通方法
public<T,R> void fly(T t,R r){ //泛型方法
System.out.println(t.getClass()); //class java.lang.String
System.out.println(r.getClass()); //class java.lang.Integer
}
}
class Fish<T,R> {//泛型类
public void run(){ //普通方法
}
public<U,M> void eat(U u,M m){}
//说明
//1. 下面hi方法不是泛型类型
//2. 是hi方法使用了类声明的泛型
public void hi(T t){}
//泛型方法,可以使用类声明的泛型,也可以使用自己声明的泛型
public<K> void hello(R r,K k){
System.out.println(r.getClass()); //class java.util.ArrayList
System.out.println(k.getClass()); //class java.lang.Double
}
}
泛型的继承和通配符
package 泛型;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo08 {
public static void main(String[] args) {
//1. 泛型没有继承性
// List<Object> list = 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<?>表示任意泛型类型都可以接受
printCollection(list1);
printCollection(list2);
printCollection(list3);
printCollection(list4);
printCollection(list5);
//?extends AAA 表示上限,可以接受 AAA 或者AAA类的父类,不限于直接子类
// printCollection2(list1);
// printCollection2(list2);
printCollection2(list3);
printCollection2(list4);
printCollection2(list5);
//super子类名 AAA :支持AAA类的父类,不限于直接父类
printCollection3(list1);
//printCollection3(list2);
printCollection3(list3);
//printCollection3(list4);
//printCollection3(list5);
}
//List<?>表示任意泛型类型都可以接受
public static void printCollection(List<?> c) {
for(Object o : c) {
System.out.println(o);
}
}
//?extends AAA 表示上限,可以接受 AAA 或者AAA类的父类,不限于直接子类
public static void printCollection2(List<? extends AAA> c) {
for(Object o : c) {
System.out.println(o);
}
}
//super子类名 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 {
}
JUnit
- JUnit是一个Java语言的单元测试框架
- 多数Java的开发环境都已经集成了JUnit作为单元测试的工具
package 泛型;
import org.junit.jupiter.api.Test;
/**
* @Author: 韩如意
* @CreateTime: 2025-02-22
* @Description: no
* @Version: 1.0
*/
public class demo10 {
public static void main(String[] args) {
}
@Test
public void m1(){
System.out.println("m1()方法被调用");
}
@Test
public void m2(){
System.out.println("m2()方法被调用");
}
}