源代码:https://gitee.com/AgentXiao/annotation
一、说明
它不是注释 注释是程序员写的,给程序员的
注解给程序看,用于描述程序如何运行及在什么阶段来运行。
注解现在在实际开发中,最大的功能是用于替换配置文件。
注解是jdk1.5的新特性
可以通过反射来让注解具有功能。
注解 @xxxx
二、自定义注解
1、JDK中的三种基本注解
a、@Override 检查子类确实是覆盖了父类的方法。
b、@Deprecated:说明已经过时了。
c、@SuppressWarnings({ "unused", "deprecation" }):抑制程序中的警告。unused警告的类型。{}数组。all抑制所有警告。
2、自定义注解
声明一个注解
public @interface MyAnnotation{}
注解的本质就是一个接口,这个接口需要继承 Annotation接口。但是不能人为进行继承。反编译后得到一下信息:public interface MyAnnotation extends java.lang.annotation.Annotation。
注解中的成员
注解本质上就是接口,接口中可以有属性方法
属性 : 例:int age();
注解的定义者
/**
* @InterfaceName MyAnnotation
* @Description 自定义注解类
* @Author xwd
* @Date 2018/10/2 10:28
*/
public @interface MyAnnotation {
//属性
int age();
String name();
//有默认值,在使用时给不给值都可以
String sex() default "";
}
注解的使用者
/**
* @ClassName TestMyAnno
* @Description 测试我自定义的注解类
* @Author xwd
* @Date 2018/10/2 10:40
*/
public class TestMyAnno {
@MyAnnotation(age = 18,name = "xwd")
public void test(){
}
}
3、注解的反射(重点)
a、反射注解类
java.lang.reflect.AnnotatedElement
- <T extends Annotation> T getAnnotation(Class<T> annotationType):得到指定类型的注解引用。没有返回null。
- Annotation[] getAnnotations():得到所有的注解,包含从父类继承下来的。
- Annotation[] getDeclaredAnnotations():得到自己身上的注解。
- boolean isAnnotationPresent(Class<? extends Annotation> annotationType):判断指定的注解有没有。
由于Class、Method、Field、Constructor等实现了AnnotatedElement接口,因此Class.isAnnotationPresent(MyTest.class):判断类上面有没有@MyTest注解;
Method.isAnnotationPresent(MyTest.class):判断方法上面有没有@MyTest注解。
b、反射注解中的属性
/**
* @InterfaceName MyTest
* @Description 自定义的测试注解
* @Author xwd
* @Date 2018/10/2 15:11
*/
public @interface MyTest {
}
如下图在使用自定义的测试注解时,是不会出现可执行标记的。
使用自定义注解我们写一个类进行测试,实现如果该方法被@MyTest注解了,就输出true且执行。
package pri.xiaowd.demo05;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @ClassName TestRunner
* @Description
* @Author xwd
* @Date 2018/10/2 15:19
*/
public class TestRunner {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException {
//实现查看测试类中的方法,哪个有@MyTest就执行那个
//得到class对象
Class c = Student.class;
//得到类中的方法
Method[] methods = c.getMethods();
//遍历所有方法
for(Method method:methods){
//如果这个方法有@MyTest注解,则执行
boolean b = method.isAnnotationPresent(MyTest.class);
System.out.println(method.getName()+"-->"+b);
if(b){
method.invoke(c.newInstance(),null);
}
}
}
}
输出结果发现:
eatLunch-->false
readBook-->false
这是因为自定义注解@MyTest的生命周期默认为CLASS。在讲解之前,先说“元注解”的概念。
在我们运行程序时,是通过类加载器在内存中获取注解的,但是这是自定义注解的生命周期已死亡,因此也是取不到的。
什么是元注解
只能用在注解上的注解叫做元注解。(即:用于修饰注解的注解)
- @Retention:作用。改变自定义的注解的存活范围。
RetentionPolicy:
SOURCE
CLASS
RUNTIME - @Target:作用,指定该注解能用在什么地方。
ElementType:
TYPE:
METHOD:
FIELD:
ANNOTATION_TYPE - @Documented:作用,使用了@MyTest的注解的类,如果@MyTest注解上面有@Documented注解,那么使用了@MyTest的注解的类的API文档中会出现@MyTest的身影。
- @Inherited:作用,说明该注解可以被继承下去。
/**
* @InterfaceName MyTest
* @Description 自定义的测试注解
* @Author xwd
* @Date 2018/10/2 15:11
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}
接了一个元注解之后,运行得:
readBook-->true
在看书
eatLunch-->false
4、Servlet3.0:web.xml已经不是必须的了。替代它的就是注解。
例如servlet中使用@webServlet(name = "LoginServlet",urlPattern = "/LoginServlet")
例如Filter中使用@webFilter("/*")
使用web.xml:优点可配置,不用修改源码;缺点是不直观,开发效率低。
使用注解:有点是直观,开发效率高;缺点是硬编码
三、类加载器
1、作用:负责把磁盘上的class文件加载到JVM中,并生成Class对象
2、JVM中的类加载器:
- BootStrap:老大。类加载器的祖先。 打印它会得到null。
负责加载JRE/lib/rt.jar(JDK中绝大部分的类) - ExtClassLoader:
负责加载JRE/lib/ext/*.jar - AppClassLoader:
负责加载在classpath环境变量中的所有类。
3、父类委托机制
父类委托机制如果需要加载一个类,由于父类委托机制,最顶层的父类BootStrap会先查找,如果找不到ExtClassLoader查找,还是找不到AppClassLoader进行查找,再找不到抛异常。
网友评论