第二十一章 泛型(generic)

                         第二十一章 泛型(generic)
(1)引言
     泛型:是指参数化类型的能力。
     例如:有这样一个类:这是一个比较简单并且是很常用的带有泛型的方法。


     package com.lidd.generic;


     public class GenericTestSecond {

public <T>void one(T t){


}


      }


      下面是几个类,分别是一般类、抽象类、接口(接口也是特殊的类)。


      package com.lidd.generic;


      public class A {


      }


      package com.lidd.generic;


      public abstract class B {


      }


      package com.lidd.generic;


      public interface C {




     }


     接下里是主函数:
     package com.lidd.generic;
     public class MainTest {
public static void main(String[] args) {

GenericTestSecond o = new GenericTestSecond();
o.one(new C(){});   //C
o.one(new A());     // A
o.one(new B(){});   // B
o.one("bbbb");      // String
o.one(1);           // Integer

}


    }


    可以看到main方法中实例化了一个GenericTestSecond对象。方法one中传的参数类型可以是C、A、B、String、Integer等等,也就是说方法one中的泛型并不是指代某一种具体的类型
    而实在具体类型的基础上又进行了一层参数化。这就是定义中所说的参数化类型的能力。


   (2)泛型的优点。
        在jdk 1.5之前
package java,lang;
public interface Comparable{

public int compareTo(Object o);
}
在jdk1.5开始及其以后
package java.lang;
public interface Comparable<T>{
  public int compareTo(T t);
}




     1、泛型使得程序更加可靠。


     Comparable c = new Date();
     System.out.println(c.compareTo("red"));


     Comparable<Date> c = new Date();
     System.out.println(c.compareTo("red"));


     62 中一个时间和一个String字符串去做比较,但是在编译期不会有任何问题。但是在运行时会报错。
     65 中在编译的时候就会报错,因为Comparable中使用了泛型,并且在64行指定为Date类型。
     注意:
     泛型类型必须是应用类型,不能用像int double或char这样的基本类型来替换泛型类型。例如下面的语句是错误的:
     ArrayList<int> list = new ArrayList<int>();
     必须是ArrayList<Integer> list = new ArrayList<Integer>();
     2、无需类型转换。
     例如:
     ArrayList<String> strList = new ArrayList<String>();
     strList.add("one");
     strList.add("two");
     String str = strList.get(0);
     91 行不需要这样 String str = (String)strList.get(0);
     (3) 泛型的几种常见形式。
     1、泛型类(抽象类):
     public class GenericStack<E>{
private java.util.ArrayList<E> list = new java.util.ArrayList<E>();

public int getSize(){


return list.size();
}
public E peek(){
return list.get(getSize()-1);

}
public void push(E e){
list.add(e);

}
public E pop(){

E o = list.get(getSize()-1);
list.remove(getSize()-1);
return o;
}


public boolean isEmpty(){

return list.isEmpty();

}

  
     }
     或者是:


      public class GenericStack<E extends A>{
private java.util.ArrayList<E> list = new java.util.ArrayList<E>();

public int getSize(){


return list.size();
}
public E peek(){
return list.get(getSize()-1);

}
public void push(E e){
list.add(e);

}
public E pop(){

E o = list.get(getSize()-1);
list.remove(getSize()-1);
return o;
}


public boolean isEmpty(){

return list.isEmpty();

}

  
     }
    


     其中A为一个类。


      2、泛型接口:
      public interface Comparable<T>{
public int compareTo(T t);
      
      }
      或者是:
      public interface Comparable<T extends A>{
 public int compareTo(T t);
      
      }
   


      其中A为一个类。


      3、泛型方法:
      public class MyTest{
      
        // 注意<T>在方法的返回值类型之前
public <T>void one(T t){

}
      
      }


      或者:
      public class MyTest{
      
        // 注意<T>在方法的返回值类型之前
public <T extends A>void one(T t){

}
      
      }
  


      其中A为一个类。

     (4)通配泛型:
     以95行的类做前置准备。
     为啥需要通配泛型?
     pulic class demo1{
     
     public static void main(String[] args){
GenericStack<Integer> stack = new GenericStack<Integer>();
stack.add(1);
stack.add(2);
stack.add(3);
System.out.println("The max number is"+max(stack));
     
     }
    public static double max(GenericStack<Number> stack){
double max = stack.pop().doubleValue();
while(!stack.isEmpty()){
double value = stack.pop().doubleValue();
if(max < value){
max = value;
}
}
return max;
    
    }
     
  }


   其中208会出现编译错误,虽然Integer是Number的子类,但是GenericStack<Integer> 不是GenericStack<Number>的子类.
   这个时候通配泛型登场了。
   上面的代码稍加改动就可以消除208的编译错误。
   修改:211-221
   public static double max(GenericStack<? extends Number> stack){
double max = stack.pop().doubleValue();
while(!stack.isEmpty()){
double value = stack.pop().doubleValue();
if(max < value){
max = value;
}
}
return max;
    
    } 
    1、通配泛型的分类:
    第一类:?(非受限通配) 相当于 ?extends Object。
    例子:
    pulic class demo2{
     
     public static void main(String[] args){
GenericStack<Integer> stack = new GenericStack<Integer>();
stack.add(1);
stack.add(2);
stack.add(3);
print(stack);
     
     }
    public static double print(GenericStack<?> stack){


while(!stack.isEmpty()){
System.out.println(stack.pop()+"");
}
    
     }
     
   }
   注意253行-259行
   虽然GenericStack<?>相当于GenericStack<? extends Object>,但是不能是
     public static double print(GenericStack<Object> stack){


while(!stack.isEmpty()){
System.out.println(stack.pop()+"");
}
    
     } 


     否则的话250行编译不能通过。这是因为GenericStack<Integer> 不是GenericStack<Object>的子类。此处有体现的通配泛型的
     必要性。




    第二类:?extends T (受限通配) // 其中的T是某个泛型类型。
参考228-239行。




    第三类:?super T (下限通配)// 其中的T是某个泛型类型。


    public class demo3{

public static void main(String[] args){

GenericStack<String> stack1 = new GenericStack<String>();
GenericStack<Object> stack2 = new GenericStack<Object>();
stack1.add("java");
stack1.add("love");
stack2.add(1);
stack2.add(2);


add(stack1,stack2);

}
public static <T>void add(GenericSatck<T> stackTo,GenericStack<? super T> destStack){

while(!stackTo.isEmpty()){

destStack.push(stack1.pop());

}



}
    
    }


    296行如果使用<T>代替<? super T> ,那么293就会编译异常。


    (5)泛型消除:
    泛型是使用一种称为类型消除的方法来实现的。编译器使用泛型类型信息来编译代码,
    但是随后就会消除它。因此,泛型信息在运行时是不可用的。
    
//===========================================读java语言程序设计进阶篇笔记====================================================














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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值