继《? extends T与? super T》之后,我们再聊聊泛型。
Demo 1
public interface Generator {
<T> T next();
}
第一种解决方法,在方法返回类型前加“<T>”使其成为一个泛型方法。
public interface Generator<T> {
T next();
}
第二种解决方法,在接口名后加“<T>”使其成为一个泛型接口。
泛型类/接口在使用前,必须先指名参数类型,其中除了泛型方法外的泛型参数都将是所指定的类型。如下:
// 泛型接口与其子类
public interface Generator<T> {
T next(T t);
void print(T t);
}
public class SubGenerator implements Generator<String>{
@Override
public String next(String t) {
// TODO Auto-generated method stub
return null;
}
@Override
public void print(String t) {
// TODO Auto-generated method stub
}
}
// 含有泛型方法的接口及其子类
public interface Generator<T> {
T next(T t);
<U> void print(U t);
}
public class SubGenerator implements Generator<String>{
@Override
public String next(String t) {
// TODO Auto-generated method stub
return null;
}
@Override
public <U> void print(U t) {
// TODO Auto-generated method stub
}
}
Demo 2
即静态方法无法访问泛型类上定义的泛型,此时采用泛型方法可解决。
// 正确做法
public class StaticGenerator {
public static <T> T rebey(T t) {
return null;
}
}
Demo 3
在《深入理解Java虚拟机 JVM高级特性与最佳实践(高清完整版)》P271 介绍了“当泛型遇见重载”的例子。得出的结论是:
两个方法如果有相同的名称和特征签名,但返回值不同,那他们也是可以合法地共存于一个Class文件中的。
public String url(String s) {
return "rebey.cn";
}
public int url(String s) {
return 0;
}
然而以上代码是无法编译通过的。因为此书出版时还未发布JDK7,因此其实只有JDK1.6及以下才能编译通过。随着时间的推移,原来错的可能所以还是按我们原来的理解来解读重载就好了。同名方法参数个数、顺序、类型不同,与返回值类型无关。
Demo 4
public class Utilities {
public static <T> HashSet<T> create(int size) {
return new HashSet<T>(size);
}
public static void print( HashSet<String> h) {
for (String s : h) System.out.println(s);
}
}
public class ResultGerneric {
public static void main(String[] args) {
Utilities.print(Utilities.create(10)); // error in Java 5,6,7 ; fine in Java 8
}
}
这是来自GenericsFAQ403中的一个例子。笔者在java7上测试了,如愿的看到了错误提示:“The method print(HashSet<String>) in the type Utilities is not applicable for the arguments (HashSet<Object>)”。由于Utilities.create方法未指定具体类型,默认转为Object,所以Utilities.print此时无法接收其作为String类型的参数。而在Java8版本的增加了类型推断(type argument inference),能够根据赋值符号左边值类型自动推断出右边。
此外,通过显示指定参数类型也能够解决上述问题:
public class ResultGerneric {
public static void main(String[] args) {
Utilities.print(Utilities.<String>create(10));//点操作符与方法名之间
}
}
在《Think In Java》4th中泛型章节也提到了相似的例子(P363)。
说点什么
通过几个泛型的例子,我们看到:随着时间的推移,对的可能错,错的亦能对。
这不是很有趣的一件事吗?
待续...
更多有意思的内容,欢迎访问笔者小站: rebey.cn
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。