JAVA---泛型

news2024/11/29 11:50:41

一、什么是泛型

        Java的泛型 (generics) 是在JDK5中推出的新概念,在泛型推出之前,程序员需要构建一个元素为Object的集合,该集合能够存储任意的数据类型对象,而在使用该集合的过程中,需要程序员明确知道存储每个元素的数据类型,否则会发生ClassCastException (类转换异常)

        而泛型提供了编译时类型安全监测机制,允许我们在编译时检测到非法的类型数据结构,它的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数 (形参),

        以ArrayList举例子来说,通过查看ArrayList源码可以看到,ArrayList中可以存放任意的类型是因为有一个泛型<E>,当new一个ArrayList并在泛型中放任意的类型之后此时这个ArrayList就只能存泛型中存放的这个类型的对象,这就是泛型的作用

        泛型的好处就在于可以让类型的存放更安全并且可以避免强制类型的转换不会报ClassCastException


二、泛型类

1、语法定义

class 类名<泛型标识, 泛型标识, ...>{

    private 泛型标识 变量名;

    .....

}

使用语法

类名<具体数据类型> 对象名 = new 类名<具体数据类型>();

java1.7之后,后面的<>中的具体的数据类型可以省略不写

类名<具体的数据类型> 对象名 = new 类名<>();

注意事项:

泛型类,如果没有指定具体的数据类型,此时操作类型是Object

 <具体数据类型> 泛型中只能存放包装类

 泛型类在逻辑上可以看成是多个不同的类型,但实际上都是相同类型

例:

public class Test1<T> {
    private T key;

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }
}

public class MainMethod {
    public static void main(String[] args) {
        Test1<String> test1 = new Test1<>();
        test1.setKey("abc");
        System.out.println("test1存的key为:" + test1.getKey());
        System.out.println("test1的类型为:" + test1.getClass().getSimpleName());
        System.out.println("test1存的key的类型为:" + test1.getKey().getClass().getSimpleName());
    }
}

同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型

public class MainMethod {
    public static void main(String[] args) {
        Test1<String> test1 = new Test1<>();
        test1.setKey("abc");
        System.out.println("test1的类型为:" + test1.getClass());

        Test1<Integer> test2 = new Test1<>();
        test2.setKey(100);
        System.out.println("test2的类型为:" + test2.getClass());

        System.out.println(test1.getClass() == test2.getClass());
    }
}

多个泛型

public class Test1<T,V> {
    private T key;
    private V value;

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }

    public V getValue() {
        return value;
    }

    public void setValue(V value) {
        this.value = value;
    }
}

public class MainMethod {
    public static void main(String[] args) {
        Test1<String,Integer> test1 = new Test1<>();
        test1.setKey("number");
        test1.setValue(100);
        System.out.println(test1.getKey() + ":" + test1.getValue());
    }
}

2、常用的泛型标识: T、E、K、V、?

T (type) 表示具体的一个java类型   常用在定义单个对象或者单个方法时

E (element) 代表元素   常在集合中使用

K V  分别代表java键值中的Key和Value   常用在类似于map的集合中

?表示不确定的 java 类型   常在上下限中使用


三、泛型类派生子类

1、语法定义

子类也是泛型类,子类和父类的泛型类型要一致

 class Children<T> extends Father<T>

子类不是泛型类,父类要明确泛型的数据类型

class Children extends Father<具体类型>

2、使用场景

 

 可以看出使用instanceof之后调用的是children的属性

 要是父类.属性调用的就是父类的

 


四、泛型接口

1、语法定义

interface 接口名<泛型标识,泛型标识, ...>{

   泛型标识 方法名();

   .....

}

2、泛型接口的使用

实现类不是泛型类,接口要明确数据类型

实现类也是泛型类,实现类和接口的泛型类型要一致

例:

public interface InMethod<T> {
    T getKey(T t);
}
//如果此时实现接口后泛型中不指定具体类型那么重新接口的方法和派生子类一样是Object
public class claMethod implements InMethod{


    @Override
    public Object getKey(Object o) {
        return null;
    }
}

//如果此时实现接口后泛型中指定具体的类型那么重写接口方法之后返回的就是定义的类型
public class claMethod implements InMethod<Integer>{


    @Override
    public Integer getKey(Integer integer) {
        return null;
    }
}

实现接口之后重写一下接口中的方法

public class ClaMethod implements InMethod<Integer>{

    @Override
    public Integer getKey(Integer integer) {
        return integer;
    }
}
public class MainMethod {
    public static void main(String[] args) {
        ClaMethod claMethod = new ClaMethod();
        Integer num = claMethod.getKey(100);
        System.out.println(num.getClass().getSimpleName());
    }
}

类实现接口并使用了接口中的方法后因为类没有定义泛型所以使用的类型是接口的类型

 

//接口中的泛型是实现类中泛型的其中一个就可以
public class ClaMethod<T,K,E> implements InMethod<K>{
    
    @Override
    public K getKey(K k) {
        return null;
    }
}


五、泛型方法

1、语法定义

修饰符 <T, E, ...> 返回值类型 方法名(形参列表) {

        方法体 ...

}

【注意】

·   public 与 返回值中间<T> 非常重要,可以理解为声明此方法为泛型方法。

·  只有声明了<T>的方法才是泛型方法,泛型类中 使用了泛型的成员方法并不是泛型方法

·  <T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T

·  与泛型类的定义一样,此处T可以随便写为任意标识,如 T、E、K、V等形式的参数常用于表示     泛型

例:

public class ClaMethod<T,K,E>{

    public <T> T getGeneric(T t){
        return t;
    }
}
public class MainMethod {
    public static void main(String[] args) {
        ClaMethod claMethod = new ClaMethod();
        String str = "abc";
        System.out.println(claMethod.getGeneric(str).getClass().getSimpleName());
    }
}

 

//要是调用的不是void方法 可以传多个类型 return的和上边返回的类型要一致
public <T,K> K GG(K k){
        return k;
    }

2、静态的泛型方法

public class ClaMethod<T,K,E>{
    //静态的泛型方法采用多个泛型类型
    public static <T,K,E> void getGenericType(T t,K k){
        System.out.println(t+"\t"+t.getClass().getSimpleName());
        System.out.println(k+"\t"+k.getClass().getSimpleName());
    }
}
public class MainMethod {
    public static void main(String[] args) {
        //static使用类名.方法名
        ClaMethod.getGenericType("abc",100);
    }
}

 

 3、泛型方法与可变参数

public <E> void print(E... e){

  for(E date : e){

     System.out.println(date);

  }

}

public class ClaMethod{

    public<E> void printE(E... e){
        for (E data : e) {
            System.out.println(data);
        }
    }
}
public class MainMethod {
    public static void main(String[] args) {
        ClaMethod claMethod = new ClaMethod();
        claMethod.printE("a","b","c");
    }
}

 

4、泛型方法和泛型类的区别

泛型类,是在实例化类的时候指明泛型的具体类型

泛型方法,是在调用方法的时候指明泛型的具体类型

5、泛型方法总结

泛型方法能使方法独立于类而产生变化

泛型可以使用多个,要是没有void 就return其中一个泛型,要是有void那么就正常输出就好

静态的泛型方法和普通泛型方法的区别是 静态的泛型方法是在泛型前多加一个static


六、类型通配符

1、定义

类型通配符一般是使用 "?" 代替具体的类型实参,所以,类型通配符是类型实参,而不是类型形参

一般和上下限进行配合使用

2、示例

public class ListMethod {
    private String listKey;

    public ListMethod(String listKey) {
        this.listKey = listKey;
    }

    @Override
    public String toString() {
        return "ListMethod{" +
                "listKey='" + listKey + '\'' +
                '}';
    }
}

public class MainMethod {
    public static void main(String[] args) {
        ListMethod listMethod1 = new ListMethod("a");
        ListMethod listMethod2 = new ListMethod("b");
        ListMethod listMethod3 = new ListMethod("c");


        ArrayList<ListMethod> list = new ArrayList<>();
        list.add(listMethod1);
        list.add(listMethod2);
        list.add(listMethod3);
        MainMethod.getMethod(list);
    }

    public static void getMethod(List<?> list){
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/152715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt OpenGL(07)通过递归细分绘制球面

文章目录Qt OpenGL通过递归细分逼近球面思路下面就是绘制的代码&#xff1a;Widget.cpp顶点着色器片段着色器Qt OpenGL通过递归细分逼近球面 在OpenGL中绘制球面&#xff0c;不是太简单的事情。因为球面和圆都不是OpenGL所支持的图元&#xff0c;因此我们将通过一种称为递归细分…

年货小史:最土年货中藏着最真实的烟火气

农历新年很快就要到了&#xff0c;这让我有些恍惚&#xff0c;觉得从前那个满是烟火的新年&#xff0c;仿佛已经是很遥远的事了。几家电商平台最近又开始了红红火火的年货节&#xff0c;上去转了转&#xff0c;几个平台看下来&#xff0c;拼多多的“年味”似乎最贴近记忆中的烟…

MySQL的锁机制之全局锁和表锁

文章目录前言一、全局锁全局锁的介绍以及使用全局锁的应用场景不加锁导致的危害加锁和其他方法对比二、表锁表锁的介绍以及使用表锁的应用场景前言 对mysql锁的总结学习&#xff0c;本文将围绕&#xff0c;加锁的概念&#xff0c;加锁的应用场景和优化&#xff0c;以及不加锁会…

【C进阶】第十四篇——字符串函数

strlen - 求字符串长度 函数介绍 模拟实现(三种方式) strcpy - 字符串拷贝 函数介绍 模拟实现 strcat - 字符串追加 函数介绍 模拟实现 strcmp - 字符串比较 函数介绍 模拟实现 strstr - 字符串查找 函数介绍 模拟实现 strtok - 字符串分割 函数介绍 strerror…

小黑周末惊心动魄进“村”赶考,周一继续拖着疲惫的身体来实习的leetcode之旅:968. 监控二叉树

小黑看完题解思路后代码 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def minCameraCover(self, root: …

前端、后台(ueditor)富文本的使用和回显

前端、后台富文本的使用前端如何配置ueditorjson文件注释一、html、js引用ueditor二、后端返回ueditor的json文件1.配置接受ueditor的接口三、回显效果图&#xff1a; 前端如何配置ueditor 下载ueditor资源文件地址&#xff1a; ueditor资源文件压缩包下载 下载解压后放在…

LLM笔记

LLM其实就是large language model&#xff0c;大语言模型。 AGI其实就是Artificial General Intelligence&#xff0c;通用人工智能。 如果对“最终任务”进一步进行分类&#xff0c;又大致可以分为两大不同类型的任务&#xff1a;自然语言理解类任务和自然语言生成类任务。如果…

YOLOv6: 面向工业应用的单阶段目标检测框架

论文地址&#xff1a;https://arxiv.org/pdf/2209.02976 代码地址&#xff1a;https://github.com/meituan/YOLOv6 多年来&#xff0c;YOLO 系列一直是高效目标检测的行业标准。 YOLO 社区蓬勃发展&#xff0c;丰富了其在众多硬件平台和丰富场景中的使用。在这份技术报告力求…

云原生Docker搭建chemex资产管理系统

这篇文章主要讲解如何使用Ubuntu系统安装Docker应用并且搭建Chemex资产管理系统 Chemex数据是存在数据库的&#xff0c;为了方便备份以及管理容器。可利用外部的数据库或者Docker搭建一个数据库出来。我这里就在Docker容器中创建一个Mysql数据库供Chemex资产管理系统使用。 一…

QQ浏览器是如何提升搜索相关性的?

导言 | 搜索相关性主要指衡量Query和Doc的匹配程度&#xff0c;是信息检索的核心基础任务之一&#xff0c;也是商业搜索引擎的体验优劣最朴素的评价维度之一。本文作者刘杰主要介绍QQ浏览器搜索相关性团队在相关性系统及算法方面的实践经历。值得一提的是&#xff0c;本文会特别…

数组常用方法总结 (2) :sort / join / reverse / concat

sort 排序后会改变原有数组。简单数组和对象数组都可以进行排序。默认升序排序。 <template><div class"myBlock"><div class"tableBlock"><div class"title">{{ newObject ? "操作后的数组" : "操作…

NEW | GOT Online支持多模式采集、Mono分析支持IL2CPP打包

在性能优化时&#xff0c;你是否也遇到过这样的困扰&#xff1a;和性能相关的参数非常多&#xff0c;为什么能保障广度&#xff0c;就没法保障深度&#xff1f;这是因为数据的获取本身存在打点消耗&#xff0c;如果获取全量数据势必存在大量打点操作&#xff0c;导致收集的数据…

定时任务、cron表达式、springBoot整合定时任务和异步任务-58

一&#xff1a;定时任务 1.1 官网地址 http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html 1.2 cron表达式 Cron表达式是一个字符串&#xff0c;字符串以5或6个空格隔开&#xff0c;分为6或7个域&#xff0c;每一个域代表一个含义&am…

Spring 教程

Spring 教程Spring 概述三层架构Spring 的优良特性使用 Spring 框架的好处依赖注入&#xff08;DI&#xff09;Spring 框架具有以下几个特点&#xff1a;1&#xff09;方便解耦&#xff0c;简化开发2&#xff09;方便集成各种优秀框架3&#xff09;降低 Java EE API 的使用难度…

如何集成GATEWAY作为网关(含网关404和503的解决办法)

新建model包 gateway 引入依赖 <dependencies><!--引入gateWay--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--新版本cloud去掉了负…

ESP32设备驱动-SHT31温度湿度传感器驱动

SHT31温度湿度传感器驱动 文章目录 SHT31温度湿度传感器驱动1、SHT31介绍2、硬件准备3、软件准备4、驱动实现1、SHT31介绍 SHT31 是 Sensirion 的下一代温湿度传感器。 它建立在一个新的 CMOSens 传感器芯片之上,该芯片是 Sensirion 新湿度和温度平台的核心。 与其前身相比,…

[数据库迁移]-LVM逻辑卷管理

[数据库迁移]-LVM逻辑卷管理 森格 | 2023年1月 1、本文旨在记录数据库迁移过程&#xff08;下云至机房&#xff09;中&#xff0c;对新磁盘做逻辑卷管理的过程&#xff0c;并对Linux的文件系统和分区做了相关介绍&#xff0c;如有不对之处&#xff0c;敬请指正。 2、对Linux文…

【实践】百度信息流推荐系统质效合一的交付系统建设

省时查报告-专业、及时、全面的行研报告库省时查方案-专业、及时、全面的营销策划方案库【免费下载】2022年12月份热门报告盘点百度APP Feed流业务架构变迁思考和升级实践罗振宇2023年跨年演讲PPT原稿吴晓波2022年年终秀演讲PPT原稿《底层逻辑》高清配图‍基于深度学习的个性化…

数据结构:关于时间复杂度的例题计算

1、嵌套循环时间复杂度的计算 该程序&#xff0c;最上面的嵌套循环里&#xff0c;i每执行一次&#xff0c;j就执行N次&#xff0c;所以嵌套循环执行次数为N*N次&#xff1b;中间的k变量循环了2*N次&#xff1b;最后M变量循环10次。所以总共执行了 N*N2*N10 次&#xff01; 所以…

ERROR: Could not find a version that satisfies the requirement six>=1.9.0

问题分析 ERROR: Could not find a version that satisfies the requirement six>1.9.0 (from prompt-toolkit) (from versions: none) ERROR: No matching distribution found for six>1.9.0 出现这个问题的原因是python国内网络不稳定&#xff0c;用pip管理工具安装库…