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());
}
}
java数据类型:集合存储元素类型限制<泛型> ;自定义类指定泛型<T> 以及限制用法;派生子类泛型<T> super(泛型内参数); 泛型通配符?以及?限制用法的更多相关文章
- HashSet集合存储数据的结构和HashSet集合存储元素不重复的原理
HashSet集合存储数据的结构 HashSet集合存储元素不重复的原理 //创建HashSet集合对象 Hashset<String> set = new HashSet<> ...
- JDBC数据类型、Java数据类型、标准sql类型
本概述是从<JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference>这本书中摘引来的.JavaSoft ...
- JAVA数据类型中的char类型
1.JAVA中,char占2字节,16位.可在存放汉字 2.char赋值 char a='a'; //任意单个字符,加单引号. char a='中';//任意单个中文字,加单引号. char a=11 ...
- 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_06 Set集合_4_Set集合存储元素不重复的原理
set集合元素为什么不能重复 集合重写了toString的方法所以打印是里面的内容 往里面存了三次abc 哈希表,初始容量是16个 set集合存储字符串的时候比较特殊 横着是数组,竖着就是链表结构.跟 ...
- 向集合中添加自定义类型--建议在自定义类型的时候要重写equals方法
package com.bjpowernode.t01list; import java.util.ArrayList; /* * 向集合中添加自定义类型 */public class TestLis ...
- Java中集合删除元素时候关于ConcurrentModificationException的迷惑点
下面的示例来至于阿里巴巴Java开发手册的集合处理部分的第7条: 运行如下代码,会发现正确运行. public static void hasNotExcption() { List<Strin ...
- Java操作Redis存储对象类型数据
背景描述 关于JAVA去操作Redis时,如何存储一个对象的数据,大家是非常关心的问题,虽然官方提供了存储String,List,Set等等类型,但并不满足我们现在实际应用.存储一个对象是是 ...
- java按照集合中元素的属性进行排序示例代码
public class Student { private String name; private int age; private int id; public Student() { sup ...
- Java 数据类型:集合接口Collection之Set接口HashSet类;LinkedHashSet;TreeSet 类
Collection 之 Set 实现类: HashSet TreeSet 特点: 无序. 元素不可重复. (如果试图添加一个已经有的元素到一个Set集合中,那么会添失败,add()方法返回false ...
随机推荐
- round函数和获取当前时间函数
round函数:对一个浮点类型的数据进行四舍五入:round(3.14) 运行结果就是3 获取当前时间: time.time() ,time函数需要导入才能使用,import time
- AT3945 [ARC092D] Two Faced Edges
要求,翻转一条边,强连通分量个数是否会改变. 考虑连通分量个数会改变的因素: 即\(v\to u\)是否成立,以及翻转前,是否有一条\(u \to v\)的路径不经过该条边 以上当只有一个满足时,连通 ...
- 力扣 - 剑指 Offer 47. 礼物的最大价值
题目 剑指 Offer 47. 礼物的最大价值 思路1 因为是要求最大价值,而且只能移动下方或者右方,因此,每个位置的最大值就是本身的值加上上边 / 左边 中的最大值,然后每次遍历都可以复用上一次的值 ...
- Anaconda 安装与卸载
Anaconda是一个免费开源的Python和R语言的发行版本,用于计算科学(数据科学.机器学习.大数据处理和预测分析),Anaconda致力于简化软件包管理系统和部署.Anaconda的包使用软件包 ...
- Go知识点大纲
目录 1. 基本介绍 2. 安装及配置 3. 变量 4. 常量 5. 数据类型 5.1 numeric(数字) 5.2 string(字符串) 5.3 array(数组) 5.4 slice(切片) ...
- 53-Linked List Cycle II
Linked List Cycle II My Submissions QuestionEditorial Solution Total Accepted: 74093 Total Submissio ...
- 为什么重写equals必须重写hashCode
目录 equals常见面试题 为什么要重写equals 重写equals不重写hashCode会存在什么问题 总结 equals常见面试题 在开始聊之前,我们先看几个常见的面试题,看看你能不能都回答上 ...
- A Child's History of England.11
CHAPTER 4 ENGLAND UNDER ATHELSTAN AND THE SIX BOY-KINGS Athelstan, the son of Edward the Elder, succ ...
- day05文件编辑命令
day05文件编辑命令 mv命令:移动文件 mv命令:mv命令用来对文件或目录重新命名,或者将文件从一个目录移到另一个目录中. 格式:mv [原来的文件路径] [现在的文件路径] mv命令后面既可以跟 ...
- Linux磁盘分区(二)之挂载卸载常用命令
Linux磁盘分区(二)之挂载卸载常用命令 转自:https://blog.csdn.net/qq_36183935/article/details/81053383 https: ...