Java注解(Annotation)
1,什么是注解?
注解就是代码中特殊的标记,这些标记在编译,类加载和运行时可以被读取,并且执行相应的处理。注解不会影响程序代码的执行
2,基本的注解
@Override
@Deprecated
@SuppressWarnings
@SafeVarargs(Java7新增)
@FunctionalInterface(Java8新增)
2.1,@Override
public class Demo01{
public void info(){
System.out.println("233333");
}
}
class A extends Demo01{
@Override
public void info() {
System.out.println("2444444");
}
}
@Override用来指定方法覆盖,它可以强制一个子类必须覆盖父类方法,这也是最常见的一个注解了,它告诉编译器检查这个方法,保证父类包含一个方法重写,否则报错
2.2,@Deprecated
该注解表示某个程序元素(类,方法等)已过时,当其他程序使用已过时的类,方法时,编译器会给出警告。
2.3,@SuppressWarnings
该注解可以抑制编译器的警告
3,JDK元注解
元注解用于修饰其他的注解定义
3.1,@Retention
@Retention包含一个RetentionPolicy类型的value变量,
1,RetentionPolicy.Class:编译器把注解记录在class文件中,运行java程序时,JVM不可获取注解信息,这是默认值
2,RetentionPolicy.RUNTIME:编译器把注解记录在class文件中,运行java程序时,JVM可获取注解信息,程序可以通过反射获取该注解信息
3,RetentionPolicy.SOURCE:注解只保留在源代码中,编译器直接丢弃这种注解
//定义下面的@Testable注解保留到运行时
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Testable{}
3.2,@Target
它用于指定被修饰的注解能用于修饰那些程序单元,包含一个ElementType类型value变量
1,ElementType.FIELD:指定该注解只能修饰构造器
2,ElementType.METHOD:指定该注解只能修饰方法定义
3,ElementType.PACKAGE:指定该注解只能修饰包定义
4,ElementType.PARAMETER:指定该注解可以修饰参数
//@ActionListenerFor注解只能修饰成员变量
@Target(ElementType.FIELD)
public @interface ActionListenerFor{}
3.3,@Documented
被该元注解修饰的注解类将被javadoc工具提取成文档
//定义Test注解将被javadoc工具提取
//自定义注解使用@interface关键字
@Documented
public @interface Test{}
3.4,@Inherited
允许子类继承父类中的注解
//@Inheritable具有继承性了
@Inherited
public @interface Inheritable {
}
@Inheritable
class Base{
}
public class Demo02 extends Base{
public static void main(String[] args) {
System.out.println(Demo02.class
.isAnnotationPresent(Inheritable.class));
}
}
Base类使用@Inheritable修饰,Demo02类继承Base类,也被@Inheritable修饰,打印结果为true
4,注释的具体的使用
使用注释修饰了类,方法,成员变量等成员后,这些注解不会自己生效,必须要由开发者提供相应的工具来提取并处理注解信息,从Java5开始,java.lang.reflect包提供的反射API增加了读取运行时注解的能力
通过注解来简化事件编程
1,定义了一个@ActionListenerFor注解,指定了一个listener成员变量,用于指定监听器的实现类
import java.awt.event.ActionListener;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ActionListenerFor {
//定义一个成员变量用于保存监听器实现类
Class<? extends ActionListener> listener();
}
2,使用@ActionListenerFor注解为两个按钮绑定时间监听器,使用注解@ActionListenerInstaller时传入listener元数据,该数据用于设定每个按钮的监听器实现类
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
class OkListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "单击了确认按钮");
}
}
class CancelListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "单击了取消按钮");
}
}
public class AnnotationTest {
private JFrame mainwin = new JFrame("1");
@ActionListenerFor(listener = OkListener.class)
private JButton ok = new JButton("确定");
@ActionListenerFor(listener = CancelListener.class)
private JButton cancel = new JButton("取消");
public void init() {
JPanel jp = new JPanel();
jp.add(ok);
jp.add(cancel);
mainwin.add(jp);
//处理本程序中的注解
ActionListenerInstaller.processAnnotations(this);
mainwin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainwin.pack();
mainwin.setVisible(true);
}
public static void main(String[] args) {
new AnnotationTest().init();
}
}
3,使用ActionListenerInstaller类来处理程序中的注解,该处理器分析取自目标对象中的所有成员变量,如果没有这个处理器,注解并不能起作用
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import javax.swing.AbstractButton;
public class ActionListenerInstaller {
public static void processAnnotations(Object obj) {
try {
Class c1 = obj.getClass();
for(Field f:c1.getDeclaredFields()) {
//将该成员变量设置成可自由访问
f.setAccessible(true);
//获取该成员变量上ActionListenerFor类型的注解
ActionListenerFor a = f.getAnnotation(ActionListenerFor.class);
Object fObj = f.get(obj);
if(a!=null && fObj!=null && fObj instanceof AbstractButton) {
//获取a注解里的listener元数据(它是一个监听器类)
Class<? extends ActionListener> listenerClazz = a.listener();
//使用反射创建listener类对象
ActionListener a1 = listenerClazz.newInstance();
AbstractButton ab = (AbstractButton) fObj;
ab.addActionListener(a1);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
程序运行结果:
这是一个很典型的注解应用的例子,在安卓中也是能经常能看到,其他的框架中也是很常见的,掌握这种注释绑定事件编程十分有必要