J2SE 5.0新功能 – Annotation
Annotation是J2SE提供的一种新语法,根据规范的说明,他的作用简单来说就是简化代码的维护。例如,EJB需要7个文件,一个XML文件来表示,通过Annotation,我们可以只需要维护源代码,其他工作都可以通过自动生成达到。这个做法跟Lomboz的效果比较一致,不过Lomboz是通过XDoclet来实现,而现在只要使用Annotation就可以了,但是Annotation只是一个必要条件,如果真要达到自动生成其他文件的目的,除了Annotation之外,还需要其他类,或者工具的支持。
1. 预定义Annotation
Tiger为我们预定义了3个可以用的Annotation,分别是Override,Deprecated,SuppressWarnings。
i. Override
1. 作用:
Override的作用就是,被生命为Override的方法,必须是对父类中方法的覆盖,如果父类中没有出现该方法,或者方法没有正确覆盖父类中的方法,则编译期就会出错。
2. 语法:
@Override public void methodA(){…}
3. 例子:
父类:
/*
* Created on 2005-1-4
*
*/
package test;
/**
*
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test {
public Test() {
}
public void hello() {
System.out.println(“hello”);
}
public void bye() {
System.out.println(“bye”);
}
}
子类:
/*
* Created on 2005-1-5
*
*/
package test;
/**
*
* @author cenyongh@mails.gscas.ac.cn
*/
public class OverTest extends Test{
@Override public void hello(){}
@Override public void methodA(){}
}
错误信息:
The method methodA() of type OverTest must override a superclass method
4. 评价:
通过Override,我们能够确保子类中的方法的确覆盖了父类中的方法。但是现在一般的IDE都可能提供了这种表示覆盖的提示,像我正在使用的Eclipse就有一个对应的符号,表示某个方法是否覆盖了父类中的方法,所以这个标记,或者只对那些还在使用Ultraedit的程序员有比较明显的作用。
ii. Deprecated
1. 作用:
用于声明一个方法不建议再被使用。
2. 语法:
@Deprecated public void methodA(){…}
3. 例子:
声明类:
/*
* Created on 2005-1-4
*
*/
/**
*
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test {
public Test() {
}
/**
*
* @deprecated
* */
public void hello() {
System.out.println(“hello”);
}
@Deprecated public void bye() {
System.out.println(“bye”);
}
}
调用类:
/*
* Created on 2005-1-5
*
*/
/**
*
* @author cenyongh@mails.gscas.ac.cn
*/
public class CallTest {
public CallTest(){
Test t = new Test();
t.hello();
t.bye();
}
}
编译信息:
CallTest.java:14: warning: [deprecation] hello() in Test has been deprecated
t.hello(); ^
CallTest.java:15: warning: [deprecation] bye() in Test has been deprecated
t.bye(); ^
2 warnings
4. 评价:
对于Deprecated这个标记,我认为,已经有一个deprecated在之前的JavaDoc标记中定义过了,为什么J2SE还要额外的增加这样的一个,完全搞不懂。
iii. SuppressWarnings
1. 作用:
这个标记的作用就是可以让编译器忽略掉一些编译期的错误,不报错。
2. 语法:
@SuppressWarnings(“unchecked”) public void void methodA(){…}
3. 例子:
原文件:
public void bye() {
ArrayList list = new ArrayList();
list.add(“Hello”);
System.out.println(“bye”);
}
错误信息:
warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.ArrayList
list.add(“Hello”);
修改后的文件:
@SuppressWarnings( { “unchecked” }) public void bye() {
ArrayList list = new ArrayList();
list.add(“Hello”);
System.out.println(“bye”);
}
4. 评价:
SuppressWarnings的作用就是可以隐藏某些编译期的消息,他主要使用的地方或者就是在范型方面。但是,实际上这个标记在Tiger当中是没有实现的,所以上述修改后的代码,在他的输出结果当中,还是会输出同样的错误,呵呵。
2. 自定义Annotation
程序员可以根据自己的需求自定义一些特定的Annotation。但是,我认为有一点是很重要的,就是Annotation的存在不应该影响Java程序的语义,也就是说,使用Annotation前后,程序的含义,执行都不应该发生改变,即使一个程序员完全不了解Annotation的语法,他也应该能够毫无障碍的阅读Java源代码。
i. 语法:
Annotation一般有三种形式,就是不含有属性的,只有一个属性,和含有多个属性的。
1. 不含属性:
public @interface MyAnno{}
注:不含属性的Annotation的作用就跟不含方法的接口类似,只是作为标记的用途。
2. 一个属性:
public @interface MyAnno{
String value();
}
注:当只含有一个属性时,属性的名称需要命名为value,这是Annotation里面的一个规定。
3. 多个属性:
public @interface MyAnno{
String hello();
int income() default 1;
}
注:当有多个属性时,属性名称可以任意。注意的是,属性的类型必须是基本类型,String,enum,Class,Annotations和这些类型的数组形式,而且属性可以通过default来声明默认值。
ii. 使用:
Annotation使用的时候,跟声明符(public,private等)类似,但一般他们都是放在第一个,即public之前。
1. 不含属性:
@MyAnno public void methodA(){…}
2. 一个属性:
@MyAnno(“hello”) pubic void methodA(){…}或者
@MyAnno(value=”hello”) public void methodA(…)
3. 多个属性:
@MyAnno(hello=”hello”,income=”1″) public void methodA(){…}
iii. 例子:
Annotation类:
/*
* Created on 2005-1-4
*
*/
package test;
import java.lang.annotation.*;
/**
*
* @author cenyongh@mails.gscas.ac.cn
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Remote {}
使用类:
/*
* Created on 2005-1-4
*
*/
package test;
import java.lang.reflect.*;
/**
*
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test {
public Test() {}
@Remote public void hello() {
System.out.println(“hello”);
}
@Remote public void bye() {
System.out.println(“bye”);
}
public static void main(String[] args) {
try {
Class c = Class.forName(“test.Test”);
Method[] ms = c.getMethods();
for (Method m : ms) {
if (m.isAnnotationPresent(Remote.class)) {
System.out.println(m.getName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
iv. 注意事项:
在声明一个新的Annotation时,一般需要带上@Retention标记,因为这个表明了Annotation的存活时间。@Retention的取值有3个,RetentionPolicy.SOURCE表示Annotation只在编译期有效,编译之后就会被编译器丢掉。RetentionPolicy.CLASS表示Annotaion将会保存到.class文件当中,但是并不会被VM提取。RetentionPolicy.RUNTIME表示Annotaion将会保存到.class文件当中,而且运行时,也会被VM提取,即通过reflect方法,能够获取到该标记。
3. 评价:
总的来说,Annotation的意义并不如之前提到的enhance for loop,generic types等新功能大,但这个只是相对来说,由于Annotation并不影响Java的语义,所以,对于一般Java程序员来说,完全可以忽略。而且,如果真的要利用Annotation,程序员还需要自己书写reflect方面的代码来提取这些Annotation来做其他额外的工作,这个一般来说,应该比较少出现。但是Annotation对于像插件开发商,其他程序员是的确有用的,像EJB开发的时候,我们可以不需要通过XDoclet的方式,也能达到所需的效果。
Tags: j2se
Leave a Reply
You must be logged in to post a comment.
近期评论