泛型

在JDK 1.5 之前,编译器允许我们向容器插入不同类据的数据。例

/*
* 现在有一批 Apple
* 需求:对这一批产品核对 id 再出仓
 */
class Apple{
    private static long counter;
    private final long id = counter++;
    public long id(){ return id; }
}
class Orange{}

public static void main(String[] ages){
    List appleList = new ArrayList();
    appleList.add(new Apple);
    appleList.add(new Orange);
    appleList.add(new Apple);
    appleList.add(new Apple);
    for(int i = 0; i < appleList.size(); i++){
        (Apple)appleList.get(i).id();
    }
}

在 appleList 集合中我们不小心加入了 Orange 类型的元素,因为ArrayList存放的中Object类型,在对 appleList 集合做遍历时,通过get(index) 方法返回的元素是Object类型的引用,所以要强转为Apple类型,又对每个元素都去调用了Apple中的 id() 方法,但 Orange 这个元素没有 id() 这个方法,所以程序在遍历到这个元素时会报错

要想让 ArrayList 只保存 Apple 类型,可以声明 ArrayList<apple></apple> 尖括号里面放的是类型参数,它指定了这个容器可以存放的类型。参数可以有多个,但要看容器是否支持。

这就是泛型,可以在编译期防止将错误的类型存放到容器中。而且从容器中取出时也不用再做类型转换,因为容器知道存储的是什么类型,在调用get()时替我们执行了转型

public static void main(String[] ages){
    List appleList = new ArrayList();
    appleList.add(new Apple);
    //appleList.add(new Orange);//提示错误
    appleList.add(new Apple);
    appleList.add(new Apple);
    for(int i = 0; i < appleList.size(); i++){
        (Apple)appleList.get(i).id();
    }
}

还可以兼容向上转型,可以将Apple类型的子类型添加到被指定为Apple对象的容器中

public class Fuji extends Apple{}
public class Gala extends Apple{}

main:
List appleList = new ArrayList();
appleList.add(new Apple());
appleList.add(new Apple());
appleList.add(new Apple());
appleList.add(new Fuji());
appleList.add(new Gala());
for (int i = 0; i < appleList.size(); i++) {
            System.out.println(appleList.get(i));
}

/*
Apple@1b6d3586
Apple@4554617c
Apple@74a14482
Fuji@1540e19d
Gala@677327b6
*/

泛型类就是一个或多个类型变量的类。

自定义泛型类, 类型变量放在类名的后面,用<>尖括括起来。可以有多个

class Pair{
    private T data;

    public Pair(){this.data = null;}
    public Pair(T data){ this.data = data; }

    public T getData(){ return data; }
    public void setData(T data){ this.data = data; }
}

类型变量使用大写形式,一般使用 E 表示集合的元素类型;K和V分别表示关键字和值;T(U,S)表示任意类型

自定义泛型方法, 类型变量放在修饰符的后面,也是用<>尖括括起来。可以有多个

class ArrayAlg{
    public static  T getMiddle(T t){
        return t[t.length / 2];
    }
}

main:
String middle = ArrayAlg.getMiddle("John");

在调用泛型方法时,在方法名前的尖括号内放入具体的类型

在类中,如果定义了一个泛型对象,那么意义着它可以是任何类的对象。想它去调用指定的方法,但又不能确保这个泛型所属的类是否有这个方法时,可以将泛型限制为实现了有这个方法的接口的类,从而限定泛型类

public static  T getMiddle(T t){
        return t.apple();
}

限定后的代码:

public static  T getMiddle(T t){
        return t.apple();
}

如果在调用方法时,给定的泛型不是实现Apple类,那么会产生编译错误。

也可以有多个限定,限定类型以 & 隔开: <t extends apple & minnex></t>

泛型机制是在编译阶段起作用,只是给编译器参考,在运行阶段没用。虚拟机中没有泛型对象,泛型可以看作是一个类型的占位符

Original: https://www.cnblogs.com/hello12153-java/p/16301493.html
Author: hello_12153_98
Title: 泛型

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/570469/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 根据子类查询父类

    1.如果改子类有父类,则把父类加入子类的父ID中 private static List breadthParentFirst(List rootTree) { if (Colle…

    Java 2023年6月16日
    066
  • 开源框架是如何使用设计模式的-MyBatis缓存机制之装饰者模式

    写在前面 聊一聊MyBatis是如何使用装饰者模式的,顺便回顾下缓存的相关知识,可以看看右侧目录一览内容概述。 装饰者模式 这里就不聊它的概念了,总结下就是套娃。利用组合的方式将装…

    Java 2023年6月6日
    0112
  • 二叉树的基本知识

    二叉树的四种遍历方式 不要较真,其实也可以分为两种:广度优先(层级)和深度优先(前序、中序、后序) 基本概念不再赘述。 复杂度:设二叉树中元素数目为n。这四种遍历算法的空间复杂性均…

    Java 2023年6月8日
    092
  • Linux下用Docker部署接口安全的运行环境

    背景:MySQL 数据库运行在宿主机上(Linux) 需求:Redis、服务、页面分别运行在独立的docker中,并处于同一网络,容器内部重要目录要挂载在物理目录,保证数据安全 方…

    Java 2023年6月8日
    096
  • Redis之ziplist源码分析

    一、ziplist简介 从上一篇分析我们知道quicklist的底层存储使用了ziplist(压缩列表),由于压缩列表本身也有不少内容,所以重新开了一篇,在正式源码之前,还是先看下…

    Java 2023年6月6日
    094
  • 修改IntelliJ IDEA字体

    posted @2016-04-05 10:11 聊聊IT那些事 阅读(254 ) 评论() 编辑 Original: https://www.cnblogs.com/FCWORL…

    Java 2023年6月6日
    0102
  • 5个必知的高级SQL函数

    5个必知的高级SQL函数 SQL是关系数据库管理的标准语言,用于与数据库通信。它广泛用于存储、检索和操作数据库中存储的数据。SQL不区分大小写。用户可以访问存储在关系数据库管理系统…

    Java 2023年6月15日
    0128
  • Golang中变量与常量的声明

    一、局部变量的声明(4种方法) 1.声明一个变量,但不初始化值,使用默认值:var a int。 2.声明一个变量,初始化值:var a int = 100。 3.声明一个变量,初…

    Java 2023年6月13日
    080
  • The valid characters are defined in RFC 7230 and RFC 3986

    The valid characters are defined in RFC 7230 and RFC 3986 1.异常截图 2.原因说明 ​ 导致上述问题是因为tomcat自…

    Java 2023年6月8日
    0108
  • callable和runnable的区别

    Runnable接口源码 Callable接口源码 区别: 相同点: Original: https://www.cnblogs.com/zjulanjian/p/11132605…

    Java 2023年5月30日
    079
  • 22.线程自解锁

    代码结构比较复杂的情况下,手动加锁,解锁,可能会有所遗漏。 这种情况下,推荐使用自解锁(自解锁在构造的时候lock,在析构的时候unlock)(对象在超出作用域时会执行析构) 自解…

    Java 2023年5月29日
    078
  • Mybatis 懒加载使用及源码分析

    什么是懒加载?懒加载的意思就是在使用的时候才去加载,不使用不去加载,相反的就叫饥饿加载或者立即加载。懒加载在 Mybatis中一般是存在与联合查询的情况,比如查询一个对象的同时连带…

    Java 2023年6月14日
    084
  • 【JavaWeb-jQuery】笔记(2)— jQuery 函数精讲

    第一组函数: 1、val: 操作 DOM 数组中的对象的 value 属性 $(&#x9009;&#x62E9;&#x5668;).val();//&amp…

    Java 2023年6月8日
    090
  • junit结合spring-test里的MockMvc来测试SpringMvc接口方法

    如下是SpringMvc项目里的Controller 重点来了,junit结合spring-test里的MockMvc来测试上面的http接口 运行结果(支持debug调试,是不是…

    Java 2023年5月29日
    0161
  • Springboot优雅参数校验,统一响应,异常处理

    1.统一响应 (1)统一状态码首先定义一个状态码接口,所有状态码都需要实现它 public interface StatusCode { public int getCode();…

    Java 2023年6月8日
    075
  • 深入理解CAS思想之原子操作类详解

    前置知识(CAS部分) (1)什么是 CAS 1.CAS(Compare And Swap,比较并交换),通常指的是这样一种原子操作: 针对一个变量,首先比较它的内存值与某个期望值…

    Java 2023年6月16日
    071
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球