java数据类型:集合存储元素类型限制<泛型> ;自定义类指定泛型<T> 以及限制用法;派生子类泛型<T> super(泛型内参数); 泛型通配符?以及?限制用法
问题背景
import java.util.ArrayList; import java.util.List; public class ProblemTest { public static void main(String[] args) { List persons = new ArrayList(); persons.add("李一桐"); persons.add("刘亦菲"); persons.add("鞠婧祎"); //不小心加入了一个int类型的数据 persons.add(10); persons.forEach(person -> System.out.println(((String) person).length())); //报错int转换不成String报错 } }
解决:
- 为要存储的元素/变量 灵活指定数据类型
1、泛型使用:
- 作用:<泛型>指定集合存储元素的类型
- 集合类<元素类型..> = new 集合类<>;
Set<String> persons = new HashSet<>(); Map<String, Integer> persons = new HashMap<>();
2、自定义泛型
语法:
自定义类名<泛型形参>{ ... }

我们就是在类名的后面加上类型的替代符,比如上面的T,K,V。我们在使用的时候,就直接把这些T,K,V替换成对应的类型名称就好了。
/** * @ClassName MyDefineClassInitTypeExample * @projectName: object1 * @author: Zhangmingda * @description: 自定义泛型测试 * date: 2021/4/11. */ public class MyDefineClassInitTypeExample { private static class Student<T>{ private T type; public Student(T type) { this.type = type; } public T getType() { return type; } } public static void main(String[] args) { Student<String> student = new Student<>("高中"); System.out.println(student.getType());//高中 Student<Integer> student1 = new Student<>(202101); System.out.println(student1.getType());//202101 } }
3、从泛型类派生子类
语法:
自定义子类名<子类泛型形参> extends 父类名<泛型形参> {
子类构造方法(数据类型|子类泛型形参 形参){
super(形参)
}
}
private static class ElementaryStudent extends Student<T>{ public ElementaryStudent(T type){ super(type); } }
public class MyDefineClassInitTypeExample { private static class Student<T>{ private T type; public Student(T type) { this.type = type; } public T getType() { return type; } } private static class ElementaryStudent extends Student<String>{ public ElementaryStudent(String type){ super(type); } } public static void main(String[] args) { ElementaryStudent elementaryStudent = new ElementaryStudent("小学"); System.out.println(elementaryStudent.getType()); //小学 } }
定义一个子类的时候,无法指定父类泛型的具体类型:则
/** * @ClassName MyDefineClassInitTypeExample * @projectName: object1 * @author: Zhangmingda * @description: 自定义泛型测试 * date: 2021/4/11. */ public class MyDefineClassInitTypeExample { private static class Student<T>{ private T type; public Student(T type) { this.type = type; } public T getType() { return type; } } private static class ElementaryStudent<T> extends Student<T>{ public ElementaryStudent(T type){ super(type); } } public static void main(String[] args) { ElementaryStudent<Integer> elementaryStudent1 = new ElementaryStudent<>(202107); System.out.println(elementaryStudent1.getType()); } }
- 用一个支持泛型的类,创建不同类型的实例,他们还是同一个类的实现。
ElementaryStudent<Integer> elementaryStudent1 = new ElementaryStudent<>(202107); System.out.println(elementaryStudent1.getType()); ElementaryStudent<String> elementaryStudent2 = new ElementaryStudent<>("幼儿园"); System.out.println(elementaryStudent2.getType()); System.out.println(elementaryStudent1.getClass()); //class MyDefineClassInitTypeExample$ElementaryStudent System.out.println(elementaryStudent2.getClass()); //class MyDefineClassInitTypeExample$ElementaryStudent System.out.println(elementaryStudent.getClass().equals(elementaryStudent2.getClass()));//true
4、 泛型通配符?
问题:List<Object> 和 List<String> 什么关系,要求传入List<Object> 传入List<String> 行不行?
import java.util.ArrayList; import java.util.List; public class ProblemTest { private static void test(List<Object> list) { for (Object o : list) { System.out.println(o); } } public static void main(String[] args) { List<String> persons = new ArrayList<>(); persons.add("李 "); persons.add("刘 "); persons.add("祎"); test(persons); //不行,他们是同一类不同的实现,不是子类关系 } }
解决:用通配符?替代泛型<Object>
import java.util.ArrayList; import java.util.List; /** * @ClassName wildcardExample * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/4/11. */ public class WildcardExample { private static void test(List<?> list){ list.forEach(o -> System.out.println(o)); } public static void main(String[] args) { List<String> list = new ArrayList(); list.add("张三"); list.add("李四"); test(list); /** * 张三 * 李四 */ } }
5、限定通配符适配范围
5.1 在List集合使用中限定示例代码:继承Animal类的子类都匹配
语法:
<?extends 类名>
本例如果直接指定List<Animal>泛型,Dog和Cat虽然是Animal的子类,但是List<Dog> List<Cat> 和<List Animal>之间并不是子类关系,List<Dog> 或List<Cat>不能匹配<List Animal>。
import java.util.ArrayList; import java.util.List; /** * @ClassName wildcardExample * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/4/11. */ public class WildcardLimitExample { private static class Animal{ public void say(){ System.out.println("动物叫了.........."); } } private static class Dog extends Animal{ @Override public void say() { System.out.println("I am Dog : 汪汪汪"); } } private static class Cat extends Animal{ @Override public void say() { System.out.println("I am Cat : 喵喵喵!!!"); } } public static void animalSay(List<? extends Animal> animals){ animals.forEach(animal -> animal.say()); } public static void main(String[] args) { List<Animal> animals = new ArrayList<>(); animals.add(new Dog()); animals.add(new Cat()); animalSay(animals); /** * I am Dog : 汪汪汪 * I am Cat : 喵喵喵!!! */ System.out.println("==================="); List<Dog> dogs = new ArrayList<>(); dogs.add(new Dog()); animalSay(dogs); List<Cat> cats = new ArrayList<>(); cats.add(new Cat()); animalSay(cats); /** * I am Dog : 汪汪汪 * I am Cat : 喵喵喵!!! */ } }
5.2在类的定义过程中给泛型限定范围
语法:
修饰符... class<T extends 父类名 [& 接口名] >
- 形参T代表数据类型 extends 后面为T要继承或实现的接口
如下类class CustomerNumber<T extends Number & Serializable> 的意义为:
在用该类创建对象时候如果指定泛型,指定传入构造方法的数据类型T必须是 继承了Number类并且实现了Serializable接口的数据类型。
import java.io.Serializable; import java.text.NumberFormat; /** * @ClassName WildcardLimitCustomerNumberExample * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/4/11. */ public class WildcardLimitCustomerNumberExample { private static class CustomerNumber<T extends Number & Serializable>{ private T info; public CustomerNumber(T info) { this.info = info; } public T getInfo() { return info; } } public static void main(String[] args) { CustomerNumber<Integer> customerNumber = new CustomerNumber<>(1); System.out.println(customerNumber.getInfo()); } }
posted on 2021-04-11 12:28 zhangmingda 阅读(1143) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2020-04-11 以太网/ IPV4/IPV6包头,TCP包头格式回顾
2020-04-11 TCP 长连接保活机制&HTTP长连接设置
2020-04-11 WebSocket协议理解-数据包格式解析