文章目录
java基础[泛型-genericity包下]代码实现git地址
什么是泛型
1.背景:
- JAVA推出泛型以前,程序员可以构建一个元素类型为Object的集合,该集合能够存储任意的数据类型对象,而在使用该集合的过程中,需要程序员明确知道存储每个元素的数据类型,否则很容易引发ClassCastException异常。
2.概念:
- Java泛型(generics)是JDK5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。泛型的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。
3.好处:
- 类型安全
- 消除了强制类型的转换
4.类型:
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(表示Java 类,包括基本的类和我们自定义的类)
- K - Key(表示键,比如Map中的key)
- V - Value(表示值)
- N - Number(表示数值类型)
- ? - (表示不确定的java类型)
- S、U、V - 2nd、3rd、4th types
泛型类
1.泛型类
- (1)使用语法
类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>(); - (2)Java1.7以后,后面的<>中的具体的数据类型可以省略不写
类名<具体的数据类型> 对象名 = new 类名<>(); 菱形语法
2.泛型类注意事项:
- 泛型类,如果没有指定具体的数据类型,此时,操作类型是Object
- 泛型的类型参数只能是类类型,不能是基本数据类型
- 泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型
package com.zgs.genericity.demo1;
/**
* @author: guisong.zhang
* @date: 2024/2/29 17:04:57
* @description 泛型类定义
* <T>泛型标识--类型参数
* T 创建对象的时候指定具体的数据类型
**/
public class Generic<T> {
private T key;
public Generic() {
}
public Generic(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
@Override
public String toString() {
return "Generic{" +
"key=" + key +
'}';
}
}
package com.zgs.genericity.demo1;
/**
* @author: guisong.zhang
* @date: 2024/2/29 17:10:14
* @description TODO
**/
public class Demo1 {
public static void main(String[] args) {
//泛型类在创建的时候,知道具体的数据类型
Generic<String> strGen = new Generic<>("1111");
String strKey = strGen.getKey();
System.out.println("strKey:" + strKey);
System.out.println("===========================");
Generic<Integer> intGen = new Generic<>(999);
Integer intKey = intGen.getKey();
System.out.println("intKey:" + intKey);
System.out.println("===========================");
//泛型类在创建的时候,不指定具体的类型,将使用Object类型操作
Generic generic = new Generic<>("AAAA");
Object objKey = generic.getKey();
System.out.println("objKey:" + objKey);
//泛型类不支持基本数据类型,比如不支持int 但是支持Integer
// Generic<int> generic = new Generic<int>(100);
System.out.println("===========================");
//同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型
System.out.println(strGen.getClass());
System.out.println(intGen.getClass());
System.out.println(strGen.getClass() == intGen.getClass());
}
}
- 可以结合后面的泛型擦除理解,泛型擦除之后 Generic < String > 和Generic< Integer >都是Generic类。
- 泛型类巩固练习
package com.zgs.genericity.demo2;
/**
* @author guisong.zhang
* @date 2024/2/29 22:50
* @description 泛型类巩固练习
*/
public class MainClass {
public static void main(String[] args) {
//创建抽奖器对象,指定数据类型
ProductGetter<String> stringProductGetter = new ProductGetter<>();
//初始化奖品
String[] strProducts = {"iPhone", "huawei", "大疆无人机", "加湿器"};
for (String strProduct : strProducts) {
stringProductGetter.addProduct(strProduct);
}
//抽奖
String strProduct = stringProductGetter.getProduct();
System.out.println("奖品为:" + strProduct);
System.out.println("===================================");
ProductGetter<Integer> integerProductGetter = new ProductGetter<>();
Integer[] integerProducts = {500, 1000, 5000, 10000};
for (Integer integerProduct : integerProducts) {
integerProductGetter.addProduct(integerProduct);
}
Integer integerProduct = integerProductGetter.getProduct();
System.out.println("奖金为:" + integerProduct);
}
}
package com.zgs.genericity.demo2;
import java.util.ArrayList;
import java.util.Random;
/**
* @author guisong.zhang
* @date 2024/2/29 22:50
* @description 泛型类巩固练习-奖品类-模拟抽奖器
*/
public class ProductGetter<T> {
Random random = new Random();
//奖品
private T product;
//奖品集合
ArrayList<T> list = new ArrayList<>();
//添加奖品
public void addProduct(T t) {
list.add(t);
}
//抽奖
public T getProduct() {
product = list.get(random.nextInt(list.size()));
return product;
}
}
3.从泛型类派生子类
- 父类
package com.zgs.genericity.demo3;
/**
* @author guisong.zhang
* @date 2024/2/29 23:04
* @description 父类
*/
public class Parent<E> {
private E value;
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
}
- 子类也是泛型类,子类和父类的泛型类型要一致
class ChildGeneric extends Generic
package com.zgs.genericity.demo3;
/**
* @author guisong.zhang
* @date 2024/2/29 23:04
* @description 子类-子类也是泛型类情况,子类的泛型要与父类的一致
* 子类可对泛型进行扩展但是必须包含父类的
*/
public class ChildFirst<T, E, K> extends Parent<T> {
@Override
public T getValue() {
return super.getValue();
}
}
- 子类不是泛型类,父类要明确泛型的数据类型
class ChildGeneric extends Generic
package com.zgs.genericity.demo3;
/**
* @author guisong.zhang
* @date 2024/2/29 23:17
* @description 子类不是泛型类,父类要明确泛型的数据类型
*/
public class ChildSecond extends Parent<String> {
@Override
public String getValue() {
return super.getValue();
}
@Override
public void setValue(String value) {
super.setValue(value);
}
}
- 测试代码
package com.zgs.genericity.demo3;
/**
* @author guisong.zhang
* @date 2024/2/29 23:12
* @description 类描述
*/
public class MainClass {
public static void main(String[] args) {
ChildFirst<String, Integer, Boolean> childFirst = new ChildFirst();
childFirst.setValue("www");
String value = childFirst.getValue();
System.out.println(value);
System.out.println("================================");
ChildSecond childSecond = new ChildSecond();
childSecond.setValue("sddsasd");
String value1 = childSecond.getValue();
System.out.println(value1);
System.out.println("================================");
}
}
泛型接口
- 泛型接口的定义语法:
interface 接口名称 <泛型标识,泛型标识,…> {
泛型标识 方法名();
.....
}
泛型接口的使用
- 泛型接口
/**
* 泛型接口
* @param <T>
*/
public interface Generator<T> {
T getKey();
}
- 实现类不是泛型类,接口要明确数据类型
package com.zgs.genericity.demo4;
/**
* @author guisong.zhang
* @date 2024/2/29 23:27
* @description 实现类不是泛型类,接口要明确数据类型
*/
public class Apple implements Generator<String> {
@Override
public String getKey() {
return "hello 坤坤";
}
}
- 实现类是泛型类,实现接口的类要与泛型接口一致
package com.zgs.genericity.demo4;
/**
* @author guisong.zhang
* @date 2024/2/29 23:31
* @description 实现类是泛型类,实现接口的类要与泛型接口一致
* 实现类可以扩展泛型,但里面必须要包含接口的泛型
*/
public class Pair<T, E> implements Generator<T> {
private T key;
public E value;
public Pair(T key, E value) {
this.key = key;
this.value = value;
}
@Override
public T getKey() {
return key;
}
public E getValue() {
return value;
}
}
- 测试类
package com.zgs.genericity.demo4;
/**
* @author guisong.zhang
* @date 2024/2/29 23:26
* @description 类描述
*/
public class MainClass {
public static void main(String[] args) {
Apple apple = new Apple();
String key = apple.getKey();
System.out.println(key);
System.out.println("============================");
Pair<String, Integer> pair = new Pair<>("坤坤", 18);
Integer value = pair.getValue();
String key1 = pair.getKey();
System.out.println(key1);
System.out.println(value);
System.out.println("============================");
}
}
泛型方法
1.用法
- 泛型方法是在调用方法的时候指明泛型的具体类型。
2.语法:
- 修饰符 <T,E, …> 返回值类型 方法名(形参列表) { 方法体… }
3.说明:
- public与返回值中间非常重要,可以理解为声明此方法为泛型方法。
- 只有声明了的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
- < T >表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
- 与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
4.泛型方法与可变参数
- 泛型方法类
package com.zgs.genericity.demo5;
import java.util.ArrayList;
import java.util.Random;
/**
* @author guisong.zhang
* @date 2024/2/29 22:50
* @description 泛型类巩固练习-奖品类-模拟抽奖器
*/
public class ProductGetter<T> {
Random random = new Random();
private T product;
ArrayList<T> list = new ArrayList<>();
public T getProduct() {
product = list.get(random.nextInt(list.size()));
return product;
}
//定义一个泛型方法
public <T> T getProduct(ArrayList<T> list) {
return list.get(random.nextInt(list.size()));
}
/**
* 静态的泛型方法
* 泛型方法可以用static 但是里如果方法使用了泛型类中的泛型则不可使用static 比如public T getProduct()此方法
*
* @author guisong.zhang
* @date 2024/3/1 10:26
*/
public static <T, E, K> void printType(T t, E e, K k) {
System.out.println("t:[" + t + "]--e:[" + e + "]--k:[" + k + "]");
}
/**
* 泛型方法与可表参数
*
* @author guisong.zhang
* @date 2024/3/1 10:29
*/
public static <E> void print(E... e) {
for (E e1 : e) {
System.out.print(e1);
}
}
}
- 测试类
package com.zgs.genericity.demo5;
import java.util.ArrayList;
/**
* @author: guisong.zhang
* @date: 2024/3/1 10:05:34
* @description TODO
**/
public class MainClass {
public static void main(String[] args) {
ProductGetter<Integer> productGetter = new ProductGetter();
ArrayList<String> strList = new ArrayList<>();
strList.add("iPhone");
strList.add("huawei");
strList.add("加湿器");
strList.add("无人机");
//泛型方法的调用,类型是通过调用方法的时候来指定的
//泛型方法是独立于泛型类的,与泛型类指定的泛型具体类型没有关系
String product = productGetter.getProduct(strList);
System.out.println(product);
System.out.println("====================================");
ArrayList<Integer> integerList = new ArrayList<>();
integerList.add(1000);
integerList.add(500);
integerList.add(5000);
integerList.add(99999);
Integer product1 = productGetter.getProduct(integerList);
System.out.println(product1);
System.out.println("====================================");
//调用多个泛型类型的静态泛型方法
ProductGetter.printType("坤坤", 18, true);
System.out.println("====================================");
//可变参数的泛型方法的调用
ProductGetter.print(1, 2, 3, 4, 5);
System.out.println("====================================");
ProductGetter.print("坤坤", true, 18, "岁");
}
}
5.泛型方法总结
- 泛型方法能使方法独立于类而产生变化
- 如果static方法要使用泛型能力,就必须使其成为泛型方法
/**
* 静态的泛型方法
* 泛型方法可以用static 但是里如果方法使用了泛型类中的泛型则不可使用static
* 比如public T getProduct()此方法
*
* @author guisong.zhang
* @date 2024/3/1 10:26
*/
public static <T, E, K> void printType(T t, E e, K k) {
System.out.println("t:[" + t + "]--e:[" + e + "]--k:[" + k + "]");
}
类型通配符
1.什么是类型通配符
- 类型通配符一般是使用"?"代替具体的类型实参。
- 所以,类型通配符是类型实参,而不是类型形参。
- 类型通配符代码实现
package com.zgs.genericity.demo6;
/**
* @author: guisong.zhang
* @date: 2024/3/1 11:17:43
* @description TODO
**/
public class Box<E> {
private E first;
public E getFirst() {
return first;
}
public void setFirst(E first) {
this.first = first;
}
}
package com.zgs.genericity.demo6;
/**
* @author: guisong.zhang
* @date: 2024/3/1 11:17:34
* @description 类型通配符
**/
public class MainClass {
public static void main(String[] args) {
Box<Number> numberBox = new Box<>();
numberBox.setFirst(100);
showBox(numberBox);
System.out.println("===============================");
//改用?后,Number Integer都可以调用了
Box<Integer> integerBox = new Box<>();
integerBox.setFirst(200);
showBox(integerBox);
}
//类型通配符?
public static void showBox(Box<?> box) {
Object first = box.getFirst();
System.out.println(first);
}
}
2.类型通配符的上限
- 语法:
类/接口<? extends 实参类型>
要求该泛型的类型,只能是实参类型,或实参类型的子类类型。 - 代码示例
三个父类子类
package com.zgs.genericity.demo7;
/**
* @author: guisong.zhang
* @date: 2024/3/1 14:29:10
* @description TODO
**/
public class Animal {
}
package com.zgs.genericity.demo7;
/**
* @author: guisong.zhang
* @date: 2024/3/1 14:29:18
* @description TODO
**/
public class Cat extends Animal {
}
package com.zgs.genericity.demo7;
/**
* @author: guisong.zhang
* @date: 2024/3/1 14:29:33
* @description TODO
**/
public class MiniCat extends Cat {
}
- 测试代码
package com.zgs.genericity.demo7;
import java.util.ArrayList;
/**
* @author: guisong.zhang
* @date: 2024/3/1 11:28:29
* @description 类型通配符上限-测试
**/
public class MainClass {
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList();
ArrayList<Cat> cats = new ArrayList();
ArrayList<MiniCat> miniCats = new ArrayList();
//addAll方法就有使用到上限通配符
// cats.addAll(animals);
cats.addAll(miniCats);
//animal会报错
// showAnimal(animals);
showAnimal(cats);
showAnimal(miniCats);
}
/**
* 泛型上限通配符,传递的类型只能Cat或者cat的子类
*
* @author guisong.zhang
* @date 2024/3/1 14:32
*/
public static void showAnimal(ArrayList<? extends Cat> list) {
//注意这种上限通配符,是不能操作在里面新增的等等,因为我们并不能确定这个上限list中传的到底是那种元素
// list.add(new Cat());
for (Cat cat : list) {
System.out.println(cat);
}
}
}
3.类型通配符的下限
- 语法:
类/接口<? super 实参类型>
要求该泛型的类型,只能是实参类型,或实参类型的父类类型。 - 代码实例
package com.zgs.genericity.demo8;
import com.zgs.genericity.demo7.Animal;
import com.zgs.genericity.demo7.Cat;
import com.zgs.genericity.demo7.MiniCat;
import java.util.ArrayList;
/**
* @author: guisong.zhang
* @date: 2024/3/1 14:41:14
* @description 类型通配符下限测试类
**/
public class MainClass {
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList();
ArrayList<Cat> cats = new ArrayList();
ArrayList<MiniCat> miniCats = new ArrayList();
showAnimal(animals);
showAnimal(cats);
//泛型下限通配符,传递的类型只能Cat或者cat的父类
// showAnimal(miniCats);
}
/**
* 泛型下限通配符,传递的类型只能Cat或者cat的父类
*
* @author guisong.zhang
* @date 2024/3/1 14:32
*/
public static void showAnimal(ArrayList<? super Cat> list) {
//下限通配符可以对其进行操作,但并不能保证元素类型的约束要求
list.add(new Cat());
list.add(new MiniCat());
// list.add(new com.zgs.genericity.demo8.Animal());
for (Object obj : list) {
System.out.println(obj);
}
}
}
- 下限通配符巩固练习
package com.zgs.genericity.demo9;
/**
* @author: guisong.zhang
* @date: 2024/3/1 14:29:10
* @description TODO
**/
public class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
'}';
}
}
package com.zgs.genericity.demo9;
/**
* @author: guisong.zhang
* @date: 2024/3/1 14:29:18
* @description TODO
**/
public class Cat extends Animal {
public int age;
public Cat(String name, int age) {
super(name);
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.zgs.genericity.demo9;
/**
* @author: guisong.zhang
* @date: 2024/3/1 14:29:33
* @description TODO
**/
public class MiniCat extends Cat {
public int level;
public MiniCat(String name, int age, int level) {
super(name, age);
this.level = level;
}
@Override
public String toString() {
return "MiniCat{" +
"name='" + name + '\'' +
", age=" + age +
", level=" + level +
'}';
}
}
package com.zgs.genericity.demo9;
import java.util.Comparator;
import java.util.TreeSet;
/**
* @author: guisong.zhang
* @date: 2024/3/1 14:48:37
* @description jdk对下限通配符的使用
**/
public class MainClass {
public static void main(String[] args) {
// TreeSet<Cat> treeSet = new TreeSet<>(new Comparator1());
TreeSet<Cat> treeSet = new TreeSet<>(new Comparator2());
// TreeSet<Cat> treeSet = new TreeSet<>(new Comparator3());
//使用Comparator1与Comparator2都可以,但是不能使用Comparator3 因为TreeSet使用了下限通配符
//所以我们只能使用Cat以及Cat的父类
treeSet.add(new Cat("张贵松", 26));
treeSet.add(new Cat("易欢", 18));
treeSet.add(new Cat("冉述保", 27));
treeSet.add(new Cat("许开聪", 28));
for (Cat cat : treeSet) {
System.out.println(cat);
}
}
}
class Comparator1 implements Comparator<Animal> {
@Override
public int compare(Animal o1, Animal o2) {
return o1.name.compareTo(o2.name);
}
}
class Comparator2 implements Comparator<Cat> {
@Override
public int compare(Cat o1, Cat o2) {
return o1.age - o2.age;
}
}
class Comparator3 implements Comparator<MiniCat> {
@Override
public int compare(MiniCat o1, MiniCat o2) {
return o1.level - o2.level;
}
}
类型擦除
1.概念
-
泛型是Java 1.5版本才引进的概念,在这之前是没有泛型的,但是泛型代码能够很好地和之前版本的代码兼容。那是因为,泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉,我们称之为–类型擦除。
-
代码理解
package com.zgs.genericity.demo10;
import java.util.ArrayList;
/**
* @author: guisong.zhang
* @date: 2024/3/1 15:10:25
* @description 类型擦除
**/
public class MainClass {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
ArrayList<String> strings = new ArrayList<>();
//这两个输出的都是ArrayList,我们可以看出Integer与String都已经被擦除了,本质上都是ArrayList,这就是类型擦除
System.out.println(integers.getClass().getSimpleName());
System.out.println(strings.getClass().getSimpleName());
System.out.println(integers.getClass() == strings.getClass());
}
}
2.分类:
- 无限制类型擦除
- 代码实例
package com.zgs.genericity.demo10;
/**
* @author: guisong.zhang
* @date: 2024/3/1 15:15:08
* @description TODO
**/
public class Erasure<T> {
private T key;
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
}
package com.zgs.genericity.demo10;
import java.lang.reflect.Field;
/**
* @author: guisong.zhang
* @date: 2024/3/1 15:15:46
* @description 类型擦除
**/
public class MainClass1 {
public static void main(String[] args) {
/**
* 无限制类型擦除
*/
Erasure<Integer> erasure = new Erasure<>();
//通过反射获取Erasure的字节码文件class类对象
Class<? extends Erasure> clazz1 = erasure.getClass();
//获取所有的成员变量
Field[] declaredFields = clazz1.getDeclaredFields();
//打印成员变量的名称和类型
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName() + "---------" + declaredField.getType().getSimpleName());
}
}
}
//输出:key---------Object
- 有限制类型擦除
- 代码示例
package com.zgs.genericity.demo11;
/**
* @author: guisong.zhang
* @date: 2024/3/1 15:15:08
* @description TODO
**/
public class Erasure<T extends Number> {
private T key;
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
}
package com.zgs.genericity.demo11;
import java.lang.reflect.Field;
/**
* @author: guisong.zhang
* @date: 2024/3/1 15:15:46
* @description 类型擦除
**/
public class MainClass {
public static void main(String[] args) {
/**
* 有限制类型擦除
*/
Erasure<Integer> erasure = new Erasure<>();
//通过反射获取Erasure的字节码文件class类对象
Class<? extends Erasure> clazz1 = erasure.getClass();
//获取所有的成员变量
Field[] declaredFields = clazz1.getDeclaredFields();
//打印成员变量的名称和类型
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName() + "---------" + declaredField.getType().getSimpleName());
}
}
}
//输出:key---------Number
- 擦除方法中类型定义的参数
- 代码示例
package com.zgs.genericity.demo12;
import java.util.List;
/**
* @author: guisong.zhang
* @date: 2024/3/1 15:15:08
* @description TODO
**/
public class Erasure<T extends Number> {
private T key;
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
/**
* 定义一个泛型方法
*
* @author guisong.zhang
* @date 2024/3/1 15:32
*/
public <T extends List> T show(T t) {
return t;
}
}
package com.zgs.genericity.demo12;
import java.lang.reflect.Method;
/**
* @author: guisong.zhang
* @date: 2024/3/1 15:33:08
* @description TODO
**/
public class MainClass {
public static void main(String[] args) {
Erasure<Integer> erasure = new Erasure();
//通过反射获取Erasure的字节码文件class类对象
Class<? extends Erasure> clazz = erasure.getClass();
//获取所有的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod.getName() + "------" + declaredMethod.getReturnType().getSimpleName());
}
}
}
/**
* 输出
* getKey------Number
* show------List
* setKey------void
*/
- 桥接方法
- 代码示例
package com.zgs.genericity.demo13;
/**
* @author guisong.zhang
* @date 2024/3/1 15:57
* @description 泛型接口
*/
public interface Info<T> {
T info(T t);
}
package com.zgs.genericity.demo13;
/**
* @author: guisong.zhang
* @date: 2024/3/1 15:58:30
* @description TODO
**/
public class InfoImpl implements Info<Integer> {
@Override
public Integer info(Integer value) {
return value;
}
}
package com.zgs.genericity.demo13;
import java.lang.reflect.Method;
/**
* @author: guisong.zhang
* @date: 2024/3/1 16:00:14
* @description 桥接方法
**/
public class MainClass {
public static void main(String[] args) {
Class<InfoImpl> infoClass = InfoImpl.class;
Method[] declaredMethods = infoClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod.getName() + "--------" + declaredMethod.getReturnType().getSimpleName());
}
}
}
//输出:info--------Integer;info--------Object
泛型与数组
泛型数组的创建
- 1:可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象
ArrayList<String>[] listArr = new ArrayList<5>(); //会报错
会报错
ArrayList[] list = new ArrayList[5];
ArrayList<String>[] listArr = list;
或者
ArrayList<String>[] listArr = new ArrayList[5];
不会报错
- 这样写带来的问题
package com.zgs.genericity.demo14;
import java.util.ArrayList;
/**
* @author: guisong.zhang
* @date: 2024/3/1 16:07:45
* @description 泛型数组
**/
public class MainClass {
public static void main(String[] args) {
//会报错
// ArrayList<String>[] listArr = new ArrayList<5>();
//可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象
ArrayList[] arrayLists = new ArrayList[5];
ArrayList<String>[] strListArr = arrayLists;
ArrayList<Integer> intList = new ArrayList<>();
intList.add(100);
arrayLists[0] = intList;
String s = strListArr[0].get(0);
System.out.println(s);
}
}
会报错
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at com.zgs.genericity.demo14.MainClass.main(MainClass.java:23)
- 正确写法
ArrayList<String>[] listArr = new ArrayList[5];
ArrayList<String> strList = new ArrayList<>();
strList.add("aaa");
listArr[0] = strList;
String s = listArr[0].get(0);
System.out.println(s);
//输出: aaa
- 2:可以通过java.lang.reflect.Array的newInstance(Class,int)创建T[]数组
- 代码实例
package com.zgs.genericity.demo15;
import java.lang.reflect.Array;
/**
* @author: guisong.zhang
* @date: 2024/3/1 16:29:36
* @description TODO
**/
public class Fruit<T> {
private T[] array;
public Fruit(Class<T> clazz, int len) {
//通过Array.newInstance创建泛型数组
array = (T[]) Array.newInstance(clazz, len);
}
public void put(T t, int idnex) {
array[idnex] = t;
}
public T get(int index) {
return array[index];
}
public T[] getAll() {
return array;
}
}
package com.zgs.genericity.demo15;
import java.util.Arrays;
/**
* @author: guisong.zhang
* @date: 2024/3/1 16:34:18
* @description TODO
**/
public class MainClass {
public static void main(String[] args) {
Fruit<String> fruit = new Fruit(String.class, 3);
fruit.put("苹果", 0);
fruit.put("梨子", 1);
fruit.put("西瓜", 2);
String s = fruit.get(0);
System.out.println(s);
System.out.println("===================");
String[] all = fruit.getAll();
System.out.println(Arrays.toString(all));
}
}
泛型和反射
- 反射常用的泛型类
Class
Constructor
package com.zgs.genericity.demo16;
/**
* @author: guisong.zhang
* @date: 2024/3/1 16:40:49
* @description TODO
**/
public class Person {
private String name;
private int age;
public Person() {
}
public Person(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;
}
}
package com.zgs.genericity.demo16;
import java.lang.reflect.Constructor;
/**
* @author: guisong.zhang
* @date: 2024/3/1 16:41:28
* @description 泛型与反射
**/
public class MainClass {
public static void main(String[] args) throws Exception {
// Class<Person> personClass = Person.class;
// Constructor<Person> constructor = personClass.getConstructor();
// Person person = constructor.newInstance();
Class personClass = Person.class;
Constructor constructor = personClass.getConstructor();
Object instance = constructor.newInstance();
}
}