java 泛型多参数接口_Java之泛型参数化使用于类,接口,方法上知识

第一:参数类型用于类上案例:

编写泛型类GenericClass:

package com.test.cgb;

/**

*

* @Description: 定义泛型类,在类名后添加 对尖括号

* 并在尖括号中填写类型参数,参数可以有多个,多个参数使用逗号分隔

* T表示的是任意类型 type

* E表示的是元素的类型 element

* K表示的是key/value中的key

* V表示的是key/value中的value

* 通常类型参数我们都是使用大写。

* @author: caigb

* @createTime: 2020年2月29日

* @version:

*/

public class GenericClass {

public T value;

public T getValue() {

return value;

}

public void setValue(T value) {

this.value = value;

}

}

编写测试类:

public class GenericDemo {

public static void main(String[] args) {

// 参数类型为String

GenericClass genericClassOfString = new GenericClass<>();

genericClassOfString.setValue("用于类上的泛型");

String str = genericClassOfString.getValue();

System.out.println("str = " + str);

// 参数类型为Integer

GenericClass genericClassOfInteger = new GenericClass<>();

genericClassOfInteger.setValue(111);

Integer intNum = genericClassOfInteger.getValue();

System.out.println("intNum = " + intNum);

}

输出结果为:

str = 用于类上的泛型

intNum = 111

==================================================================================================================================

第二个:泛型接口:

定义接口如:

/**

*

* @Description: 用于接口上的泛型

* @author: caigb28355

* @createTime: 2020年2月29日

* @version:

*/

public interface GenericInterface {

void show(T value);

}

那么针对这个接口我们可以分别定义多种类型的实现类如:

IntegerShowGenericInterfaceImpl:

package com.test.cgb;

// 泛型类型参数为Integer

public class IntegerShowGenericInterfaceImpl implements GenericInterface{

@Override

public void show(Integer value) {

System.out.println(" 整数型 "+ value);

}

}

StringShowGenericInterfaceImpl:

package com.test.cgb;

// 泛型类型参数为String

public class StringShowGenericInterfaceImpl implements GenericInterface{

@Override

public void show(String value) {

System.out.println(" 字符串 "+ value);

}

}

编写测试类如下:

public class GenericDemo {

public static void main(String[] args) {

GenericInterface IntFace = new IntegerShowGenericInterfaceImpl(); // 向上转型

IntFace.show(200);

GenericInterface StringFace = new StringShowGenericInterfaceImpl(); // 向上转型

StringFace.show("字符串");

}

// 输出结果为:

整数型 200

字符串 字符串

==================================================================================================================================

第三:泛型方法,可以定义在泛型类中,也可以定义在普通类中。如果可以定义泛型方法,那就尽量定义泛型方法

泛型方法类定义如:

package com.test.cgb;

/**

*

* @Description: 泛型方法,可以定义在泛型类中,也可以定义在普通类中

* 定义泛型方法,在返回值前边,修饰符后边添加尖括号,并在其中填写类型参数

* 如果可以定义泛型方法,那就尽量定义泛型方法

* @author: caigb

* @createTime: 2020年2月29日

* @version:

*/

public class GenericFun {

public static void saveScore(T score) {

// 这是一个保存分数的方法,分数的类型可以是int,double,float...数值类型

// 我们对分数进行复杂操作......

System.out.println("score = " + score);

}

}

编写测试类如下:

public class GenericDemo {

public static void main(String[] args) {

GenericFun.saveScore(20.0);

GenericFun.saveScore(20);

}

打印结果如下:

score = 20.0

score = 20

但是上面这个例子有个不足的就是,命名这个方法是用来保存分数的,由于使用了static形式,所以可以接收所有类型的值比如字符串中文,那么就有点违背最初的想法了,如:

public static void main(String[] args) {

GenericFun.saveScore(20.0);

GenericFun.saveScore(20);

GenericFun.saveScore("保存分数的入参竟然是中文");

}

打印结果有:

score = 20.0

score = 20

score = 保存分数的入参竟然是中文

所以为了改进上面的缺陷,我们需要限制一下参数类型,于是要对引入类型参数做一下限定,这个限定可以是类,也可以是接口,而且可以同时限定多个,如果有多个,可以使用&符号连接,如果限定中既有类又有接口,那么类一定要写在前面或者如:

public class GenericFun {

// T extends Number表示T这个类型必须继承自Number类型,也就是一定要是Number类的字类,那么也就不能是String类型了

public static void saveScore(T score) {

// 这是一个保存分数的方法,分数的类型可以是int,double,float...数值类型

// 我们对分数进行复杂操作......

System.out.println("score = " + score);

}

// Double 和Float都是继承字Number类如:

//public final class Double extends Number implements Comparable {

// /**

// * A constant holding the positive infinity of type

// * {@code double}. It is equal to the value returned by

// * {@code Double.longBitsToDouble(0x7ff0000000000000L)}.

// */

// public static final double POSITIVE_INFINITY = 1.0 / 0.0;

//}

//public final class Float extends Number implements Comparable {

// /**

// * A constant holding the positive infinity of type

// * {@code float}. It is equal to the value returned by

// * {@code Float.intBitsToFloat(0x7f800000)}.

// */

// public static final float POSITIVE_INFINITY = 1.0f / 0.0f;

}

这样改造之后,在测试类中如果还是调用GenericFun.saveScore("保存分数的入参竟然是中文")方法的话就会报错如:

public class GenericDemo {

public static void main(String[] args) {

GenericFun.saveScore(20.0);

GenericFun.saveScore(20);

// 下面这句报错信息就是The method saveScore(T) in the type GenericFun is not applicable for the arguments (String)

GenericFun.saveScore("这里有中文");

}

===============================================================================================================================

泛型之类型擦出重要知识点扩展:下面让我们一起学习下泛型是如何擦出的,我们要知道,对于JVM来说,根本没有泛型这个概念,只有具体类型也就是说在运行期间根本就没有GenericClass,有的只是普通类和方法。JVM都会自动提供了一个相应的原始类型替换。在编译期间必要时会插入强制类型转换方法。

JVM在泛型编译时,做两件事:

1.去掉类名后的尖括号和尖括号的类型参数,剩下的名字就是对应的类名

2.对于类中使用了类型参数的变量的类型,如果没有限制类型的情况下,使用Object替换,如果有类型限定,使用限定的类型替换。下面我们一起看看:

首先我们在工作空间找到对应的class字节码文件路径,然后在该路径打开命令符窗口:

5893e2333b6f948a203f7c0db7114dac.png

最初我们的源文件GenericClass.java代码如:

public class GenericClass {

public T value;

public T getValue() {

return value;

}

public void setValue(T value) {

this.value = value;

}

}

第二步我们可以在cmd.exe窗口输入命令javap -help可以看到各种命令:

d2e235d0778c01db3936d47ad3965171.png

第三步我们可以输入输入命令javap -c -s GenericClass.class,我们可以看到Object类

98914c76543d1005c3c3675f5ede42ca.png

那么如果源代码是这样的呢?就是有类型限定的如:

public class GenericClass {

public T value;

public T getValue() {

return value;

}

public void setValue(T value) {

this.value = value;

}

}

那么就替换成Number了:

a575b872e0322e1c5c4a7c19f08e4ff2.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值