java参数传入泛型类型_java泛型的那些事

学习泛型的理由

首先明确为什么需要学习泛型?个人觉得至少有三个理由:1、使用泛型可以让你在声明类(或者创建方法)的时候不着急立即去指定它的类型,而是等到你实例化对象(或者方法调用)的时候才明确它的类型;2、避免通过使用Object类型来泛指java对象时,因类型强制向下转型时发生错误;3、可以毫无障碍的阅读Java相关源码。你经常遇到诸如Comparator super E> comparator和List extends Number>此类的代码,可能不太明白其中的含义,如果你学会了泛型,就毫无压力可以从容地面对那些代码了。

什么是泛型

泛型不光是在java,在很多面向对象语言及各种设计模式中有广泛的应用。所谓的泛型,其实就是把类型“参数化”。

一提到参数,大家最熟悉的就是定义方法时的形参和调用方法时的实参。那么类型“参数化”到底怎么理解呢?顾名思义,类型“参数化”就是将类型由原来的具体类型,变成参数化的“类型”,有点类似于方法中的变量参数,不过此时是类型定义成参数形式(你可以理解为类型形参),然后在使用时传入具体的类型(也就是类型实参)。为什么这样操作呢?因为它能让类型"参数化",也就是在不创建新的类型的情况下,通过泛型可以指定不同类型来控制形参具体限制的类型。

举一个你可能在实际编程过程中遇到过的例子:

  public static void main(String[] args){        List arrayList = Arrays.asList("hello","world",2018);        for(int i=0;i

猜猜运行结果,可以发现输出信息为:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

为什么会这样呢?我们知道ArrayList可以存放任意类型,在本例中仅仅是添加了两个String类型和一个Integer类型,只不过在获取对象的时候都变成String类型,由于Integer类型无法强制转为String类型,所以程序报出异常。问题就在于程序在编译时期并没有报错,而是在运行期报错了。我们希望有这么一个类型机制,就是只要程序在编译时期没有出现警告,那么运行时期就不会出现上述的ClassCastException异常,其实这就是Java泛型设计的原则。泛型其实就是将类型明确的工作推迟到创建对象或方法调用的时候才去明确的特殊类型。

为了解决上面那个问题,你需要将声明arrayList的代码修改一下,这样编译器在编译阶段就能发现类似的问题:

List arrayList = Arrays.asList("hello","world",2020);// Incompatible types.在编译阶段,编译器就会报错,无需运行

通过"泛型"这种语法糖,我们就能在编译阶段发现由于类型异常而导致的程序运行问题。

泛型只存在于编译阶段

泛型只存在于编译阶段,到了程序运行时刻就不存在了,这一现象称为“泛型擦除”。当你使用javac编译器将.java源文件转为字节码的.class文件时,泛型就不存在了。接下来通过一个例子来验证泛型只存在于编译阶段这一论据:

   public static void main(String[] args){        List stringList = new ArrayList<>();        List integerList = new ArrayList<>();        Class classStringList = stringList.getClass();        Class classIntegerList = integerList.getClass();        System.out.println(classStringList==classIntegerList);    }

猜猜运行结果,可以发现输出信息为:

true

这里我们使用了java反射机制,这样可以在运行时动态获取类的相关信息,这从侧面验证了论据的正确性。程序会编译后去除泛型,即Java中的泛型只在编译阶段有效。在编译过程正确检验泛型结果后,会将泛型的相关信息擦除,且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。泛型类型在逻辑上看似乎是多个不同的类型,但其实都是相同的类型。(注意泛型不能使用基本数据类型,必须是其对应的包装类。)

由于你在声明stringList对象的时候,使用泛型确定了它存储的元素类型为String,因此可以使用增强for循环来遍历stringList对象。

Java泛型中的标记符

在使用Java泛型前,了解其中一些标识符的含义,有助于提升开发效率。常用的标识符及含义如下:

 E - Element (集合使用,因集合中存放元素) T - Type(Java 类) K - Key(键) V - Value(值) N - Number(数值类型) ? -  表示不确定的java类型 S、U、V  - 2nd、3rd、4th types

你可能会有疑问,弄这么多标识符干嘛,直接使用万能的Object难道不香么?我们知道Object是所有类的基类(任何类如果没有指明其继承类,都默认继承于Object类),因此任何类的对象都可以设置Object的引用,只不过在使用的时候可能要类型强制转换。但是如果设置了泛型E、T等这些标识符,那么在实际使用之前类型就已经确定,因此不再需要类型强制转换。

泛型的使用

在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口和泛型方法。

泛型类

顾名思义,泛型类就是把泛型定义在类上,用户使用该类的时候,才把类型确定下来。用户确定什么类型,该类就代表什么类型,就不用担心在使用的时候需要类型强转及运行时转换异常等问题。泛型使用最多的就是各种容器类,如List、Set、Map等,通过泛型可以对一组类的操作提供对外相同的接口。请注意,在类上定义的泛型,在类的方法中同样也能使用(普通静态方法除外)。

泛型类的基本写法:

class 类名称 {  private 泛型标识 variable;   .....  }}

这么看你可能会感到困惑,这里结合一个实例来进行说明。新建一个泛型类:

package com.envy.parameter;public class ParameterClass {    private T type;    public T getType(){        return type;    }    public void setType(T type){        this.type = type;    }    //无参的构造方法    public ParameterClass(){    }    //有参的构造方法    public ParameterClass(T type){        this.type =type;    }}

接下来开始进行测试,前面说过用户需要哪种类型,就可以在实例化对象的时候指定哪种类型:

   public static void main(String[] args){        ParameterClass stringParameterClass = new ParameterClass<>("envy");        String result = stringParameterClass.getType();        System.out.println(result)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于Java泛型类参数传入,我们需要先了解一下Java泛型的基本概念。 Java中的泛型是一种参数化类的概念,即在定义类、接口或方法时,使用一个或多个类参数来表示其中的某些类,这些类参数在使用时再被具体化。通过使用泛型,可以使代码更加通用、安全和可读性更强。 Java中的泛型类参数可以用于类、接口和方法的定义中。在使用时,需要将具体的类参数传递给它们,以指定其中的泛型类。 下面以一个简单的例子来说明Java参数传入泛型类的用法。 ``` public class Box<T> { private T data; public Box(T data) { this.data = data; } public T getData() { return data; } public void setData(T data) { this.data = data; } } ``` 在这个例子中,我们定义了一个泛型类Box,其中的类参数T可以在类的定义中被指定。在Box类的构造函数和getData、setData方法中,我们使用了泛型类T来表示其中的某些类。 现在我们可以创建一个Box对象,并将一个具体的类参数传递给它,以指定其中的泛型类。例如: ``` Box<Integer> box = new Box<Integer>(new Integer(10)); ``` 在这个例子中,我们创建了一个Box对象,并将Integer类作为泛型类参数传递给它。这样一来,我们就可以在Box对象中存储和获取Integer类的数据了。 同样地,我们也可以创建其他类的Box对象,例如: ``` Box<String> box = new Box<String>("Hello World!"); Box<Double> box = new Box<Double>(new Double(3.14)); ``` 通过这种方式,我们可以方便地定义、使用和重用泛型类,从而使代码更加通用和灵活。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值