注解是插入到代码中用于某种工具处理的标签。这些标签可以在源码层次上进行操作,或者可以处理编译器将其纳入到注解类文件中。
注解不会改变对程序的编译方式。Java编译器会对包含注解和不包含注解的代码生成相同的虚拟机指令。
在java中,注解通常使用@Annotation来表示,注解通常用于框架的设计,配合反射,从而减少代码量,明确业务逻辑。
我们最为常见的注解是@Override和@Test这种注解,前者用于标明方法为实现某接口,后者则常用于JUNIT.
下面给出个注解的实例定义:
1
2
3
4
5
6
|
@Target (ElementType.Method)
@Retention (RetentionPolicy.RUNTIME)
public @interface Test
{ long
timeout() default
0L;
} |
@Interface声明创建了一个真正的java接口。处理注解的工具将接受实现了该接口的对象。
注解Target和Retention是元注解,它们注解了注解,即标识了Test注解是一个只能用在方法上的注解,并且当类文件载入虚拟机的时候,仍然可以保留下来。
注解的使用通常要配合反射使用,下面给出例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
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 );
}
} |
1
2
3
4
5
6
7
8
9
10
11
12
|
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();
} |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
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);
}
} |