Java学习笔记 13、泛型

简介: Java学习笔记 13、泛型

一、认识泛型


首先提出一个问题:为什么有泛型?


设计背景:集合容器在设计阶段/声明阶段不能确定该容器实际存的是什么类型的对象,所以在JDK1.5之前统一将容器中的元素设计为Object,在JDK1.5之后使用泛型来解决。

将元素的类型设计成一个参数,这个参数就叫做泛型。例如:interface Collection<E> extends Iterable<E>其中的E就是泛型,根据传入类型来定。

泛型:就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时确定(例如继承实现某某接口,声明变量,创建对象)。


一个类继承了父类,那么就能通过它的父类找到对应的子类,但是不能通过其他类来找到具体要找的和这个类。

好处:使用泛型能够规范集合中的元素,避免了强转出现异常的情况,没有实现泛型前是类型不安全的。


重要点:JDK1.5改写了集合框架中的全部接口和类,为这些接口、类增加了泛型支持。若是不指定类型也可以默认是Object。



JDK1.7新特性:类型推断


//当我们创建实例时,new后面不需要设置指定类型了(前面一定要有)
Map<String,Integer> map = new HashMap<>();



二、自定义泛型结构


自定义泛型举例


class MyGeneric<T>{
    private String name;
    private T Order;
    public void setOrder(T order) {
        Order = order;
    }
    public T getOrder() {
        return Order;
    }
}


这里T作为泛型,等待创建实例传入指定的类型参数,并且该类属性也能够使用该泛型。


继承泛型类两种方式

方式一:不属于泛型类,直接确定类型


//当子类不使用泛型时,其继承的类需要明确类型
class Type1 extends MyGeneric<String>{//这里使用的上面自定义例子的类
}


方式二:属于泛型类,根据传过来的类型决定


//可以通过创建Type2实例时将类型也传递给MyGeneric
class Type2<T> extends MyGeneric<T>{
}



自定义泛型注意点

1、泛型类可以有多个参数,多个参数要一起放在<>中,例如<T,E,K>。


2、泛型类的构造器不需要使用<E>,和往常一样即可。


3、使用泛型类若是不指定类型,对应类型默认为Object。


4、若泛型类是一个接口或抽象类,不能创建泛型类的对象。


5、泛型指定只能使用引用数据类型,若是想要表示基本数据类型可用包装类代替。


6、异常类不能指定泛型。



三、泛型不同使用情境


泛型表示接口
interface MyGeneric<E>{
    E get();
}


一般泛型接口常用于生成器,即对象工厂,一种专门用来创建类的工厂对象。



泛型方法

泛型方法:在方法中出现泛型的结构,泛型参与类的泛型参数没有任何关系。


情况一:使用类中的泛型


class MyGeneric<T>{
    private String name;
    private T Order;
    //这里的T与创建实例时传入的类型一致
    public List<T> getList(List<T> arr){
        return arr;
    }
}


情况二:若是单独在方法中使用泛型,则需要在返回参数之前加上类似于<E>标记


class MyGeneric<T>{
    private String name;
    private T Order;
    //为了让E不表示一个类而是一个参数则需要在返回参数前加<E>
    public <E> List<E> copy(List<E> arr){
        return arr;
    }
}


不加标记会将E识别为一个类,从而找不到该类出现编译错误:




四、泛型继承上的体现


①类A是类B的超类,G<A> 和 G<B> 二者不具备子父类关系,二者是并列关系



②类A是类B的父类,A<G> 是 B<G> 的父类



总结:对于具有子父类关系的泛型类,其泛型应该一致,否则不具备子父类关系。



五、通配符使用


通配符为:?


通过使用?通配符能够解决之前G<A> 和 G<B>的问题,这两者共同的父类为G<?>



运用到方法中:


import java.util.*;
public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        traversal(list);
        traversal(list2);
    }
    //可遍历任意list<A> List<B>
    public static void traversal(List<?> list){
        Iterator<?> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //或者
//        for (Object o : list) {
//            System.out.println(o);
//        }
    }
}



注意点:例如上面List使用?不能进行add()的添加操作,获取值也只能获取到Object类型。


@Test


public void test(){
    List<String> list1 = new ArrayList<>();
    //给list1添加两个String字符串
    list1.add("AA");
    list1.add("BB");
    List<?> list2 = null;
    list2 = list1;
    //添加(写入):对于List<?> 就不能向其内部添加数据
    //除了添加null之外
    //        list2.add("AA");
    //        list2.add('?');//两个都会进行报错
    list2.add(null);//添加null值是允许的
    //获取读取:允许读取数据,读取的数据类型为Object
    Object o = list2.get(0);
    System.out.println(o);//AA
}



有限制条件的通配符使用


<? extends Number>:只允许泛型为Number及Number子列的引用调用。


<? super Number>:只允许泛型为Number及Number父类的引用调用。


extends:使用时只能使用对应类及其子类。

super:使用时只能使用对应类及其父类。

例子如下:


public static void main(String[] args) {
    List<? extends Person> list = new ArrayList<>();
    List<? super Person> list2 = new ArrayList<>();
    List<Person> list3 = new ArrayList<>();
    List<Student> list4 = new ArrayList<>();
    List<Object> list5 = new ArrayList<>();
    //赋值操作
    list = list3;
    list = list4;
    list = list5;//无法赋值,Object是Person父类
    list2 = list3;
    list2 = list4;//无法赋值,Student是Person子类
    list2 = list5;
    //获取对应值
    Person person = list.get(0);//由于泛型范围为Person及其子类,所以返回一个最大父类Person
    Object object = list2.get(0);//由于泛型范围为Person及其父类,所以返回一个最大父为Object
}



注意其中引用赋值范围以及获取对应泛型参数值的范围!!!


六、泛型中E、T、K等含义


其实可以使用任何合法的Java标识字符串,习惯用法是单一的字母表示,为了好辨识某些泛型的含义,特使用如下几个字母:


E:可表示Element,一般在集合中使用,集合中存放元素。

T:可表示Type,Java类。

K:可表示Key,作为键,Map中使用到。

V:可表示Value,作为值,Map中使用到。

N:Number,数值类型。

?:表示不确定的java类型。


目录
打赏
0
0
0
0
25
分享
相关文章
2025 年 Java 从入门到精通学习笔记全新版
《Java学习笔记:从入门到精通(2025更新版)》是一本全面覆盖Java开发核心技能的指南,适合零基础到高级开发者。内容包括Java基础(如开发环境配置、核心语法增强)、面向对象编程(密封类、接口增强)、进阶技术(虚拟线程、结构化并发、向量API)、实用类库与框架(HTTP客户端、Spring Boot)、微服务与云原生(容器化、Kubernetes)、响应式编程(Reactor、WebFlux)、函数式编程(Stream API)、测试技术(JUnit 5、Mockito)、数据持久化(JPA、R2DBC)以及实战项目(Todo应用)。
67 5
# 【Java全栈学习笔记-U1-day02】变量+数据类型+运算符
本篇笔记主要围绕Java全栈学习的第二天内容展开,涵盖了变量、数据类型、运算符以及Scanner类的应用。首先介绍了变量的概念与命名规范,以及如何定义和使用变量;接着详细讲解了Java中的基本数据类型,包括整型、浮点型、字符型、布尔型等,并通过实例演示了数据类型的运用。随后,深入探讨了各类运算符(赋值、算术、关系、逻辑)及其优先级,帮助理解表达式的构成。最后,介绍了如何利用Scanner类实现用户输入功能,并通过多个综合示例(如计算圆面积、购物打折、变量交换及银行利息计算)巩固所学知识。完成相关作业将进一步加深对这些基础概念的理解与实践能力。
62 12
【Java全栈学习笔记-U1-day01】Java介绍
本笔记整理了Java学习的基础内容,涵盖程序理解、Java语言特性、JDK安装与配置、Java程序开发工具及编写步骤。重点介绍了Java程序的基本结构、编译和运行过程,以及输出语句的使用。通过实例演示了IDEA创建Java程序的方法,并强调了编码规范和注意事项。适合初学者复习和交流学习。 主要内容: 1. 理解程序:计算机组成、程序定义。 2. 简介:Java语言特点、技术平台、JDK作用。 3. 编写Java程序:编写、编译、运行步骤,基本结构。 4. 输出语句 5. DEA使用:新建工程、保存位置、文件介绍、新建类。 6. 扩展:注释、代码规范、大小写敏感、缩进等。
Java——包装类和泛型
包装类是Java中一种特殊类,用于将基本数据类型(如 `int`、`double`、`char` 等)封装成对象。这样做可以利用对象的特性和方法。Java 提供了八种基本数据类型的包装类:`Integer` (`int`)、`Double` (`double`)、`Byte` (`byte`)、`Short` (`short`)、`Long` (`long`)、`Float` (`float`)、`Character` (`char`) 和 `Boolean` (`boolean`)。包装类可以通过 `valueOf()` 方法或自动装箱/拆箱机制创建。
113 9
Java——包装类和泛型
|
9月前
|
🌱Java零基础 - 泛型详解
【10月更文挑战第7天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
76 1
java数据结构泛型
java数据结构泛型
74 5
|
9月前
|
Java集合定义其泛型
Java集合定义其泛型
53 1
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
158 0
【用Java学习数据结构系列】初识泛型
【用Java学习数据结构系列】初识泛型
62 2
Java中的泛型
【9月更文挑战第15天】在 Java 中,泛型是一种编译时类型检查机制,通过使用类型参数提升代码的安全性和重用性。其主要作用包括类型安全,避免运行时类型转换错误,以及代码重用,允许编写通用逻辑。泛型通过尖括号 `&lt;&gt;` 定义类型参数,并支持上界和下界限定,以及无界和有界通配符。使用泛型需注意类型擦除、无法创建泛型数组及基本数据类型的限制。泛型显著提高了代码的安全性和灵活性。
105 8

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问