注解
来源:互联网 发布:光学透镜设计软件 编辑:程序博客网 时间:2024/05/23 17:30
在学习Effictive Java注解几节的内容之前,我们先看一下Java注解的基础知识。
1. Java的内置注解。
2. 定义注解和元注解。
3. 怎么使用注解。
4. 自定义注解实现依赖注入。
1. Java的内置注解。
a.@Override
这个我们非常熟悉,子类覆盖父类的方法是需要在子类方法上添加这个注解。如果你的方法拼写错误,编译器就会报错。
b.@Deprecated
这个注解我们很少会用到,当部分人肯定会碰到过。表示注解的元素过期了,不再使用了,如果使用的话,编译器会给警告。
c.@SuppressWarnings
这个我们也很熟悉,当我们需要编译器忽略掉这个警告的时候使用它。
总的来说,这三个注解其实并不会影响程序的运行,我们用到的功能比较强大的注解都是一些框架的自定义注解。
2. 定义注解和元注解。
我们看一下下面代码,这是注解@Override的定义。定义注解和接口的定义有点类似,只不过多了一个@符号。@Target, @Retention叫做元注解,就是用来定义注解的注解。我们来看一下各种元注解的作用。
@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public @interface Override {}
a.Target用来表示你的注解用在什么地方,上面的ElementType.METHOD,表示这个注解用在方法上。除了METHOD,还有很多,看下面代码,
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, 可以修饰类接口,包括注解类型,和枚举类型 /** Field declaration (includes enum constants) */ FIELD, 修饰域,也就是变量 /** Method declaration */ METHOD, 修饰方法 /** Formal parameter declaration */ PARAMETER, 修饰参数,比如我们Mybatis框架常用的@param /** Constructor declaration */ CONSTRUCTOR, 修饰构造器 /** Local variable declaration */ LOCAL_VARIABLE, 修饰局部变量 /** Annotation type declaration */ ANNOTATION_TYPE, 修饰注解类型 /** Package declaration */ PACKAGE, 修饰包 /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, Java8添加的,有兴趣的可以了解一下 /** * Use of a type * * @since 1.8 */ TYPE_USE Java8添加的,有兴趣的可以了解一下}
b.Retention
@Retention表示注解信息保留到什么时候,取值只能有一个,类型为RetentionPolicy,它是一个枚举,有三个取值:
- SOURCE:只在源代码中保留,编译器将代码编译为字节码文件后就会丢掉
- CLASS:保留到字节码文件中,但Java虚拟机将class文件加载到内存时不一定会在内存中保留
- RUNTIME:一直保留到运行时
如果没有声明@Retention,默认为CLASS。
@Override和@SuppressWarnings都是给编译器用的,所以@Retention都是RetentionPolicy.SOURCE,自定注解一般都为RUNTIME,程序运行的时候可以得到。
c.Documented - 将此注解包含在JavaDoc中
d.Inherited 允许子类继承父类中的注解
前面两个在自定义注解的时候用的比较多。
要使用注解,首先要取得注解的信息才行,看下面代码,Class中有下面这些供注解使用的方法。通过反射来获取注解信息。
//获取所有的注解public Annotation[] getAnnotations()//获取所有本元素上直接声明的注解,忽略inherited来的public Annotation[] getDeclaredAnnotations()//获取指定类型的注解,没有返回nullpublic <A extends Annotation> A getAnnotation(Class<A> annotationClass)//判断是否有指定类型的注解public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
我们来看一个简单的例子,看下面代码,定义了一个DefaultValue注解,通过反射得到注解信息后,就可以做自己想做的很多事了。
public class Test{ @Target(ElementType.PARAMETER) 修饰参数 @Retention(RetentionPolicy.RUNTIME) 运行时候也可以得到注解信息 static @interface DefaultValue { String value() default ""; } public void hello(@DefaultValue("owen") String sort){ ... } public static void main(String[] args) throws Exception { Class<?> cls = Test.class; 得到Class对象 Method method = cls.getMethod("hello", String.class); 得到方法hello Annotation[][] annts = method.getParameterAnnotations(); 得到方法参数的注解 for(int i=0; i < annts.length; i++){ Annotation[] anntArr = annts[i]; for(Annotation annt : anntArr){ if(annt instanceof DefaultValue){ DefaultValue dv = (DefaultValue)annt; 得到DefaultValue注解 System.out.println(dv.annotationType().getSimpleName()+":"+ dv.value()); 打印注解的名字和设的值 } } } }}
4. 自定义注解实现依赖注入。
Spring框架中的依赖注入可以通过配置文件的方式注入,同样可以通过注解的方式注入,我们用注解来实现一个简单的依赖注入。
@Retention(RUNTIME) 运行时可以得到@Target(FIELD) 修饰域的public @interface autowired{}public class ServiceA { @autowired 注入b ServiceB b;}public class ServiceB {}ServiceA a = SimpleContainer.getInstance(ServiceA.class); 这个方法是关键public static <T> T getInstance(Class<T> cls) { try { T obj = cls.newInstance(); 实例化对象 Field[] fields = cls.getDeclaredFields(); 取得对象的域 for (Field f : fields) { if (f.isAnnotationPresent(autowired.class)) { 判断是否被注解修饰 if (!f.isAccessible()) { 让我们有操作这个字段的权限 f.setAccessible(true); } Class<?> fieldCls = f.getType(); 取得域的类型 f.set(obj, getInstance(fieldCls)); 实例化类型并注入b,这个是真正起作用的语句 } } return obj; } catch (Exception e) { throw new RuntimeException(e); }}
有了注解的基础,后面我们再看一下Effective Java中注解的知识点。
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解
- 注解。
- 注解
- 注解
- 注解
- 注解
- python基础练习
- bzoj 3790(manacher+树状数组)
- hdu 2090 算菜价
- [BZOJ1576] [Usaco2009 Jan]安全路经Travel
- jdk 源码分析(8)java synchronized和锁lock对比
- 注解
- 程序员面试-数据库 1
- LeetCode 561. Array Partition I
- hdu 2091 空心三角形
- 如何向eclipse中添加数据库驱动文件开发JDBC程序
- 高级数据结构2--并查集
- 八大排序算法之-快速排序 java代码
- 关于函数的调用过程(栈帧)
- 制作软盘镜像文件