Skip to content

Latest commit

 

History

History
115 lines (94 loc) · 3.74 KB

02_Static_Members.md

File metadata and controls

115 lines (94 loc) · 3.74 KB

《《《 返回首页
《《《 上一节

静态成员

因为泛型是通过擦除编译的,所以在运行时类List<Integer>List<String>List<List<String>> 全部由一个类实现,即 List。你可以看到这个使用 反射:

  List<Integer> ints = Arrays.asList(1,2,3);
  List<String> strings = Arrays.asList("one","two");
  assert ints.getClass() == strings.getClass();

这里在运行时与整数列表关联的类与与字符串列表关联的类相同。

其中一个结果是泛型类的静态成员在该类的所有实例上共享,包括不同类型的实例。 类的静态成员不能引用泛型类的类型参数,并且在访问静态成员时,不应该对类名称 进行参数化。

例如,下面是一个类 Cell<T>,其中每个单元格都有一个整型标识符和一个类型为 T 的值:

class Cell<T> {
  private final int id;
  private final T value;
  private static int count = 0;
  private static synchronized int nextId() { 
    return count++; 
  }
  public Cell(T value) { 
    this.value=value; id=nextId(); 
  }
  public T getValue() { 
    return value; 
  }
  public int getId() { 
    return id; 
  }
  public static synchronized int getCount() { 
    return count; 
  }
}

静态字段 count 用于为每个单元分配不同的标识符。 静态 nextId 方法被同步,以确保即使在多个线程的情况下也能生成唯一的标识符。 静态 getCount 方 法返回当前计数。

这里是分配包含字符串的单元格和包含整数的单元格的代码,它们分别分配了标识符 01

  Cell<String> a = new Cell<String>("one");
  Cell<Integer> b = new Cell<Integer>(2);
  assert a.getId() == 0 && b.getId() == 1 && Cell.getCount() == 2;

静态成员在类的所有实例中共享,因此在分配字符串或整数单元格时,相同的计数会递增。

由于静态成员独立于任何类型参数,因此在访问静态成员时,我们不允许使用类型参数跟随类名称:

  Cell.getCount(); // ok
  Cell<Integer>.getCount(); // 编译报错
  Cell<?>.getCount(); // 编译报错

计数是静态的,所以它是整个类的一个属性,而不是任何特定的实例。

出于同样的原因,您不能在静态成员中的任何地方引用类型参数。 以下是 Cell 的第二个版本,它试图使用一个静态变量来保存存储在任何单元中的所有值的列表:

class Cell2<T> {
  private final T value;
  private static List<T> values = new ArrayList<T>(); // illegal
  public Cell(T value) { 
    this.value=value; 
    values.add(value); 
  }
  public T getValue() { 
    return value; 
  }
  public static List<T> getValues() { 
    return values; 
  } // illegal
}

由于类可能在不同的地方使用不同的类型参数,因此在声明静态字段值或静态方法 getValues() 时引用 T 是没有意义的,并且这些行在编译时会报告为错误。如果 我们想要一个单元格中保存的所有值的列表,那么我们需要使用一个对象列表,如下面的变体所示:

class Cell2<T> {
  private final T value;
  private static List<Object> values = new ArrayList<Object>(); // ok
  public Cell(T value) { 
    this.value=value; values.add(value); 
  }
  public T getValue() { 
    return value; 
  }
  public static List<Object> getValues() { 
    return values; 
  } // ok
}

这段代码编译和运行没有任何困难:

Cell2<String> a = new Cell2<String>("one");
Cell2<Integer> b = new Cell2<Integer>(2);
assert Cell2.getValues().toString().equals("[one, 2]");

《《《 下一节
《《《 返回首页