Java中泛型的理解(三)

来源:互联网 发布:hany是什么牌子 知乎 编辑:程序博客网 时间:2024/04/26 22:01
主要总结了泛型的一些应用
泛型接口、泛型方法、泛型数组、泛型的嵌套设置、标识接口
一.泛型接口
1.定义方式:
[访问权限]interface 接口名称<泛型标识>{}
interface Info<T>{    public T getVar();}interface Info<T>{public T getVar();}class InfoImpl implements Info{public String getVar(){return null;}}

以上的操作并不是子类实现泛型接口的最好操作,最好在实现的时候也指定其具体的泛型类型
2.泛型接口的两种实现方式
第一种:在子类的定义上也声明泛型类型
interface Info<T>{//在接口上定义泛型public T getVar();//定义抽象方法,抽象方法的返回值就是泛型类型}class InfoImpl<T> implements Info<T>{//定义泛型接口的子类private T var;public InfoImpl(T var){this.setVar(var);}public void setVar(T var){this.var = var;}public T getVar(){return this.var;}}public class GenericDemo10{public static void main(String[] args){InfoI<String> i = null;    //声明接口对象i = new InfoImpl<String>("Jack");//通过子类实例化对象System.out.println("内容:"+ i.getVar());}}

第二种:在实现接口的子类不使用泛型声明,则在实现接口的时候直接指定操作类型
interface Info<T>{//在接口上定义泛型public T getVar();//定义抽象方法,抽象方法的返回值就是泛型类型}class InfoImpl implements Info<String>{//定义泛型接口的子类private String var;public InfoImpl(String var){this.setVar(var);}public void setVar(String var){this.var = var;}public String getVar(){return this.var;}}public class GenericDemo11{public static void main(String[] args){Info i = null;i = new InfoImpl("Jack");//通过子类实例化对象System.out.println("内容:"+ i.getVar());}}

二.泛型方法
之前总结泛型方法,这里再给出泛型方法的两个操作
定义方法:
[访问权限]<泛型标识> 泛型标识 方法名称(泛型标识 参数名称){}
class Demo{public <T> T fun(T t){//可以接收任意类型的数据return t;}}public class GenericDemo01{public static void main(String[] args){Demo d = new Demo();String str = d.<String>fun("Jack");int i = d.<Integer>fun(30);System.out.println("内容:"+ str);System.out.println("内容:"+ i);}}

1.通过泛型方法返回类的实例
class Info<T extends Number>{  private T var;public void setVar(T var){this.var = var;}public T getVar(){return var;}}  public class GenericDemo03{public static void main(String[] args){  Info<Integer> i = fun(30);System.out.println(i.getVar());}  public static <T extends Number> Info<T> fun(T param){Info<T> temp = new Info<T>();temp.setVar(param);return temp;}}  

2.使用泛型方法统一参数类型
某些操作中,希望传递的泛型类型参数是同一种类型,比如加法,此时需要统一参数类型
class Info<T>{  private T var;public void setVar(T var){this.var = var;}public T getVar(){return var;}}  public class GenericDemo04{public static void main(String[] args){  Info<String> i1 = new Info<String>();Info<String> i2 = new Info<String>();i1.setVar("Jack");i2.setVar("Rose");add(i1,i2);}  public static <T> void add(Info<T> i1,Info<T> i2){System.out.println(i1.getVar()+" love "+i2.getVar());}}  

此时,若传入的参数不统一,编译时会产生错误

三.泛型数组
1.运行时类型查询只适用于原始类型
我们先看一下运行时类型查询的局限性
虚拟机中的对象总有一个特定的非泛型类型,因此,所有的类型查询只产生原始类型,每个泛型程序都会对应一个原始类型程序,由虚拟机翻译
例如:
class Info<T>{  private T var;public void setVar(T var){this.var = var;}public T getVar(){return var;}}  public class GenericDemo06{public static void main(String[] args){  Info<String> i = new Info<String>();if(i instanceof Info<String>){i.setVar("Jack");}}  }  

或者强制类型转换:
Info<String> i = (Info<String>) a;
无论何时使用instanceof或者涉及泛型类型的强制类型转换表达式都会看到编译器警告

2.不能创建参数化类型的数组

不能实例化参数化类型的数组,如:
Info<String>[] names = new Info<String>[10];    //ERROR
需要说明的是,这里这是不允许创建这些数组,而声明类型为Info<String>[]的变量是合法的,不过不能用new Info<String>[10]初始化

3.Varargs警告

Varargs:可变参数
向参数个数可变的方法传递一个泛型类型数组的实例:
public class GenericDemo05{public static void main(String[] args){Integer i[] = fun1(1,2,3,4,5,6);fun2(i);//调用时不用[]}public static <T> T[] fun1(T...arg){    //接收可变参数return arg;//返回泛型数组}public static <T> void fun2(T param[]){for(T t:param){System.out.print(t+"、");}}}  


这里,java虚拟机必须建立一个泛型类型的数组,与第二条相违背,但是在Java SE7中可以使用@SafeVarargs标注fun1()
public class GenericDemo05{public static void main(String[] args){Integer i[] = fun1(1,2,3,4,5,6);fun2(i);//调用时不用[]}@SafeVarargspublic static <T> T[] fun1(T...arg){return arg;//返回泛型数组}public static <T> void fun2(T param[]){for(T t:param){System.out.print(t+"、");}}}  

四.泛型嵌套
class Info<T,V>{private T var;private V value;public Info(T var,V value){this.setVar(var);this.setValue(value);}public void setVar(T var){this.var = var;}public void setValue(V value){this.value = value;}public T getVar(){return this.var;}public V getValue(){return this.value;}}class Demo<S>{private S info;publci Demo(S info){this.setInfo(info);}public void setInfo(S info){this.info = info;}public S getInfo(){return this.info;}}

现在希望Demo类中info属性是Info类的这种类型,但是Info类本身需要设置两个泛型
这时就用到泛型嵌套了 
class Info<T,V>{private T var;private V value;public Info(T var,V value){this.setVar(var);this.setValue(value);}public void setVar(T var){this.var = var;}public void setValue(V value){this.value = value;}public T getVar(){return this.var;}public V getValue(){return this.value;}}class Demo<S>{private S info;public Demo(S info){this.setInfo(info);}public void setInfo(S info){this.info = info;}public S getInfo(){return this.info;}}public class GenericDemo07{public static void main(String[] args){Demo<Info<String,Integer>> d = null;//将Info作为Demo类的泛型类型Info<String,Integer> i = null;//Info指定两个泛型类型i = new Info<String,Integer>("Jack",30);//实例化Info对象d = new Demo<Info<String,Integer>>(i);//在Demo类中设置Info类的对象System.out.println("内容一:"+d.getInfo().getVar());System.out.println("内容二:"+d.getInfo().getValue());}}

五.标识接口
标识接口是没有任何方法和属性的接口。标识接口不对实现他的类有任何语义上的要求,他仅仅表示实现它的类属于一个特定的类型。
java语言中标识接口有一些著名的应用,比如java.io.Serializable和java.rmi.Remote等接口便是标识接口

参考资料:
java核心技术卷一
java编程思想
李兴华java视频讲解
0 0