1
public
class
Test {
2
3 // 泛型方法
4 public < T > void printClass(T a){
5 System.out.println(a.getClass());
6 }
7
8 public static void main(String[] args){
9
10 Test t = new Test();
11 t.printClass(t);
12 }
13 }
2
3 // 泛型方法
4 public < T > void printClass(T a){
5 System.out.println(a.getClass());
6 }
7
8 public static void main(String[] args){
9
10 Test t = new Test();
11 t.printClass(t);
12 }
13 }
输出:
class
Test
泛型方法中,<T>在返回值的定义前面,如果有返回值,返回值也可以是<T>,就可以是这样:
//
泛型方法,它什么也没干
public < T > T printClass(T a){
return a;
}
public < T > T printClass(T a){
return a;
}
可以这样理解:<>告诉编译器,这里里面的东西到时候给我替换了,于是,调用这个方法时,传入了某个类型a,则这些代码中的T都被临时变为a的类型了。
当然,<>中可以随便写
1
//
<> 里面可以随便写
2 public < X > void printClass(X a){
3 System.out.println(a.getClass());
4 }
5
6 public < a > void printClass(a a){
7 System.out.println(a.getClass());
8 }
9
10 public < Xa > void printClass(Xa a){
11 System.out.println(a.getClass());
12 }
2 public < X > void printClass(X a){
3 System.out.println(a.getClass());
4 }
5
6 public < a > void printClass(a a){
7 System.out.println(a.getClass());
8 }
9
10 public < Xa > void printClass(Xa a){
11 System.out.println(a.getClass());
12 }
以上代码都可以编译通过的。
下面复杂一点,泛型边界控制:
1
public
class
Test {
2
3 // 泛型方法
4 public < T extends Test > void printClass(T a){
5 System.out.println(a.getClass());
6 }
7
8 public class Gen {
9
10 }
11
12 public static void main(String[] args){
13
14 Test t = new Test();
15 Gen g = t. new Gen();
16 t.printClass(g);
17 }
18 }
2
3 // 泛型方法
4 public < T extends Test > void printClass(T a){
5 System.out.println(a.getClass());
6 }
7
8 public class Gen {
9
10 }
11
12 public static void main(String[] args){
13
14 Test t = new Test();
15 Gen g = t. new Gen();
16 t.printClass(g);
17 }
18 }
输出:
Exception in thread
"
main
"
java.lang.Error: 无法解析的编译问题:
边界不匹配:类型 Test 的通用方法 printClass(T)不适用于参数(Test.Gen)。推断类型 Test.Gen 并不是有界参数 < T 到 Test > 的有效替代项。
at Test.main(Test.java: 17 )
边界不匹配:类型 Test 的通用方法 printClass(T)不适用于参数(Test.Gen)。推断类型 Test.Gen 并不是有界参数 < T 到 Test > 的有效替代项。
at Test.main(Test.java: 17 )
上面的 <T extends Test> ,要求这个泛型参数必须是继承于Test或者实现了Test接口,把class gen改写为 class gen extends Test即可以编译通过运行。
再复杂一点,
1
public
class
Test {
2
3 // 泛型方法,要求参数必须是继承了泛型类Gen的对象,而泛型类Gen的泛型可以定义为任意
4 public < T extends Gen <?>> void printClass(T a){
5 System.out.println(a.getClass());
6 }
7
8 public class Gen < T > {
9
10 }
11
12 // 继承了泛型类Gen,并定义泛型类的类型参数是String
13 public class Gen1 extends Gen < String > {
14
15 }
16 // 继承了泛型类Gen,并定义泛型类的类型参数是Gen1
17 public class Gen2 extends Gen < Gen1 > {
18
19 }
20
21 public static void main(String[] args){
22
23 Test t = new Test();
24 Gen1 g1 = t. new Gen1();
25 t.printClass(g1);
26 Gen2 g2 = t. new Gen2();
27 t.printClass(g2);
28
29 }
30 }
2
3 // 泛型方法,要求参数必须是继承了泛型类Gen的对象,而泛型类Gen的泛型可以定义为任意
4 public < T extends Gen <?>> void printClass(T a){
5 System.out.println(a.getClass());
6 }
7
8 public class Gen < T > {
9
10 }
11
12 // 继承了泛型类Gen,并定义泛型类的类型参数是String
13 public class Gen1 extends Gen < String > {
14
15 }
16 // 继承了泛型类Gen,并定义泛型类的类型参数是Gen1
17 public class Gen2 extends Gen < Gen1 > {
18
19 }
20
21 public static void main(String[] args){
22
23 Test t = new Test();
24 Gen1 g1 = t. new Gen1();
25 t.printClass(g1);
26 Gen2 g2 = t. new Gen2();
27 t.printClass(g2);
28
29 }
30 }
输出:
class
Test$Gen1
class Test$Gen2
class Test$Gen2
到这里为止,所有的泛型都只运用到了方法的传入参数,那么对于方法的返回值怎么泛型呢:
1
public
class
Test {
2
3 // 泛型方法,传入参数a为任意类型,返回值为传入值的类型
4 public static < T > T getA(T a){
5 return a;
6 }
7
8 // 泛型方法,传入参数a为整形,返回值为传入值的类型
9 @SuppressWarnings( " unchecked " )
10 public static < T > T getB(String a){
11 return (T)a;
12 }
13
14 // 返回值为String ,参数a的类型为任意
15 public static < T > String getC(T a){
16 return a.toString();
17 }
18
19
20 public static void main(String[] args){
21 int a = 1 ;
22 int b = getA(a);
23 System.out.println(b);
24 String s1 = " test " ;
25 String s = getA(s1);
26 System.out.println(s);
27
28 s = getB(s);
29 System.out.println(s);
30
31 s = getC(a);
32 System.out.println(s);
33 }
34 }
2
3 // 泛型方法,传入参数a为任意类型,返回值为传入值的类型
4 public static < T > T getA(T a){
5 return a;
6 }
7
8 // 泛型方法,传入参数a为整形,返回值为传入值的类型
9 @SuppressWarnings( " unchecked " )
10 public static < T > T getB(String a){
11 return (T)a;
12 }
13
14 // 返回值为String ,参数a的类型为任意
15 public static < T > String getC(T a){
16 return a.toString();
17 }
18
19
20 public static void main(String[] args){
21 int a = 1 ;
22 int b = getA(a);
23 System.out.println(b);
24 String s1 = " test " ;
25 String s = getA(s1);
26 System.out.println(s);
27
28 s = getB(s);
29 System.out.println(s);
30
31 s = getC(a);
32 System.out.println(s);
33 }
34 }
输出:
1
test
test
1
test
test
1
泛型的使用,很常见的比如容器,看看下面的示例,就知道自己该如何定义泛型了:
1
public
class
Test {
2
3 // 这是个泛型接口,定义了一个泛型方法
4 public interface Eat < T > {
5 public void doEat(T t);
6
7 }
8
9
10 // 实现了Eat接口,使Eat接口的泛型类型为Shit这个内部类
11 public class Dog implements Eat < Dog.Shit > {
12
13 public Dog(){
14 System.out.println( " 这是狗 " );
15 // 这里只是掩饰,Dog自己并不是自产自销的家伙
16 Shit s = new Shit();
17 this .doEat(s);
18 }
19
20
21 // 内部类
22 public class Shit{
23 public Shit(){
24 System.out.println( " 这是一坨 " );
25 }
26
27 }
28
29
30 @Override
31 public void doEat(Shit t) {
32 // TODO Auto-generated method stub
33 System.out.println( " 狗吃了一坨 " );
34 }
35
36
37 }
38
39 public class Bull implements Eat < Bull.Grass > {
40
41 public Bull(){
42 System.out.println( " 这是Bull " );
43 Grass g = new Grass();
44 this .doEat(g);
45 }
46
47 // 内部类
48 public class Grass {
49 public Grass(){
50 System.out.println( " 这是Grass " );
51 }
52 }
53
54 @Override
55 public void doEat(Grass t) {
56 // TODO Auto-generated method stub
57 System.out.println( " Bull吃了Grass " );
58
59 }
60
61 }
62
63
64 public static void main(String[] args){
65 Test t = new Test();
66 Dog d = t. new Dog();
67 Bull b = t. new Bull();
68 }
69 }
2
3 // 这是个泛型接口,定义了一个泛型方法
4 public interface Eat < T > {
5 public void doEat(T t);
6
7 }
8
9
10 // 实现了Eat接口,使Eat接口的泛型类型为Shit这个内部类
11 public class Dog implements Eat < Dog.Shit > {
12
13 public Dog(){
14 System.out.println( " 这是狗 " );
15 // 这里只是掩饰,Dog自己并不是自产自销的家伙
16 Shit s = new Shit();
17 this .doEat(s);
18 }
19
20
21 // 内部类
22 public class Shit{
23 public Shit(){
24 System.out.println( " 这是一坨 " );
25 }
26
27 }
28
29
30 @Override
31 public void doEat(Shit t) {
32 // TODO Auto-generated method stub
33 System.out.println( " 狗吃了一坨 " );
34 }
35
36
37 }
38
39 public class Bull implements Eat < Bull.Grass > {
40
41 public Bull(){
42 System.out.println( " 这是Bull " );
43 Grass g = new Grass();
44 this .doEat(g);
45 }
46
47 // 内部类
48 public class Grass {
49 public Grass(){
50 System.out.println( " 这是Grass " );
51 }
52 }
53
54 @Override
55 public void doEat(Grass t) {
56 // TODO Auto-generated method stub
57 System.out.println( " Bull吃了Grass " );
58
59 }
60
61 }
62
63
64 public static void main(String[] args){
65 Test t = new Test();
66 Dog d = t. new Dog();
67 Bull b = t. new Bull();
68 }
69 }
输出:
这是狗
这是一坨
狗吃了一坨
这是Bull
这是Grass
Bull吃了Grass
这是一坨
狗吃了一坨
这是Bull
这是Grass
Bull吃了Grass
将泛型用到这样的接口中看来还是有很多好处的。