• 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

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

  • 相关阅读:
    Delphi播放铃声
    小技巧
    Delphi线程中使用waitfor返回值
    window安装、启动consul
    kali2020-bash: openvas-setup:未找到命令 ,解决办法
    zookeeper 客户端
    redis 集群
    activeMQ
    Shiro
    Eclipse Java注释模板设置详解
  • 原文地址:https://www.cnblogs.com/hangxin1940/p/2042240.html
Copyright © 2020-2023  润新知