注解是插入到代码中用于某种工具处理的标签。这些标签可以在源码层次上进行操作,或者可以处理编译器将其纳入到注解类文件中。
注解不会改变对程序的编译方式。Java编译器会对包含注解和不包含注解的代码生成相同的虚拟机指令。
在java中,注解通常使用@Annotation来表示,注解通常用于框架的设计,配合反射,从而减少代码量,明确业务逻辑。
我们最为常见的注解是@Override和@Test这种注解,前者用于标明方法为实现某接口,后者则常用于JUNIT.
下面给出个注解的实例定义:
@Target(ElementType.Method)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test
{
long timeout() default 0L;
}
@Interface声明创建了一个真正的java接口。处理注解的工具将接受实现了该接口的对象。
注解Target和Retention是元注解,它们注解了注解,即标识了Test注解是一个只能用在方法上的注解,并且当类文件载入虚拟机的时候,仍然可以保留下来。
注解的使用通常要配合反射使用,下面给出例子:
package com.inspur.jiyq.corejava.annotation;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonFrame extends JFrame{
private static final long serialVersionUID = 1L;
public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 200;
private JPanel panel;
private JButton yellowButton;
private JButton blueButton;
private JButton redButton;
public ButtonFrame()
{
setTitle("ButtonTest");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
panel = new JPanel();
add(panel);
yellowButton = new JButton("Yellow");
blueButton = new JButton("Blue");
redButton = new JButton("Red");
panel.add(yellowButton);
panel.add(blueButton);
panel.add(redButton);
ActionListenerInstaller.processAnnotations(this);
}
@ActionListenerFor(source = "yellowButton")
public void yellowBackground()
{
panel.setBackground(Color.YELLOW);
}
@ActionListenerFor(source = "blueButton")
public void blueBackground()
{
panel.setBackground(Color.BLUE);
}
@ActionListenerFor(source = "redButton")
public void redBackground()
{
panel.setBackground(Color.RED);
}
public static void main(String[] args)
{
ButtonFrame frame = new ButtonFrame();
frame.setVisible(true);
}
}
package com.inspur.jiyq.corejava.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ActionListenerFor {
String source();
}
package com.inspur.jiyq.corejava.annotation;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 用于分析注解及新增行为监听器
*/
public class ActionListenerInstaller {
/**
* Process all ActionListenerFor annotations in the given object
*
* @param obj
* an object whose methods may have ActionListnerFor annotations
*/
public static void processAnnotations(Object obj) {
try {
Class<?> cl = obj.getClass();
for (Method m : cl.getDeclaredMethods()) {
ActionListenerFor a = m.getAnnotation(ActionListenerFor.class);
if (a != null) {
Field f = cl.getDeclaredField(a.source());
f.setAccessible(true);
addListener(f.get(obj), obj, m);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addListener(Object source, final Object param,
final Method m) throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return m.invoke(param);
}
};
Object listener = Proxy.newProxyInstance(null,
new Class[] { java.awt.event.ActionListener.class }, handler);
Method adder = source.getClass().getMethod("addActionListener",
ActionListener.class);
adder.invoke(source, listener);
}
}