日常编码时泛型的体现简直无处不在,但是对其一直没有系统的学习过,今天就来学习一下!老样子,先百度其他大牛已经写好的博客来看,对于这种经典的知识点,网上肯定已经有很多了。下面这篇就已经写得很详细了,可以说超级好理解!
Java泛型详解:<T>和Class<T>的使用。泛型类,泛型方法的详细使用实例
原博客已经写得超级详细了(虽然大佬也是转载其他博客哈哈哈),小渣就不重复赘述了。为了加深理解泛型的概念,先将大佬博客中的实例复现一波:
1. 首先看看怎么实现一个泛型接口
package com.wjb.generic;
/**
* 泛型接口实例
* @author Administrator
*
* @param <T>
*/
interface Info<T>{
public T getVar();
public void setVar(T var);
}
public class InfoImpl implements Info<String>{
private String var;
public InfoImpl(String var) {
this.setVar(var);
}
@Override
public String getVar() {
// TODO Auto-generated method stub
return this.var;
}
@Override
public void setVar(String var) {
this.var = var;
}
public static void main(String[] args) {
InfoImpl info = new InfoImpl("泛型接口");
System.out.println(info.getVar());
}
}
在这里我们将Info<String>中的泛型变量T定义填充为了String类型。所以在重写时setVar()和getVar()时,IDE会也我们直接生成String类型的重写函数。(所以要注意,如果是手动重新的话注意类型要相应改为String!)
2. 实现泛型类
package com.wjb.generic;
/**
* 泛型接口实例
* @author Administrator
*
* @param <T>
*/
interface Info<T>{
public T getVar();
public void setVar(T var);
}
public class InfoImpl<T> implements Info<T>{ //使用泛型类来继承泛型接口
private T var;
public InfoImpl(T var) {
this.setVar(var);
}
@Override
public T getVar() {
// TODO Auto-generated method stub
return this.var;
}
@Override
public void setVar(T var) {
this.var = var;
}
public static void main(String[] args) {
InfoImpl<String> info = new InfoImpl<String>("泛型类");
System.out.println(info.getVar());
}
}
值得注意的是,这样写乍看起来更繁琐了些。但是这样写的一大好处就是:使用泛型类来继承泛型接口的作用就是让用户来定义接口所使用的变量类型,而不是像方法一那样,在类中写死。
3.泛型方法
“泛型方法”就没上面那两个好理解了,所以这里要大概讲解一下。泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型。 说明一下,定义泛型方法时,必须在返回值前边加一个<T>,来声明这是一个泛型方法。持有一个泛型T,然后才可以用泛型T作为方法的返回值(这里注意体会一下上面代码中getVar()方法的返回值也是T)。
package com.wjb.generic;
/**
* 泛型方法
* @author Administrator
*
*/
public class StaticFans {
//定义一个静态泛型方法
public static <T> T staticMethod(T a) {
System.out.println("StaticMethod: "+a.toString());
return a;
}
//定义一个常规泛型方法
public <T> void otherMethod(T a) {
System.out.println("OtherMethod: "+a.toString());
}
public static void main(String[] args) {
StaticFans.staticMethod("静态泛型方法1");//使用方法1
StaticFans.<String>staticMethod("静态泛型方法2");//使用方法2
StaticFans sf = new StaticFans();
sf.otherMethod("常规泛型方法1");//使用方法1
sf.<String>otherMethod("常规泛型方法2");//使用方法2
}
}
泛型方法只要记得在返回值前加个<T>就行了,对于代码中的两种使用方法,方法1是隐式的参数传递,需要编译器帮我们识别传递的参数类型,尽量不要使用这种隐式的传递方式,代码不利于阅读和维护。因为从外观根本看不出来你调用的是一个泛型函数。方法2与方法1不同的地方在于,在调用方法前加了一个<String>来指定传给<T>的值,如果加了这个<String>来指定参数的类型的话,那StaticMethod()函数里所有用到的T类型也就是强制指定了是String类型。这是我们建议使用的方式。
那泛型方法存在的意义是什么呢: 因为泛型类要在实例化的时候就指明类型,如果想换一种类型,不得不重新new一次,可能不够灵活;而泛型方法可以在调用的时候指明类型,更加灵活。因此,当方法的参数类型为泛型时,就必须将方法定义为泛型方法。
4. 泛型数组
package com.wjb.generic;
/**
* 泛型数组
* @author Administrator
*
*/
public class Funs {
public static <T> T[] fun(T...arg) {// 接收可变长参数
return arg; //返回可变数组
}
public static void main(String[] args) {
Integer[] i = {1,2,3,4,5}; //这里不能用int类型数组,如果用int类型
Integer[] i2 = fun(i); //这里就会报错,因为T一定是派生于Object类的
}
}