主要总结了泛型的一些应用
泛型接口、泛型方法、泛型数组、泛型的嵌套设置、标识接口
一.泛型接口
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); //调用时不用[]
}
@SafeVarargs
public 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视频讲解