java 之 泛型

 

 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  }

输出:

class  Test

 

泛型方法中,<T>在返回值的定义前面,如果有返回值,返回值也可以是<T>,就可以是这样:

// 泛型方法,它什么也没干
     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      }

以上代码都可以编译通过的。

 

下面复杂一点,泛型边界控制:

 

 1  public   class  Test {
 2      
 3       // 泛型方法
 4       public   < 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 )

 

上面的 <extends Test>  ,要求这个泛型参数必须是继承于Test或者实现了Test接口,把class gen改写为 class gen extends Test即可以编译通过运行。

 

再复杂一点,

 

 1  public   class  Test {
 2      
 3       // 泛型方法,要求参数必须是继承了泛型类Gen的对象,而泛型类Gen的泛型可以定义为任意
 4       public   < 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

 

到这里为止,所有的泛型都只运用到了方法的传入参数,那么对于方法的返回值怎么泛型呢:

 

 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  }

输出:

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  }

 

输出:

这是狗
这是一坨
狗吃了一坨
这是Bull
这是Grass
Bull吃了Grass

 

将泛型用到这样的接口中看来还是有很多好处的。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值