泛型 <T> 详解

引用。原地址:http://www.java3z.com/cwbwebhome/article/article5/tiger2.jsp

清单 1
// 一个简单的范型类.  
// 这里,T 是一个类型参数,当创建Gen类的对象时将被真实的类型取代. 
public class Gen< T> { 
  T ob; // 声明一个T类型的对象 
   

  Gen(T o) { 
    ob = o; 
  } 


  public T getob() { 
    return ob; 
  } 

  // 输出T的类型
public  void showType() { 
    System.out.println("Type of T is " + 
                       ob.getClass().getName()); 
  } 


// 示范这个范型类的用法
public class GenDemo { 
  public static void main(String args[]) { 
    // 声明一个类型参数为Integers的Gen对象  
    Gen< Integer> iOb;  

    // 创建一个Gen< Integer> 对象并分配其引用到iOb.  注意使用了自动装箱. 
    iOb = new Gen< Integer>(88); 

    // 显示类型 
    iOb.showType(); 

    // 获取在iOb对象内的值,注意不需要类型转换.
  
    int v = iOb.getob(); 
    System.out.println("value: " + v); 

    System.out.println(); 

    // 创建一个类型参数为String的Gen对象
    Gen< String> strOb = new Gen< String>("Generics Test"); 

   
    strOb.showType(); 

   
    String str = strOb.getob(); 
    System.out.println("value: " + str); 
  } 
}

清单2
// NonGen类没有使用范型, 与使用范型的Gen的等价 
class NonGen {  
  Object ob; // ob 现在是一个Object类型
    
  
  NonGen(Object o) {  
    ob = o;  
  }  
  
  // 返回类型为 Object. 
  Object getob() {  
    return ob;  
  }  

  // 显示ob的类型.  
  void showType() {  
    System.out.println("Type of ob is " +  
                       ob.getClass().getName());  
  }  
}  
  
// 示范这个类用使用.  
class NonGenDemo {  
  public static void main(String args[]) {  
    NonGen iOb;   
  
    
    // 自动装箱还会发生. 
    iOb = new NonGen(88);  
  
   
    iOb.showType(); 

    // 输出iOb的值,必须进行类型转换 
    int v = (Integer) iOb.getob();  
    System.out.println("value: " + v);  
  
    System.out.println();  
  

    // 创建另一个对象,存字符串. 
    NonGen strOb = new NonGen("Non-Generics Test");  
  
    strOb.showType(); 

    String str = (String) strOb.getob();  
    System.out.println("value: " + str);  

    // 下面这句编译能通过,因为没有语法错误 
    iOb = strOb; 
    v = (Integer) iOb.getob(); // 发生运行时错误! 
  }  
}

清单 3
//带两个类型参数的范型 
class TwoGen< T, V> { 
  T ob1; 
  V ob2; 
   

  TwoGen(T o1, V o2) { 
    ob1 = o1; 
    ob2 = o2; 
  } 

  // 显示T 和 V的类型. 
  void showTypes() { 
    System.out.println("Type of T is " + 
                       ob1.getClass().getName()); 

    System.out.println("Type of V is " + 
                       ob2.getClass().getName()); 
  } 

  T getob1() { 
    return ob1; 
  } 

  V getob2() { 
    return ob2; 
  } 


// 示范. 
class SimpGen { 
  public static void main(String args[]) { 

    TwoGen< Integer, String> tgObj =
      new TwoGen< Integer, String>(88, "Generics"); 

    tgObj.showTypes(); 

    // 获取并显示值. 
    int v = tgObj.getob1(); 
    System.out.println("value: " + v); 

    String str = tgObj.getob2(); 
    System.out.println("value: " + str); 
  } 
}

清单 4
// 尝试创建一个能计算数字平均值的泛型类
// 这个类包括一个错误! 
class Stats< T> {  
  T[] nums; // nums 是一个T类型的数组 
    
  
  Stats(T[] o) {  
    nums = o;  
  }  
  
  // 所有的情况下都返回double. 
  double average() {  
    double sum = 0.0; 

    for(int i=0; i < nums.length; i++)  
      sum += nums[i].doubleValue(); // 错误!!!,编译器无法知道你只使用数字类型创建Stats对象.

    return sum / nums.length; 
  }  
}

清单 5
// 这次使用有界类型的范型,声明一个上界,所有类型变量必须从超类派生. 
class Stats< T extends Number> {  
  T[] nums; // Number或它的子类型的数组 
    

  Stats(T[] o) {  
    nums = o;  
  }  
  
  double average() {  
    double sum = 0.0; 

    for(int i=0; i < nums.length; i++)  
      sum += nums[i].doubleValue(); 

    return sum / nums.length; 
  }  
}  
  
// 示范  
class BoundsDemo {  
  public static void main(String args[]) {  

    Integer inums[] = { 1, 2, 3, 4, 5 }; 
    Stats< Integer> iob = new Stats< Integer>(inums);   
    double v = iob.average(); 
    System.out.println("iob average is " + v); 

    Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 }; 
    Stats< Double> dob = new Stats< Double>(dnums);   
    double w = dob.average(); 
    System.out.println("dob average is " + w); 

    // 这不能编译,因为String不是Number的子类
    // String strs[] = { "1", "2", "3", "4", "5" }; 
    // Stats< String> strob = new Stats< String>(strs);   
  
    // double x = strob.average(); 
    // System.out.println("strob average is " + v); 

  }  
}

清单 6
// 使用通配符 
class Stats< T extends Number> {   
  T[] nums; 
     
  
  Stats(T[] o) {   
    nums = o;   
  }   
   
  double average() {   
    double sum = 0.0;  
  
    for(int i=0; i < nums.length; i++)   
      sum += nums[i].doubleValue();  
  
    return sum / nums.length;  
  } 

  // 确定两个包含数组的Stats对象是否有相同的平均值. 
  // 注意使用通配符
  boolean sameAvg(Stats< ?> ob) { 
    if(average() == ob.average())  
      return true; 

    return false; 
  } 
}   
   
// 示范. 
class WildcardDemo {   
  public static void main(String args[]) {   
    Integer inums[] = { 1, 2, 3, 4, 5 };  
    Stats< Integer> iob = new Stats< Integer>(inums);    
    double v = iob.average();  
    System.out.println("iob average is " + v);  
  
    Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };  
    Stats< Double> dob = new Stats< Double>(dnums);    
    double w = dob.average();  
    System.out.println("dob average is " + w);  
  
    Float fnums[] = { 1.0F, 2.0F, 3.0F, 4.0F, 5.0F };  
    Stats< Float> fob = new Stats< Float>(fnums);    
    double x = fob.average();  
    System.out.println("fob average is " + x);  
  
    // 看哪二个数组有相同的平均值. 
    System.out.print("Averages of iob and dob "); 
    if(iob.sameAvg(dob)) 
      System.out.println("are the same.");  
    else 
      System.out.println("differ.");  

    System.out.print("Averages of iob and fob "); 
    if(iob.sameAvg(fob)) 
      System.out.println("are the same.");  
    else 
      System.out.println("differ.");  
  }   
}

运行结果:

C:\java>java   WildcardDemo
iob average is 3.0
dob average is 3.3
fob average is 3.0
Averages of iob and dob differ.
Averages of iob and fob are the same.


listing 7
// 有界通配符. 

// 二维空间. 
class TwoD { 
  int x, y; 

  TwoD(int a, int b) { 
    x = a; 
    y = b; 
  } 


// 三维空间. 
class ThreeD extends TwoD { 
  int z; 
   
  ThreeD(int a, int b, int c) { 
    super(a, b); 
    z = c; 
  } 


// 四维空间. 
class FourD extends ThreeD { 
  int t; 

  FourD(int a, int b, int c, int d) { 
    super(a, b, c); 
    t = d;  
  } 


class Coords< T extends TwoD> { //有界范型
  T[] coords; 

  Coords(T[] o) { coords = o; } 


// 示范. 
class BoundedWildcard { 
  static void showXY(Coords< ?> c) { 
    System.out.println("X Y Coordinates:"); 
    for(int i=0; i < c.coords.length; i++) 
      System.out.println(c.coords[i].x + " " + 
                         c.coords[i].y); 
    System.out.println(); 
  } 

  static void showXYZ(Coords< ? extends ThreeD> c) { 
    System.out.println("X Y Z Coordinates:"); 
    for(int i=0; i < c.coords.length; i++) 
      System.out.println(c.coords[i].x + " " + 
                         c.coords[i].y + " " + 
                         c.coords[i].z); 
    System.out.println(); 
  } 

  static void showAll(Coords< ? extends FourD> c) { 
    System.out.println("X Y Z T Coordinates:"); 
    for(int i=0; i < c.coords.length; i++) 
      System.out.println(c.coords[i].x + " " + 
                         c.coords[i].y + " " + 
                         c.coords[i].z + " " + 
                         c.coords[i].t); 
    System.out.println(); 
  } 

  public static void main(String args[]) { 
    TwoD td[] = { 
      new TwoD(0, 0), 
      new TwoD(7, 9), 
      new TwoD(18, 4), 
      new TwoD(-1, -23) 
    }; 

    Coords< TwoD> tdlocs = new Coords< TwoD>(td);     

    System.out.println("Contents of tdlocs."); 
    showXY(tdlocs); // OK, is a TwoD 
//  showXYZ(tdlocs); // Error, not a ThreeD 
//  showAll(tdlocs); // Erorr, not a FourD 

    // 创建一些四维点
    FourD fd[] = { 
      new FourD(1, 2, 3, 4), 
      new FourD(6, 8, 14, 8), 
      new FourD(22, 9, 4, 9), 
      new FourD(3, -2, -23, 17) 
    }; 

    Coords< FourD> fdlocs = new Coords< FourD>(fd);     

    System.out.println("Contents of fdlocs."); 
    //这些都不会产生错误. 
    showXY(fdlocs);  
    showXYZ(fdlocs); 
    showAll(fdlocs); 
  } 
}

清单 8
// 示范简单的范型方法 
class GenMethDemo {  

  // 静态的范型方法,测试一个对象是否在一个数组中. 
  static < T, V extends T> boolean isIn(T x, V[] y) { 

    for(int i=0; i < y.length; i++) 
      if(x.equals(y[i])) return true; 

    return false; 
  } 

  public static void main(String args[]) {  

    // 对Integers使用isIn()方法. 
    Integer nums[] = { 1, 2, 3, 4, 5 }; 

    if(isIn(2, nums)) 
      System.out.println("2 is in nums"); 

    if(!isIn(7, nums)) 
      System.out.println("7 is not in nums"); 

    System.out.println(); 

    // 对Strings使用isIn()
    String strs[] = { "one", "two", "three", 
                      "four", "five" }; 

    if(isIn("two", strs)) 
      System.out.println("two is in strs"); 

    if(!isIn("seven", strs)) 
      System.out.println("seven is not in strs"); 

    // 不能编译,类型必须一致. 
    //    if(isIn("two", nums)) 
    //      System.out.println("two is in strs"); 
  }  
}

清单 9
// 泛型构造器. 
class GenCons { 
  private double val; 

  < T extends Number> GenCons(T arg) { 
    val = arg.doubleValue(); 
  } 

  void showval() { 
    System.out.println("val: " + val); 
  } 


class GenConsDemo { 
  public static void main(String args[]) { 

    GenCons test = new GenCons(100); 
    GenCons test2 = new GenCons(123.5F); 

    test.showval(); 
    test2.showval(); 
  } 
}
运行结果:
C:\java>java   GenConsDemo
val: 100.0
val: 123.5

清单 10
// 一个泛型接口的例子. 

// 来用返回某个对象集的最小或最大值. 
interface MinMax< T extends Comparable< T>> { 
  T min(); 
  T max(); 


//MyClass实现接口MinMax
class MyClass< T extends Comparable< T>> implements MinMax< T> { 
  T[] vals; 

  MyClass(T[] o) { vals = o; } 

  // 返回最小值. 
  public T min() { 
    T v = vals[0]; 

    for(int i=1; i < vals.length; i++) 
      if(vals[i].compareTo(v) < 0) v = vals[i]; 

    return v; 
  } 

  // 返回最大值. 
  public T max() { 
    T v = vals[0]; 

    for(int i=1; i < vals.length; i++) 
      if(vals[i].compareTo(v) > 0) v = vals[i]; 

    return v; 
  } 


class GenIFDemo { 
  public static void main(String args[]) { 
    Integer inums[] = {3, 6, 2, 8, 6 }; 
    Character chs[] = {'b', 'r', 'p', 'w' }; 

    MyClass< Integer> iob = new MyClass< Integer>(inums); 
    MyClass< Character> cob = new MyClass< Character>(chs); 

    System.out.println("Max value in inums: " + iob.max()); 
    System.out.println("Min value in inums: " + iob.min()); 

    System.out.println("Max value in chs: " + cob.max()); 
    System.out.println("Min value in chs: " + cob.min()); 
  } 
}

清单 11
// 示范使用原始类型. 一个泛型类在使用时可以不带类型参数,同时带来的是失去了类型安全.
class Gen< T> {  
  T ob; // 声明一个T类型的对象
    
  Gen(T o) {  
    ob = o;  
  }  
  
  T getob() {  
    return ob;  
  }  
}  
  
// 使用原始类型. 
class RawDemo {  
  public static void main(String args[]) {  

    Gen< Integer> iOb = new Gen< Integer>(88);  
   
    Gen< String> strOb = new Gen< String>("Generics Test");  
  
    // 创建一个使用原始类型参数的Gen
    Gen raw = new Gen(new Double(98.6)); 

    // 类型转换是必须的
    double d = (Double) raw.getob(); 
    System.out.println("value: " + d); 

    //int i = (Integer) raw.getob(); // 运行时错误 

    strOb = raw; // 可以通过编译 
    // String str = strOb.getob(); // 运行时错误  
     
    raw = iOb; // 可能编译 
    // d = (Double) raw.getob(); // 运行时错误 
  }  
}

清单 12
// 泛型类层次. 使用泛型超类
class Gen< T> {  
  T ob; 
    
  Gen(T o) {  
    ob = o;  
  }  
  
  // Return ob.  
  T getob() {  
    return ob;  
  }  
}  

// Gen的子类
class Gen2< T> extends Gen< T> { 
  Gen2(T o) { 
    super(o); 
  } 
}

清单 13
// 子类能增加自己的类型参数. 
class Gen< T> {  
  T ob; 
    
  Gen(T o) {  
    ob = o;  
  }  
  
  T getob() {  
    return ob;  
  }  
}  

class Gen2< T, V> extends Gen< T> { 
  V ob2; 

  Gen2(T o, V o2) { 
    super(o); 
    ob2 = o2; 
  } 

  V getob2() { 
    return ob2; 
  } 

  
// 创建一个Gen2类型的对象. 
class HierDemo {  
  public static void main(String args[]) {  
    
    Gen2< String, Integer> x = new Gen2< String, Integer>("Value is: ", 99);  

    System.out.print(x.getob()); 
    System.out.println(x.getob2()); 
  }  
}

清单 14
// 泛型子类 

class NonGen { 
  int num; 

  NonGen(int i) { 
    num = i; 
  } 

  int getnum() { 
    return num; 
  } 


// 一个泛型子类 
class Gen< T> extends NonGen {  
  T ob; 
    
  Gen(T o, int i) {  
    super(i); 
    ob = o;  
  }  
  
  T getob() {  
    return ob;  
  }  
}  
  
class HierDemo2 {  
  public static void main(String args[]) {  
    
    Gen< String> w = new Gen< String>("Hello", 47); 
    
    System.out.print(w.getob() + " "); 
    System.out.println(w.getnum()); 
  }  
}

清单 15
// 泛型层次中的运行时类型比较.  
class Gen< T> {   
  T ob;  
     
  Gen(T o) {   
    ob = o;   
  }   
   
  T getob() {   
    return ob;   
  }   
}   
  
// Gen的子类.  
class Gen2< T> extends Gen< T> {  
  Gen2(T o) {  
    super(o);  
  }  
}  
  
class HierDemo3 {   
  public static void main(String args[]) {   
     
    // Create a Gen object for Integers.  
    Gen< Integer> iOb = new Gen< Integer>(88);  
  
    // Create a Gen2 object for Integers.  
    Gen2< Integer> iOb2 = new Gen2< Integer>(99);   
    
    // Create a Gen2 object for Strings.  
    Gen2< String> strOb2 = new Gen2< String>("Generics Test");   
  
    // See if iOb2 is some form of Gen2. 
    if(iOb2 instanceof Gen2< ?>)   
      System.out.println("iOb2 is instance of Gen2");  

    // See if iOb2 is some form of Gen. 
    if(iOb2 instanceof Gen< ?>)   
      System.out.println("iOb2 is instance of Gen");  
  
    System.out.println();  
  
    // See if strOb2 is a Gen2. 
    if(strOb2 instanceof Gen2< ?>)   
      System.out.println("strOb is instance of Gen2");  
  
    // See if strOb2 is a Gen. 
    if(strOb2 instanceof Gen< ?>)   
      System.out.println("strOb is instance of Gen");  

    System.out.println();  
  
    // See if iOb is an instance of Gen2, which its not. 
    if(iOb instanceof Gen2< ?>)   
      System.out.println("iOb is instance of Gen2");  
  
    // See if iOb is an instance of Gen, which it is. 
    if(iOb instanceof Gen< ?>)   
      System.out.println("iOb is instance of Gen");  
  
    // The following can't be compiled because  
    // generic type info does not exist at runtime. 
    // if(iOb2 instanceof Gen2< Integer>)   
    // System.out.println("iOb2 is instance of Gen2< Integer>");  
  }   
}

运行结果:

C:\java>java     HierDemo3
iOb2 is instance of Gen2
iOb2 is instance of Gen

strOb is instance of Gen2
strOb is instance of Gen

iOb is instance of Gen

listing 16
// 重写泛型类中的方法
class Gen< T> {  
  T ob; 

  Gen(T o) {  
    ob = o;  
  }  
  
  
  T getob() {  
    System.out.print("Gen's getob(): " ); 
    return ob;  
  }  
}  

// Gen的子类重写了getob(). 
class Gen2< T> extends Gen< T> { 

  Gen2(T o) { 
    super(o); 
  } 
   
  T getob() {  
    System.out.print("Gen2's getob(): "); 
    return ob;  
  }  

  
// 演示重写泛型方法. 
class OverrideDemo {  
  public static void main(String args[]) {  
    
    // Create a Gen object for Integers. 
    Gen< Integer> iOb = new Gen< Integer>(88); 

    // Create a Gen2 object for Integers. 
    Gen2< Integer> iOb2 = new Gen2< Integer>(99);  
   
    // Create a Gen2 object for Strings. 
    Gen2< String> strOb2 = new Gen2< String>("Generics Test");  

    System.out.println(iOb.getob()); 
    System.out.println(iOb2.getob()); 
    System.out.println(strOb2.getob()); 
  }  
}
运行结果:

C:\java>java   OverrideDemo
Gen's getob(): 88
Gen2's getob(): 99
Gen2's getob(): Generics Test


清单 17
// 不使用泛型,迭代一个collection. 
import java.util.*; 

class OldStyle {  
  public static void main(String args[]) { 
    ArrayList list = new ArrayList(); 

    list.add("one"); 
    list.add("two"); 
    list.add("three"); 
    list.add("four"); 

    Iterator itr = list.iterator(); 
    while(itr.hasNext()) { 

     
      String str = (String) itr.next(); // 这里需要类型转换. 

      System.out.println(str + " is " + str.length() + " chars long."); 
    } 
  }  
}

清单 18
// 新的泛型版本. 
import java.util.*; 

class NewStyle {  
  public static void main(String args[]) { 

    ArrayList< String> list = new ArrayList< String>(); 

    list.add("one"); 
    list.add("two"); 
    list.add("three"); 
    list.add("four"); 

    // 注意Iterator 也是泛型. 
    Iterator< String> itr = list.iterator(); 

    // Iterator< Integer> itr = list.iterator(); // 这样会产生编译错误! 

    while(itr.hasNext()) { 
      String str = itr.next(); // no cast needed 

      // Now, the following line is a compile-time, 
      // rather than runtime, error. 
      // Integer i = itr.next(); // this won't compile 

      System.out.println(str + " is " + str.length() + " chars long."); 
    } 
  }  
}

清单 19(擦拭)
// 这个类编译后,T将被Object替换掉. 
class Gen< T> {  
  T ob; // here, T will be replaced by Object 
    
  Gen(T o) {  
    ob = o;  
  }  
  
  // Return ob.  
  T getob() {  
    return ob;  
  }  
}  

// 编译后.这个类中的T 将被String替换. 
class GenStr< T extends String> { 
  T str; // here, T will be replaced by String 

  GenStr(T o) {  
    str = o;  
  }  

  T getstr() { return str; } 
}

清单 20
class GenTypeDemo {  
  public  static void main(String args[]) {  
    Gen< Integer> iOb = new Gen< Integer>(99);  
    Gen< Float> fOb = new Gen< Float>(102.2F); 

    System.out.println(iOb.getClass().getName()); 
    System.out.println(fOb.getClass().getName()); 
  } 
}

运行的输出:(在编译时所有类型都被擦拭了,运行时,只有原始类型存在.)
Gen
Gen

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值