/** 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”,显然是不对的。 */ }