类加载器

类加载器

类加载内存分析

public class Test04 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.a);//20
    }
}
class A{
    //第一个执行
    static {
        System.out.println("静态代码块初始化");
        int a = 10;
    }
    //第三个执行
        static int a = 20;

    //第二个执行
    public A(){
        System.out.println("无参构造");
        int a = 30;
    }
}

在这里插入图片描述

public class Test05 {
    static {
        System.out.println("Main所在的类加载");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //1、主动引用
        //Son son = new Son();//由于父类没有初始化,所以在调用子类的时候会先初始化父类

        //2、反射也会产生主动引用
        //Class.forName("com.yjj.reflection.Son");//先主动引用然后在反射,所以浪费了资源

        //以下不会发生类的初始化
        
        //3、子类调用父类静态的东西,子类不会被加载
        //System.out.println(Son.b);//只是调用了Father的b,相当于Father.b

        //4、通过数组也不会加载,只加载main类
//        Son[] sons = new Son[5];
//        Father[] fathers = new Father[10];

        //5、调用常量也不会加载常量所在的类
        System.out.println(Son.M);//常量在链接阶段就存入调用类的常量池中了
    }

}
class Father {
    static int b = 2;

    static {
        System.out.println("父类被加载");
    }
}
class Son extends Father{
    static {
        System.out.println("子类被加载");
    }
    static final int M = 1;//常量
}

类加载器的作用

  • 将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口
  • 类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,他将维持加载(缓存)一段时间。JVM垃圾回收机制可以回收这些Class对象
  • Java核心类库–rt.jar包
public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException {

        //获取系统类加载器--->用户加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);//AppClassLoader

        //获取系统类加载器的父类加载器--->扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);//ExtClassLoader

        //获取扩展类加载器的父类加载器--->根加载器(C/C++编写),Java无法直接访问
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);//null

        //测试当前类是那个加载器加载的
        ClassLoader classLoader = Class.forName("com.yjj.reflection.Test06").getClassLoader();
        System.out.println(classLoader);

        //测试JDK内置的类Object类是谁加载的
        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader1);//根加载器,null

        //获得系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));
        

/*
C:\Program Files\Java\jdk1.8.0_271\jre\lib\charsets.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\deploy.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\access-bridge-64.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\cldrdata.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\dnsns.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\jaccess.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\jfxrt.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\localedata.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\nashorn.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunec.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunjce_provider.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunmscapi.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunpkcs11.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\zipfs.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\javaws.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\jce.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\jfr.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\jfxswt.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\jsse.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\management-agent.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\plugin.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\resources.jar;
C:\Program Files\Java\jdk1.8.0_271\jre\lib\rt.jar;      //所有写的东西都在这里
D:\IDEA\Java\out\production\基础语法;
D:\IDEA\Java\lib\kotlin-stdlib.jar;
D:\IDEA\Java\lib\kotlin-reflect.jar;
D:\IDEA\Java\lib\kotlin-test.jar;
D:\IDEA\Java\lib\kotlin-stdlib-jdk7.jar;
D:\IDEA\Java\lib\kotlin-stdlib-jdk8.jar;
D:\IDEA\Java\基础语法\src\com\yjj\lib\commons-io-2.8.0.jar;
D:\IDEA\IntelliJ IDEA Community Edition 2020.3.1\lib\idea_rt.jar

 */

    }
}
  • 双亲委派机制:当要进行加载一个类时,系统会在加载器中逐层寻找是否和系统类相同名字的类。防止写了一个和系统类名相同的类,增加了安全性

获取类的信息

public class User {
    private String name;
    private int age;

    public User(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;
    }

    private void test(){ }
}
=======================================================================
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test07 {
    public static void main(String[] args) throws Exception {
        Class c1 = Class.forName("com.yjj.reflection.User");

        //获得类的属性
        Field[] fields = c1.getFields();//只能获取public属性
        for (Field field : fields) {
            System.out.println(field);//什么都没有
        }

        fields = c1.getDeclaredFields();//可以获取全部属性
        for (Field field : fields) {
            System.out.println(field);
        }

        //获取指定属性
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        //获得类的方法
        //Methods所有方法,Method指定方法
        Method[] methods = c1.getMethods();//获得本类和父类的所有public方法
        for (Method method : methods) {
            System.out.println("public的方法:"+method);
        }

        methods = c1.getDeclaredMethods();//获得本类的所有方法
        for (Method method : methods) {
            System.out.println("getDeclaredMethods的方法:"+method);
        }

        //因为方法涉及重载,需要参数系统才能判断出来你要的是那个方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        //获得构造器和前面差不多

        //获得指定构造器,比如有参构造
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class);
        System.out.println("指定:"+declaredConstructor);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值