在上一篇文章中,简要地对泛型的概念以及泛型类的使用进行了说明。除了在泛型类之外,泛型还可以在接口和方法中使用。
泛型接口
对于泛型接口,它的声明方式为: public interface 接口名 <泛型>{泛型定义的抽象方法}。这个声明方式和泛型类的声明方式基本一致。在定义了泛型接口后,在实现这个泛型接口的时候,要求我们指定泛型所代表的具体类型。比如在下面的这个演示代码中,定义了泛型抽象接口Igeneric,用泛型T来代表数据类型,因此在抽象方法中就可以使用泛型T来代表方法返回的的类型以及方法中需要传入的参数的类型。这里要注意泛型接口定义时的泛型与抽象泛型方法中使用的泛型的关系。
在泛型接口Igeneric的实现接口IgenericIme中,我们给定了泛型T的具体类型为String,这时如果通过实现类IgenericIme来创建对象,那么创建的对象中的数据类型就是String类。在这里就必须说到实例化对象的不同方式——通过接口实例化对象以及通过实现类实例化对象。在通过泛型接口的的实现类来实例化对象的时候,它的实例化方式与普通类的实例化没有区别,比如在下面演示代码中的igenericIme。但是当我们用泛型接口来实例化对象的时候就要特别注意,这种实例化方式要指定泛型所代之的类型并且还要指定特定的实现类,它的语法格式为:泛型接口名称<泛型指代的类型> 对象名称 = new 泛型接口的实现类名称();。就像演示代码中的对象igeneric以及对象igeneric1一样,并且要注意,尖括号中的泛型指代的类型要和接口的实现类中的保持一致,如果将对象igeneric中的泛型指代的名称输入为Integer,那么因为和后面的实现类中的泛型不同,所以程序无法通过编译。
package com.generic.demo;
/**
* 泛型接口
*/
public interface Igeneric<T> {
abstract T getName(T name);
}
package com.generic.demo;
/**
* 泛型接口的实现类
*/
public class IgenericIme implements Igeneric<String >{
@Override
public String getName(String name) {
return name;
}
}
package com.generic.demo;
public class IgenericIme1 implements Igeneric<Integer>{
@Override
public Integer getName(Integer name) {
return name;
}
}
package com.generic.demo;
public class TestIgeneric {
public static void main(String[] args) {
//通过实现类实例化
IgenericIme igenericIme = new IgenericIme();
String name1 = igenericIme.getName("尚学堂");
System.out.println(name1);
//通过接口实例化
Igeneric<String> igeneric = new IgenericIme();
String name2 = igeneric.getName("123");
System.out.println(name2);
Igeneric<Integer> igeneric1 = new IgenericIme1();
Integer name3 = igeneric1.getName(125);
System.out.println(name3);
}
}
泛型方法
静态泛型方法与非静态泛型方法
在之前说的泛型类以及泛型接口的部分能够发现,我们定义在类和接口上的泛型在它们的方法中仍然可以使用,但是有时我们需要的仅仅是在一个指定的方法上使用泛型而不需要在整个类和接口上使用泛型,因此泛型方法的概念就被提出了。泛型方法指的是将方法中的参数类型定义为泛型,以便在调用时接收不同的参数类型的现象。泛型方法可以分为非静态泛型方法和静态泛型方法。在定义泛型方法时,参数类型一般放到返回值前面,并且需要说明的是如果返回值类型不是void的情况下,返回值类型仍然定义为泛型。此外,调用泛型方法时不需要像泛型类和泛型接口那样指定泛型的类型,系统能够自动判断出泛型的类型,因此泛型方法的调用和普通方法没有区别。
非静态泛型方法的语法结构:
public <泛型表示符号> void 方法名(泛型表示符号 形式参数){}
public <泛型表示符号> 泛型表示符号 方法名(泛型表示符号 形式参数){}
静态泛型方法的语法够:
public static <泛型表示符号> void 方法名(泛型表示符号 形式参数){}
public static <泛型表示符号> 泛型表示符号 方法名(泛型表示符号 形式参数){}
对于静态泛型方法和非静态泛型方法,除了在定义的格式上存在的细微区别外,还要特别注意,静态泛型方法时无法访问类上定义的泛型的,也就是说如果我们定义了一个泛型类,在这个类中定义静态泛型方法时必须在static后面定义泛型,而不能直接使用类上定义的泛型。
泛型方法与可变参数
在泛型方法中和普通方法一样,传入的参数也可以是任意类型,包括像数组这种可变参数依旧可以传入方法,不过在泛型方法中用泛型定义可变参数的类型时要采用特殊的语法结构进行说明,它的具体语法格式为:
public (static) 泛型表示符号 泛型表示符号(void) 方法名 (泛型表示符号. . . 可变参数名称){}
在这个语法结构中要特别注意泛型表示符号与可变参数名称之间的符号. . . ,它是用来区分普通参数和可变参数的标志。
演示代码
package com.generic.demo;
public class MethodGeneric01 {
public <T> void setName(T name){
System.out.println(name);
}
public <T> T getName(T name){
return name;
}
public static <T> void setFlag(T flag){
System.out.println(flag);
}
public static <T> T getFlag(T flag){
return flag;
}
public <T> void method (T...args){
for(T t:args){
System.out.print(t+"\t");
}
System.out.println();
}
}
package com.generic.demo;
public class TestMethodGeneric01 {
public static void main(String[] args) {
MethodGeneric01 methodGeneric01 = new MethodGeneric01();
methodGeneric01.setName(123);
methodGeneric01.setName("jiuju");
MethodGeneric01 methodGeneric02 = new MethodGeneric01();
String name1 = methodGeneric02.getName("dede");
System.out.println(name1);
Integer name2 = methodGeneric02.getName(1234);
System.out.println(name2);
System.out.println("___________________");
//静态方法无法使用类上定义的泛型
MethodGeneric01.setFlag("liuyi");
Integer flag = MethodGeneric01.getFlag(123);
System.out.println(flag);
System.out.println("_____________________________");
//泛型与可变参数:数组
String[] arr1 = new String[]{"a","b","c"};
Integer[] arr2 = new Integer[]{1,2,3,4};
methodGeneric01.method(arr1);
methodGeneric01.method(arr2);
}
}