分类: Java
2008-11-17 21:55:08
以下几个Java官方文档描述了一些java区别于其他语言的特殊性
反射
Proxy
Annotation
Many APIs require a fair amount of boilerplate code. For example, in order to write a JAX-RPC web service, you must provide a paired interface and implementation. This boilerplate could be generated automatically by a tool if the program were “decorated” with annotations indicating which methods were remotely accessible.
很多的API需要相当数量的样板代码。例如,为了写一个JAX-RPC(Java™ API for XMLbased RPC,顾名思义,它是一种远程方法调用) web service,你必须提供一组配对的接口和实现。如果你在那些远程访问的methods上“装饰”annotaions的话,那么你就可以通过一个工具来自动生成(generated
automatically)这些样板。
Other APIs require “side files” to be maintained in parallel with programs. For example JavaBeans requires a class to be maintained in parallel with a bean, and Enterprise JavaBeans (EJB) requires a deployment descriptor. It would be more convenient and less error-prone if the information in these side files were maintained as annotations in the program itself.
还有一些API需要"额外文件"来保持代码的同步。例如JavaBeans需要一个BeanInfo类来与一个Bean平行,EJB需要一个部署描述 。如果这些“额外文件”是用Annotaion在各自的代码上描述的话,将会更加的方便,并且减少错误。
The Java platform has always had various ad hoc annotation mechanisms. For
example the transient
modifier is an ad hoc annotation indicating
that a field should be ignored by the serialization subsystem, and the @deprecated
javadoc tag is an ad hoc annotation indicating that the
method should no longer be used. As of release 5.0, the platform has a general
purpose annotation (also known as metadata) facility that permits you
to define and use your own annotation types. The facility consists of a syntax
for declaring annotation types, a syntax for annotating declarations, APIs for
reading annotations, a class file representation for annotations, and an .
Annotations do not directly affect program semantics, but they do affect the way programs are treated by tools and libraries, which can in turn affect the semantics of the running program. Annotations can be read from source files, class files, or reflectively at run time.
说明不直接影响程序的语义,但它们确实改善了工具和Library的编程方式,它可以反过来影响程序的运行。 Annotation可以从源文件,类文件,在运行时间用反射来读取。
Annotations complement javadoc tags. In general, if the markup is intended to affect or produce documentation, it should probably be a javadoc tag; otherwise, it should be an annotation.
Typical application programmers will never have to define an annotation type,
but it is not hard to do so. Annotation type declarations are similar to normal
interface declarations. An at-sign (@
) precedes the interface
keyword. Each method declaration defines an
element of the annotation type. Method declarations must not have any
parameters or a throws
clause. Return types are restricted to
primitives, ,
,
,
annotations, and arrays of the preceding types. Methods can have default
values. Here is an example annotation type declaration:
典型应用程序员不需要定义一个Annotation类型(Annotation Type),但定义Annotation类型并不难。定义Annotation类型与定义Interface很像。at符号(@)后紧跟一个interface关键字,每个方法定义一个Annotation类型的元素。方法描述不可以有任何参数和throws描述。返回类型仅限基本类型、String、Class、枚举类型、Annotations、还有之前这些类型对应的数组类型。方法可以有默认值。这里是一个定义Annotaion Type的例子
/**
* Describes the Request-For-Enhancement(RFE) that led
* to the presence of the annotated API element.
*/
public @interface RequestForEnhancement {
int id();
String synopsis();
String engineer() default "[unassigned]";
String date() default "[unimplemented]";
}
Once an annotation type is defined, you can use it to annotate declarations.
An annotation is a special kind of modifier, and can be used anywhere that other
modifiers (such as public
, static
, or final
) can be used. By convention, annotations precede other
modifiers. Annotations consist of an at-sign (@
) followed by an
annotation type and a parenthesized list of element-value pairs. The values must
be compile-time constants. Here is a method declaration with an annotation
corresponding to the annotation type declared above:
一旦Annotaion类型定义好了,你就可以使用它来注解(annotate)描述信息了。Annotaion是一种特殊的修饰词(modifier),任何其他修饰词(如:public,static,或final)可以使用的地方都可以使用Annotaion。按照惯例,Annotaion会放在其他修饰词前面。at符合(@
)
紧跟Annotaion类型和一组用括号括起的元素-值。值必须是一个编译时常量(compile-time
constants)。这里是一个使用上面的Annotaion类型来注解一个函数的例子。
@RequestForEnhancement(
id = 2868724,
synopsis = "Enable time-travel",
engineer = "Mr. Peabody",
date = "4/1/3007"
)
public static void travelThroughTime(Date destination) { ... }
An annotation type with no elements is termed a marker annotation type, for example:
没有元素的Annotation类型被称为标记,例如
/**
* Indicates that the specification of the annotated API element
* is preliminary and subject to change.
*/
public @interface Preliminary { }
It is permissible to omit the parentheses in marker annotations, as shown below:
@Preliminary public class TimeTravel { ... }
In annotations with a single element, the element should be named value
, as shown below:
如果annotation只有一个元素,那这个元素应该被命名为value,如下:
/**
* Associates a copyright notice with the annotated API element.
*/
public @interface Copyright {
String value();
}
It is permissible to omit the element name and equals sign (=
)
in a single-element annotation whose element name is value
, as
shown below:
单一元素命名为value的Annotaion允许省略元素名和等号(=),如下:
@Copyright("2002 Yoyodyne Propulsion Systems")
public class OscillationOverthruster { ... }
To tie it all together, we'll build a simple annotation-based test framework. First we need a marker annotation type to indicate that a method is a test method, and should be run by the testing tool:
import java.lang.annotation.*;
/**
* Indicates that the annotated method is a test method.
* This annotation should be used only on parameterless static methods.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test { }
Note that the annotation type declaration is itself annotated. Such
annotations are called meta-annotations. The first (@Retention(RetentionPolicy.RUNTIME)
) indicates that annotations
with this type are to be retained by the VM so they can be read reflectively at
run-time. The second (@Target(ElementType.METHOD)
) indicates that
this annotation type can be used to annotate only method declarations.
Here is a sample program, some of whose methods are annotated with the above interface:
public class Foo {
@Test public static void m1() { }
public static void m2() { }
@Test public static void m3() {
throw new RuntimeException("Boom");
}
public static void m4() { }
@Test public static void m5() { }
public static void m6() { }
@Test public static void m7() {
throw new RuntimeException("Crash");
}
public static void m8() { }
}
Here is the testing tool:
import java.lang.reflect.*;
public class RunTests {
public static void main(String[] args) throws Exception {
int passed = 0, failed = 0;
for (Method m : Class.forName(args[0]).getMethods()) {
if (m.isAnnotationPresent(Test.class)) {
try {
m.invoke(null);
passed++;
} catch (Throwable ex) {
System.out.printf("Test %s failed: %s %n", m, ex.getCause());
failed++;
}
}
}
System.out.printf("Passed: %d, Failed %d%n", passed, failed);
}
}
The tool takes a class name as a command line argument and iterates over all
the methods of the named class attempting to invoke each method that is
annotated with the Test
annotation type (defined above). The
reflective query to find out if a method has a Test
annotation is
highlighted in green. If a test method invocation throws an exception, the test
is deemed to have failed, and a failure report is printed. Finally, a summary is
printed showing the number of tests that passed and failed. Here is how it looks
when you run the testing tool on the Foo
program (above):
$ java RunTests Foo
Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom
Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash
Passed: 2, Failed 2
While this testing tool is clearly a toy, it demonstrates the power of annotations and could easily be extended to overcome its limitations.