Java---JUnita、注解与类加载器详解以及实例(3)

简介: Java---JUnita、注解与类加载器详解以及实例

如何读取注解

要读取注解的内容,就需要使用反射的技术。

注意:要想使用反射得到注释信息,必须用@Retention(RetentionPolicy.RUNTIME)进行注解。

    /**
     * 分别读取类上的@MyAnno注解 和  方法上的@MyAnno注解
     */
    @Test
    public void readAnno(){
        //※※注意:MyAnno注解定义时,必须指定它的保持性为 RUNTIME,否则下面是读取不出注解的
        //以下方式是读取“声明在类上的”MyAnno注解
        Class c = UserModel.class;
        //boolean boo = c.isAnnotationPresent(cn.hncu.anno.MyAnno.class);
        //boolean boo = c.isAnnotationPresent(MyAnno.class);
        boolean boo = (c.getAnnotation(MyAnno.class)!=null);
        System.out.println(boo);
        //以下方式是读取“声明在方法上的”MyAnno注解
        Method ms[] = c.getDeclaredMethods();
        for(Method m:ms){
            if(m.isAnnotationPresent(MyAnno.class)){
                System.out.println(m.getName()+"方法上有@MyAnno注解");
            }
        }
    }


结果:


true
getAge方法上有@MyAnno注解
getId方法上有@MyAnno注解


类加载器


Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:

BootStrap, ExtClassLoader, AppClassLoader
    @Test
    public void systemLoaderDemo(){
        ClassLoader loader = Person.class.getClassLoader();
        System.out.println(loader);//AppClassLoader
        loader = loader.getParent();
        System.out.println(loader);//ExtClassLoader
        loader = loader.getParent();
        System.out.println(loader);//null
    }


image.png

因为BootStrap是最底层,用C写的,我们不能访问到,我们没有权限,所以输出就是null了。


类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。


Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载。


image.png


☆类加载器的委托机制


通过API认识ClassLoader类


当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?


首先当前线程的类加载器去加载线程中的第一个类。如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。


还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。


每个类加载器加载类时,又先委托给其上级类加载器。当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?

对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的aa.jar包中后,运行结果为ExtClassLoader的原因。


演示不是classpath下的类,系统类加载器是无法加载的

Person类:

package cn.hncu;
/**
 * 
 * @author 陈浩翔
 *
 * @version 1.0  2016-5-4
 */
public class Person {
    private String name;
    private int age;
    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
    @Test
    public void loaderLocalClassDemo() throws ReflectiveOperationException{
        Class c = Class.forName("cn.hncu.Person");
        System.out.println(c);
        Object obj = c.newInstance();
        System.out.println(obj);
    }

运行结果:


class cn.hncu.Person

Person [name=null, age=0]


再看:

我把Person.class移到d:\cn\hncu


//不是classpath下的类,系统类加载器是无法加载的---如果要加载,得自己写类加载器
@Test
    public void loaderRemoteClassDemo() throws ReflectiveOperationException{
        Class c = Class.forName("d:\\cn\\hncu\\Person.class");
        System.out.println(c);
        Object obj = c.newInstance();
        System.out.println(obj);
    }

结果:

image.png

挂了,不能运行了。


因为没有配置classpath。


对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的aa.jar包中后,运行结果为ExtClassLoader



image.png

必须是压.class文件,不要压缩.java文件。!!!!

package cn.hncu;
/**
 * 
 * @author 陈浩翔
 *
 * @version 1.0  2016-5-4
 */
public class LoaderDemo {
    public static void main(String[] args) {
        LoaderDemo a = new LoaderDemo();
        System.out.println(a);
    }
    @Override
    public String toString() {
        return "随便演示。。。chx";
    }
}

先按照这个命令打包这个.java

image.png

image.png

image.png

package cn.hncu;
/**
 * 
 * @author 陈浩翔
 *
 * @version 1.0  2016-5-4
 */
public class LoaderDemo {
    public static void main(String[] args) {
        LoaderDemo a = new LoaderDemo();
        System.out.println(a);
    }
    @Override
    public String toString() {
        return "湖南城院。。。随便演示...chx";
    }
    //改了没用。已经不会运行这里的代码了。
}

结果:

image.png

image.png

对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的aa.jar包中后,运行结果还是为ExtClassLoader。


也就是那三层从上到下,如果上面已经有那个类了,就不会运行下面的那个类:

BootStrap—>ExtClassLoader—>AppClassLoader(System classLoader)


大家再看看这个图,是不是感觉容易理解一些了:


image.png

目录
相关文章
|
4天前
|
Java 编译器 程序员
java注解浅述
java注解浅述
12 1
|
4天前
|
Java
java中递归实例
java中递归实例
18 0
|
3天前
|
ARouter Java
Java注解之编译时注解
Java注解之编译时注解
16 3
|
4天前
|
Java
【Java开发指南 | 第九篇】访问实例变量和方法、继承、接口
【Java开发指南 | 第九篇】访问实例变量和方法、继承、接口
14 4
|
4天前
|
Java 编译器 开发者
Java一分钟之-Java注解的理解与应用
【5月更文挑战第12天】本文介绍了Java注解的基础知识和常见应用,包括定义、应用和解析注解。注解在编译检查、框架集成和代码生成等方面发挥重要作用。文章讨论了两个易错点:混淆保留策略和注解参数类型限制,并提供了避免策略。提醒开发者避免过度使用注解,以保持代码清晰。理解并恰当使用注解能提升代码质量。
13 3
|
4天前
|
Java API Python
java注解
java注解
|
4天前
|
JSON 前端开发 Java
【JAVA进阶篇教学】第七篇:Spring中常用注解
【JAVA进阶篇教学】第七篇:Spring中常用注解
|
4天前
|
Java
代码实例演示Java字符串与输入流互转
代码实例演示Java字符串与输入流互转
|
4天前
|
IDE Java 数据库连接
Lombok注解大全
这些是Lombok中的一些常见注解,它们可以显著减少Java代码中的冗余代码,提高代码的可读性和可维护性。不过,在使用Lombok之前,请确保你的开发环境已经配置好支持Lombok,通常需要安装相应的插件或进行设置以使IDE(如Eclipse、IntelliJ IDEA)能够正确解析Lombok注解。
27 2
|
4天前
|
Java 编译器 Android开发
Java注解你知多少?
Java注解你知多少?
13 1