美文网首页
【Java基础】注解、类加载器的使用

【Java基础】注解、类加载器的使用

作者: 灰色孤星 | 来源:发表于2018-10-02 16:57 被阅读0次

    源代码: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进行查找,再找不到抛异常。

    相关文章

      网友评论

          本文标题:【Java基础】注解、类加载器的使用

          本文链接:https://www.haomeiwen.com/subject/dabooftx.html