Exemplo n.º 1
0
  /** Get the value for the key in this context. */
  public <T> T get(Key<T> key) {
    try {
      DEBUG.P(this, "get(Key<T> key)");
      // if(key!=null) DEBUG.P("key="+key.getClass().getName());
      // else DEBUG.P("key="+key);
      DEBUG.P("key=" + key);

      checkState(ht);
      Object o = ht.get(key);

      if (o != null) DEBUG.P("o=" + o.getClass().getName());
      else DEBUG.P("o=" + o);

      DEBUG.P("(o instanceof Factory)=" + (o instanceof Factory));

      if (o instanceof Factory) {
        Factory fac = (Factory) o;
        o = fac.make();
        if (o instanceof Factory) throw new AssertionError("T extends Context.Factory");
        // 也就是说在调用make()时已把make()返回的结果放入ht(例子见:JavacFileManager.preRegister())
        assert ht.get(key) == o;
      }

      /* The following cast can't fail unless there was
       * cheating elsewhere, because of the invariant on ht.
       * Since we found a key of type Key<T>, the value must
       * be of type T.
       */
      return Context.<T>uncheckedCast(o);

    } finally {
      DEBUG.P(0, this, "get(Key<T> key)");
    }
    /*
    注意这里的“<T>”与 “private static <T> T uncheckedCast(Object o)”中
    的“<T>”的差别,前者表示的是get(Key<T> key)方法中的“T”的实际类型,
    假设最开始:
    -------------------------------------
    Context context = new Context();
    Context.Key<Number> numberKey = new Context.Key<Number>();
    Number number=new Number();
    context.put(numberKey,number);

    number=context.get(numberKey);
    ------------------------------------
    这时把“numberKey”传进“get(Key<T> key)”方法,
    因为参数“numberKey”是“Context.Key<Number>”类型,
    所以get(Key<T> key)中的“T”的实际类型是“Number”。

    但是“get(Key<T> key)”方法里的“Object o = ht.get(key)”,
    变量“o”是Object类型的,必需调用“Context.<T>uncheckedCast(o)”将
    变量“o”引用的Object实例转换成“Number”类型,
    这样“number=context.get(numberKey)”得到的结果才正确。
    “Context.<T>uncheckedCast(o)”相当于把“Object o”转换成“<T>”(这里就是Number)

    像“Context.<T>uncheckedCast(o)”这种语法确实很古怪,
    这主要是由于“private static <T> T uncheckedCast(Object o)”方法的定义
    造成的,这个方法是一个静态泛型方法,而且只有返回类型与泛型变量“<T>”相关,
    方法参数只有( Object o ),并且不与泛型变量“<T>”相关,
    当要调用uncheckedCast方法时,可以用下面的格式调用它:
    Context.<返回值类型>uncheckedCast(参数Object o)

    返回值类型可以是泛型变量
    (泛型变量的实际类型在编译期间只能推断它的上限绑定,
    具体是什么类型只能在运行期间确定)


    假设最开始:
    Object o=new String("str");
    那么可以这样调用它:
    String str=Context.<String>uncheckedCast(o);(等价于: String str=(String)o)

    把“return Context.<T>uncheckedCast(o);”与uncheckedCast方法的调用格式对照
    “<T>”对应“<返回值类型>”,“(o)”对应“(参数Object o)”

    另外“uncheckedCast”方法的定义如下:
    --------------------------------------
    @SuppressWarnings("unchecked")
       private static <T> T uncheckedCast(Object o) {
           return (T)o;
       }
       --------------------------------------
       注释“@SuppressWarnings("unchecked")”间接指出了uncheckedCast方法会在
       运行时有可能产生转换异常(java.lang.ClassCastException),
       因为(T)的类型是未确定的,
       比如(T)的类型可能是“Number”,当参数(Object o)实际是String的实例引用时,
       这时“(T)o”就等价于“(Number)String”,显然是不对的。
    */
  }