The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
One of the changes in JDK 5.0 is that the class JDK 5.0中的一个变化是java.lang.Class
is generic. java.lang.Class
类泛型的。It's an interesting example of using genericity for something other than a container class.这是一个有趣的例子,它将泛型用于容器类以外的其他对象。
Now that 现在这个Class
has a type parameter T
, you might well ask, what does T
stand for? Class
有了一个类型参数T
,你可能会问,T
代表什么?It stands for the type that the 它代表Class
object is representing.Class
对象所代表的类型。
For example, the type of 例如,String.class
is Class<String>
, and the type of Serializable.class
is Class<Serializable>
. String.class
的类型是Class<String>
,Serializable.class
的类型是Class<Serializable>
。This can be used to improve the type safety of your reflection code.这可以用来提高反射代码的类型安全性。
In particular, since the 特别是,由于newInstance()
method in Class
now returns a T
, you can get more precise types when creating objects reflectively.Class
中的newInstance()
方法现在返回一个T
,所以在反射式创建对象时可以获得更精确的类型。
For example, suppose you need to write a utility method that performs a database query, given as a string of SQL, and returns a collection of objects in the database that match that query.例如,假设您需要编写一个实用程序方法来执行数据库查询(以SQL字符串形式给出),并返回数据库中与该查询匹配的对象集合。
One way is to pass in a factory object explicitly, writing code like:一种方法是显式传入factory对象,编写如下代码:
interface Factory<T> { T make();} public <T> Collection<T> select(Factory<T> factory, String statement) { Collection<T> result = new ArrayList<T>(); /* Run sql query using jdbc */ for (/* Iterate over jdbc results. */) { T item = factory.make(); /* Use reflection and set all of item's * fields from sql results. */ result.add(item); } return result; }
You can call this either as你可以用这种方式调用它
select(new Factory<EmpInfo>(){ public EmpInfo make() { return new EmpInfo(); }}, "selection string");
or you can declare a class 或者可以声明一个类EmpInfoFactory
to support the Factory
interfaceEmpInfoFactory
来支持Factory
接口
class EmpInfoFactory implements Factory<EmpInfo> { ... public EmpInfo make() { return new EmpInfo(); } }
and call it也可以用这种方式调用它
select(getMyEmpInfoFactory(), "selection string");
The downside of this solution is that it requires either:这种解决方案的缺点是需要:
It is natural to use the class literal as a factory object, which can then be used by reflection. 将类字面量用作工厂对象是很自然的,然后反射就可以使用它。Today (without generics) the code might be written:今天(没有泛型),代码可能是这样写的:
Collection emps = sqlUtility.select(EmpInfo.class, "select * from emps"); ... public static Collection select(Class c, String sqlStatement) { Collection result = new ArrayList(); /* Run sql query using jdbc. */ for (/* Iterate over jdbc results. */ ) { Object item = c.newInstance(); /* Use reflection and set all of item's * fields from sql results. */ result.add(item); } return result; }
However, this would not give us a collection of the precise type we desire. 然而,这并不能提供我们想要的精确类型的集合。Now that 既然该Class
is generic, we can instead write the following:Class
是泛型的,我们可以编写以下内容:
Collection<EmpInfo> emps = sqlUtility.select(EmpInfo.class, "select * from emps"); ... public static <T> Collection<T> select(Class<T> c, String sqlStatement) { Collection<T> result = new ArrayList<T>(); /* Run sql query using jdbc. */ for (/* Iterate over jdbc results. */ ) { T item = c.newInstance(); /* Use reflection and set all of item's * fields from sql results. */ result.add(item); } return result; }
The above code gives us the precise type of collection in a type safe way.上面的代码以类型安全的方式为我们提供了精确的集合类型。
This technique of using class literals as run time type tokens is a very useful trick to know. 这种将类文本用作运行时类型标记的技术是一个非常有用的技巧。It's an idiom that's used extensively in the new APIs for manipulating annotations, for example.例如,这是一个在新的API中广泛使用的用于操作注释的习惯用法。