类加载器、反射总结

类加载器

1.jvm用什么方式把class文件加载到内存中?

2.默认类加载器有哪几个,它们的关系是什么; 默认父加载器能不能加载子类加载器的Class

1.概述:
​ 在jvm中,负责将本地上的class文件加载到内存的对象

2.分类:

1. BootstrapClassLoader 根类加载器-->C语言写的,我们获取不到
      ​	也被称为引导类加载器,负责Java核心类的加载
      ​	比如System,String等。
        jre/lib/rt.jar下的类都是核心类 
2. ExtClassLoader 扩展类加载器
      ​	负责JRE的扩展目录中jar包的加载。
      ​	在JDK中JRE的lib目录下ext目录
3. AppClassLoader 系统类加载器
      ​	负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包(第三方jar包)和类路径。或者自定义的类
      
关联:   AppClassLoader的父加载器是ExtClassLoader
        ExtClassLoader的父加载器是BootstrapClassLoader
        但是他们不是子父类继承关系,他们有一个共同的爹-->ClassLoader

双亲委派作用

       假如:ext和boot都不加载,app才会自己加载
           class Test{
    
    
               new Person()
           }
a.AppClassLoader负责加载Test,然后按道理来讲Person也是由AppClassLoader加载到内存
  但是App先不加载,先去找ExtClassLoader,Ext不负责加载自定义类,Ext就去找Boot
  但是Boot只负责加载核心类,所以Boot也不加载
  
b.最后App看两个双亲不加载,自己就加载了Person
              
 5.双亲委派作用:
    能够让Class类加载一次
    创建一个Class对象

/*
	类名.class.getClassLorder()这个类的加载器
 	ClassLorder类的方法 getParent()返回父加载器
*/0
public class ClassLoader {
    
    
	
	@Test
	public void classLorder(){
    
    
		//三个类加载器的关系
		//父子关系
		ClassLoader c1 = ClassLoader.class.getClassLoader();
		System.out.println(c1);
		
		ClassLoader c2 = c1.getParent();
		System.out.println(c2);
		
		ClassLoader c3 = c2.getParent();
		System.out.println(c3);
	}
	
    //获取AppClassLoader 系统类加载器
	@Test
	public void app(){
    
    
        //ClassLoader为本类类名
		ClassLoader c1 = ClassLoader.class.getClassLoader();
		System.out.println(c1);
	}
	
    //获取ExtClassLoader 扩展类加载器
	@Test
	public void ext(){
    
    
		ClassLoader c1 = DNSNameService.class.getClassLoader();
		System.out.println(c1);
	}
	 
    //BootstrapClassLoader 根类加载器
	@Test
	public void boot(){
    
    
		//引导类加载器,不是类,JVM内部,返回值null
		ClassLoader cl = String.class.getClassLoader();
		System.out.println(cl);
	}
}

八:反射

根据JVM创建的Class对象去操作、解析Class对象中的成员,让代码灵活性强、扩展性强。

获取Class对象的三种方式:
      Class.forName(类的全限定名)
      类名.Class
      对象.getClass()

   Class文件加载几次?
   Class对象又创建几次?

   答案:1-->由于类加载器的加载机制(双亲委派-->全盘负责委托机制)
       
三种方式谁最常用:
   forName最常用:扩展性最好,灵活性最高
   因为:forName方法参数为一个字符串,将来我们可以将字符串放在文件中,然后用IO读取
       这个字符串,然后放在forName方法中,这样,我想获取不同的Class对象,直接改文件就可以了
       不用修改源代码
       
public class Person {
    
    
    private String name;
    private int age;

    public Person() {
    
    
    }

    public Person(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    private Person(String name){
    
    
        this.name = name;
        System.out.println("我是私有的构造");
    }
    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 name+"..."+age;
    }
}
//测试类
public class Test01 {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
        //每个数据类型,不管基本还是引用数据类型,jvm都赋予了这个类型一个静态属性,名字叫class
        Class aClass = Person.class;
         
        Class aClass1 = Class.forName("cn.itcast.day15.class02.Person");

        //Object类中的getClass方法
        Person person = new Person();
        Class aClass2 = person.getClass();

        System.out.println(aClass==aClass1);
        System.out.println(aClass==aClass2);
    }
}

获取Class对象的构造方法

 获取Class对象中的构造:
      1. Constructor[] getConstructors()
   	     获取所有的public修饰的构造方法

      2. Constructor getConstructor(Class... parameterTypes)
         根据参数类型获取构造方法对象,只能获得public修饰的构造方法。

         如果只获取空参构造,getConstructor()

      3.根据获取出来的构造方法对象,创建对象
         T newInstance(Object... initargs)

         如果new无参构造,参数不用写
public class Test02_Constructor {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //获取Person的class对象
        Class aClass = Class.forName("cn.itcast.day15.class02.Person");
        method02_Constructor(aClass);
        method03_ConstructorVar(aClass);
    }

    获取有参构造
    private static void method03_ConstructorVar(Class aClass)throws Exception {
    
    
        //获取有参构造
        Constructor constructor = aClass.getConstructor(String.class, int.class);
        //创建对象
        Object o = constructor.newInstance("柳岩", 36);//Person person = new Person("柳岩", 36)
        System.out.println(o);
    }


    //获取空参构造
    public static void method02_Constructor(Class aClass) throws Exception{
    
    
        //获取空参构造对象
        Constructor constructor = aClass.getConstructor();
        Object o = constructor.newInstance();//Person person = new Person()
        System.out.println(o);
    }

    //获取类中所有的public的构造方法
    public static Class method01_Constructors(Class aClass) throws ClassNotFoundException {
    
    

        //获取Person的Class对象中的所有构造
        Constructor[] constructors = aClass.getConstructors();
        //遍历
        for (Constructor constructor : constructors) {
    
    
            System.out.println(constructor);
        }
        return aClass;
    }
}



猜你喜欢

转载自blog.csdn.net/weixin_47785112/article/details/106887156
今日推荐