More
More
文章目录
  1. Demo 1
  2. Demo 2
  3. Demo 3
  4. Demo 4
  5. 说点什么

是你眼中的泛型吗?

《? extends T与? super T》之后,我们再聊聊泛型。

Demo 1

1

1
2
3
public interface Generator {
<T> T next();
}

第一种解决方法,在方法返回类型前加“”使其成为一个泛型方法。

1
2
3
public interface Generator<T> {
T next();
}

第二种解决方法,在接口名后加“”使其成为一个泛型接口。

泛型类/接口在使用前,必须先指名参数类型,其中除了泛型方法外的泛型参数都将是所指定的类型。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 泛型接口与其子类
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

2

即静态方法无法访问泛型类上定义的泛型,此时采用泛型方法可解决。

1
2
3
4
5
6
// 正确做法
public class StaticGenerator {
public static <T> T rebey(T t) {
return null;
}
}

Demo 3

在《深入理解Java虚拟机 JVM高级特性与最佳实践(高清完整版)》P271 介绍了“当泛型遇见重载”的例子。得出的结论是:

两个方法如果有相同的名称和特征签名,但返回值不同,那他们也是可以合法地共存于一个Class文件中的。

1
2
3
4
5
6
7
public String url(String s) {
return "rebey.cn";
}
public int url(String s) {
return 0;
}

然而以上代码是无法编译通过的。因为此书出版时还未发布JDK7,因此其实只有JDK1.6及以下才能编译通过。随着时间的推移,原来错的可能所以还是按我们原来的理解来解读重载就好了。同名方法参数个数、顺序、类型不同,与返回值类型无关。

Demo 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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) in the type Utilities is not applicable for the arguments (HashSet)”。由于Utilities.create方法未指定具体类型,默认转为Object,所以Utilities.print此时无法接收其作为String类型的参数。而在Java8版本的增加了类型推断(type argument inference),能够根据赋值符号左边值类型自动推断出右边。

此外,通过显示指定参数类型也能够解决上述问题:

1
2
3
4
5
public class ResultGerneric {
public static void main(String[] args) {
Utilities.print(Utilities.<String>create(10));//点操作符与方法名之间
}
}

在《Think In Java》4th中泛型章节也提到了相似的例子(P363)。

说点什么

通过几个泛型的例子,我们看到:随着时间的推移,对的可能错,错的亦能对。

这不是很有趣的一件事吗?

待续…


更多有意思的内容,欢迎访问笔者小站: rebey.cn

打赏
手机扫一扫,支持CHE~