自定注解的语法
注解都隐式实现自java.long.Annotation接口。
注解:
@AnnotationName{elementDeclaration1=value1,elementDeclaration1=value2}
注解类代码
modifiers@interface AnnotationName{
elementDeclaration1
elementDeclaration2
.....
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Entrance
{
String[] value() default {};
}
注意以下几点:
第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;
第二
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组
第三
注解元素没有返回值,和参数,且默认值不能为null。字符串我们可以使用”“.对象我们可以使用Void.class
可注解的对象
类,接口,方法,构造器,实例域。
还有局部变量,参数变量,包,这三个暂时没明白等以后有时间再弄吧,先占着坑
元注解
meta-annotation注解就是注解注解的注解
@Target
限定注解的范围
@Retention
SOURCE:源码级别,不包括在类文件中
CLASS:包括在类文件中,但不包括在虚拟机中
RUNTIME:包括在类文件中,同时也包括在虚拟机中,可以通过反射获取它们
源代码级别的注解有两个意图, 一是作为文档的补充, 给人看的, 比如Override注解, 二是作为源代码生成器(java和android都有注解处理器APT)的材料, 比如ButterKnife框架.
同样字节码级别的注解, 可以作为字节码修改, 插桩, 代理的依据, 可以使用aspectj, asm等工具进行字节码修改. 比如一些模块间调用, 如果你直接写代码, 会导致耦合, 此时可以加入一个注解, run一下asm这样的工具, 将注解标注的方法字段以generate的方式插入进去.
运行时级别的注解, 显然是用于反射后参与某些业务逻辑用的, 比如spring依赖注入.
如果需要深入理解源码期注解可以自行参考注解处理器方面的API
案例
附上《java 核心技术》中用注解代替添加监听函数的代码
public class ActionListenerInstall{
public static void processAnontation(Object obj){
Class<?> c1=obj.getClass();
for(Method m:c1.getDeclaredMethods()){
ActionListenerFor atf=m.getAnnotation(ActionListenerFor.class);
if(atf!=null){
try {
Field fld=c1.getDeclaredField(atf.source());
fld.setAccessible(true);
//调用
addListenr(fld.get(obj),obj , m);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void addListenr(Object source ,final Object param,final Method M){
InvocationHandler handler=new InvocationHandler() {
//invoke ActionListener.addActionListener
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
//invoke ButtonFrame.changeBKtoBlue/Yellow funcation
return M.invoke(param);
}
};
//proxy class ActionListener
Object listener=Proxy.newProxyInstance(null,new Class[]{ActionListener.class}, handler);
try {
Method mt=source.getClass().getMethod("addActionListener",ActionListener.class);
mt.invoke(source,listener);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Junit的的代码
import static org.junit.Assert.*;
import org.junit.Test;
public class ButtonFrameTest {
@Test
public void test() {
assertTrue(true);
//fail("Not yet implemented");
}
}