首页 > 编程语言 >[JAVA] Java泛型实践

[JAVA] Java泛型实践

时间:2024-01-14 20:33:53浏览次数:54  
标签:JAVA 类型 参数 泛型 Java 实参 方法 public

Java泛型实践

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

特性

泛型只在编译阶段有效。看下面的代码:

List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();

Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();

if(classStringArrayList.equals(classIntegerArrayList)){
    Log.d("泛型测试","类型相同");
}

输出结果:D/泛型测试: 类型相同。

通过上面的例子可以证明,在编译之后程序会采取去泛型化的措施。也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。

对此总结成一句话:泛型类型在逻辑上可以看成是多个不同的类型,实际上都是相同的基本类型。

泛型的使用

泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法

泛型类

泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map。
一个最普通的泛型类:

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
    //key这个成员变量的类型为T,T的类型由外部指定
    private T key;

    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }

    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}

注意:
泛型的类型参数只能是类类型,不能是简单类型。

泛型接口

泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中,可以看一个例子:

//定义一个泛型接口
public interface Generator<T> {
    public T next();
}

class FruitGenerator<T> implements Generator<T>{
    @Override
    public T next() {
        return null;
    }
}
泛型通配符

类型通配符一般是使用?代替具体的类型实参,注意了,此处’?’是类型实参,而不是类型形参; 再直白点的意思就是,此处的?和Number、String、Integer一样都是一种实际的类型,可以把?看成所有类型的父类。是一种真实的类型。

可以解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。

泛型方法

在java中,泛型类的定义非常简单,但是泛型方法就比较复杂了。尤其是我们见到的大多数泛型类中的成员方法也都使用了泛型,有的甚至泛型类中也包含着泛型方法,这样在初学者中非常容易将泛型方法理解错了。
泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。

/**
 * 泛型方法的基本介绍
 * @param tClass 传入的泛型实参
 * @return T 返回值为T类型
 * 说明:
 *     1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
 *     2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
 *     3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
 *     4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
 */
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}

注意,在泛型类中,静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。
即:如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法 。

泛型上下边界

在使用泛型的时候,我们还可以为传入的泛型类型实参进行上下边界的限制,如:类型实参只准传入某种类型的父类或某种类型的子类。为泛型添加上边界,即传入的类型实参必须是指定类型的子类型

public class ShowInfo {
    // 用在方法上,只能接收 Number 及其子类
    public static void showInfo(Info<? extends Number> t) {
        System.out.print(t);
    }


    // 只接受 String 的父类
    public static void showInfo(Info<? super String> t) {
        System.out.println(t);
    }
}

类型擦除

泛型是提供给 javac 编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的 java 程序后,生成的 class 文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为 “擦除”。

以下是泛型的一些使用规范
1、不能实例化泛型类
2、静态变量或方法不能引用泛型类型变量,但是静态泛型方法是可以的
3、基本类型无法作为泛型类型
4、无法使用 instanceof 关键字或 == 判断泛型类的类型
5、泛型类的原生类型与所传递的泛型无关,无论传递什么类型,原生类是一样的
6、泛型数组可以声明但无法实例化
7、泛型类不能继承 Exception 或者 Throwable
8、不能捕获泛型类型限定的异常但可以将泛型限定的异常抛出

参考:
使用泛型的正确姿势
java 泛型详解

标签:JAVA,类型,参数,泛型,Java,实参,方法,public
From: https://www.cnblogs.com/hellojamest/p/17964145

相关文章

  • java于C配合
       虽然没有完成全部过程,最后卡在调用时报错,但还是记录下过程:1、创建java类,声明native方法packagecom.example.gpumonitor;publicclassGPUMonitor{static{System.loadLibrary("gpumonitor");//加载对应平台的动态链接库}publicnativeS......
  • java后端设置Cookie和响应Cookie
    @Slf4j@RestController@CrossOriginpublicclassLoginController{@GetMapping("/c1")publicResultcookie1(HttpServletResponseresponse){response.addCookie(newCookie("Login_user","zwj"));returnnew......
  • 【JAVA基础】Java项目开发工具之Maven
    JAVA开发工具IDE有哪些?eclipce、idea、vscode等等IDEA比Eclipse更强大和高效。IDEA提供了更好的代码补全和重构功能,更好的代码导航和搜索功能,以及更好的支持多模块项目和多语言开发等。构建项目工具构建项目工具有哪些?Maven、Gradle、Ant等Maven管理和构建项目以及维护......
  • SparkSQL in Java
    参考地址:StartingPoint:SparkSession1.新建Maven项目,POM引入依赖<dependencies><dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.13</artifactId><version&......
  • Java小细节之循环标号
    importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args){Scannerin=newScanner(System.in);intn=in.nextInt();out:for(inti=0;i<=n;i++){for(intj=0;j<=n/2;j++){for(intz=0;z<=n/5;z++){if(i+j......
  • 第一章:Java语言概述
    1.注释注释的类型:单行注释多行注释文档注释注释的作用:提高了程序的可阅读性用于调试程序的重要方法2.Java核心机制:JVM优点:跨平台性面向对象性健壮性安全性高简单性高性能缺点:语法过于复杂严谨一般适用于大型网站开发,维护成本高并非适用于所有领域2......
  • 开始学习Java - Day1
    学习Java目标掌握一门编程语言可以看懂代码,具备编程能力。WhyJava(vspython)相比较Python,更原生态,更灵活。(Python只是上手简单,仅此而已)Java封装好了,调用是一样的学完Java,再学习其他语言,会更快一些。如PHP,Python具体解决问题,底层更多的是看算法学习方法写代码......
  • 详解Java之Spring框架中事务管理的艺术
    第1章:引言大家好,我是小黑,咱们今天聊聊Spring框架中的事务管理。不管是开发小型应用还是大型企业级应用,事务管理都是个不可避免的话题。那么,为什么事务管理这么重要呢?假设在银行系统中转账时,钱从A账户扣了,但没到B账户,这种情况就是事务管理处理不当的后果。显然,我们需要一种机制来......
  • JavaImprove--Lesson06--正则表达式
    一.正则表达式的入门正则表达式是一些特定支付组成的,代表一个规则,简化代码,以字符的形式体现规则正则表达式,又称规则表达式,(RegularExpression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a到z之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。......
  • 大型JAVAEE医疗 项目介绍
    一项目介绍1简介云医疗项目属于微医云医疗技术部组建的项目,目前微医全科已开业八家,专注于为个人、家庭和企业提供预防、诊断、治疗、康复,高端体检等一站式的健康维护和医疗服务,打造中国医疗界的"星巴克",未来,微医全科高品质的健康医疗服务基地将继续在全国各地开枝散叶。云医疗......