java--类加载器、反射

 类的加载

当程序要使用某个类时,若是该类还未被加载到内存中,则系统会经过加载,链接,初始化三步来实现对这个类进行初始化。java

 加载数组

就是指将class文件读入内存,并为之建立一个Class对象。安全

任何类被使用时系统都会创建一个Class对象oracle

 链接ide

验证 是否有正确的内部结构,并和其余类协调一致this

准备 负责为类的静态成员分配内存,并设置默认初始化值spa

解析 将类的二进制数据中的符号引用替换为直接引用code

  初始化对象

就是咱们之前讲过的初始化步骤blog

   类初始化时机

1. 建立类的实例

2. 类的静态变量,或者为静态变量赋值

3. 类的静态方法

4. 使用反射方式来强制建立某个类或接口对应的java.lang.Class对象

5. 初始化某个类的子类

6. 直接使用java.exe命令来运行某个主类

     类加载器

 负责将.class文件加载到内存中,并为之生成对应的Class对象。

  虽然咱们不须要关心类加载机制,可是了解这个机制咱们就能更好的理解程序的运行

     类加载器的组成

  Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,负责Java核心类的加载

好比System,String等。在JDK中JRE的lib目录下rt.jar文件中

Extension ClassLoader 扩展类加载器

负责JRE的扩展目录中jar包的加载。

在JDK中JRE的lib目录下ext目录

 System ClassLoader 系统类加载器

    反射

   Class类

代码演示:

复制代码
 1 public class Person {
 2     public String name;
 3     private int age;
 4     public Person(){
 5         System.out.println("公共构造方法");
 6     }
 7     public Person(String name,int age){
 8         this.name=name;
 9         this.age=age;
10         System.out.println("公共有参构造");
11     }
12     private Person(int age,String name){
13         System.out.println("私有有参构造");
14     }
15     public void eat(){
16         System.out.println("公共方法");
17     }
18     public void sleep(String name){
19         System.out.println(name+"公共有参方法");
20     }
21     private void playGames(){
22         System.out.println("私有方法");
23     }
24     @Override
25     public String toString() {
26         return "Person [name=" + name + ", age=" + age + "]";
27     }
28 
29 }
复制代码
复制代码
 1 //获取字节码文件对象的三种方式
 2     public static void method1() throws ClassNotFoundException{
 3         //1.经过对象获取
 4         Person p=new Person();
 5         Class c=p.getClass();
 6         System.out.println(c);
 7         //2.经过类名获取
 8         Class c1=Person.class;
 9         System.out.println(c1);
10         System.out.println(c==c1);
11         System.out.println(c.equals(c1));
12         //3.经过Class类的静态方法forName(包名.类名)获取
13         Class c2=Class.forName("com.oracle.demo03.Person");
14         System.out.println(c2);
15     }
复制代码

   经过反射获取构造方法并使用

复制代码
 1 //获取构造方法
 2     public static void method2() throws Exception{
 3         //获取字节码文件对象
 4         Class c=Class.forName("com.oracle.demo03.Person");
 5         //获取非私有构造方法数组
 6         /*Constructor[] cons=c.getConstructors();
 7         for(Constructor con:cons){
 8             System.out.println(con);
 9         }*/
10     /*    //获取空参构造
11         Constructor con=c.getConstructor();
12         //使用空参构造建立对象
13         Object obj=con.newInstance();
14         Person p=(Person)obj;
15         p.eat();*/
16         //获取有参构造方法并调用
17         /*Constructor con=c.getConstructor(String.class,int.class);
18         Object obj=con.newInstance("张三",18);
19         System.out.println(obj);*/
20         //针对空参构造有一个快速建立对象的方式
21         //1.Person类中必须有空参构造方法
22         //2.空参构造方法必须是public修饰
23         Object obj=c.newInstance();
24         System.out.println(obj);
25     }
复制代码

经过反射方式,获取构造方法,建立对象

1. 获取到Class对象

2. 获取指定的构造方法

3. 经过构造方法类Constructor中的方法,建立对象

public T newInstance(Object... initargs)

经过反射方式,获取私有构造方法,建立对象

经过反射获取成员变量并使用

代码展现:

复制代码
 1     //经过反射获取私有构造---暴力反射  不推荐使用
 2     //它破坏了咱们程序的封装性、安全性
 3     //抢银行方式
 4     public static void method3()throws Exception{
 5         //获取字节码文件对象
 6         Class c=Class.forName("com.oracle.demo03.Person");
 7         //获取全部构造方法
 8         /*Constructor[] cons=c.getDeclaredConstructors();
 9         for(Constructor con:cons){
10             System.out.println(con);
11         }*/
12         //获取私有构造方法并使用
13         Constructor con=c.getDeclaredConstructor(int.class,String.class);
14         //取消Java对个人检查
15         con.setAccessible(true);
16         Object obj=con.newInstance(18,"李四");
17         System.out.println(obj);
18     }
19     public static void method4() throws Exception{
20         //获取字节码文件对象
21         Class c=Class.forName("com.oracle.demo03.Person");
22         Object obj=c.newInstance();
23         //获取公共成员变量并使用
24         Field field=c.getField("name");
25         field.set(obj,"张三");
26         //获取私有成员变量并使用
27         Field f=c.getDeclaredField("age");
28         f.setAccessible(true);
29         f.set(obj, 18);
30         System.out.println(obj);
31         //System.out.println(field.get(obj));
32     }
33     public static void method5() throws Exception{
34         //获取字节码文件对象
35         Class c=Class.forName("com.oracle.demo03.Person");
36         Object obj=c.newInstance();
37         //获取空参的成员方法并运行
38         Method method=c.getMethod("eat");
39         method.invoke(obj);
40         //获取有参成员方法并运行
41         Method method1=c.getMethod("sleep", String.class);
42         method1.invoke(obj, "张三");
43     }
复制代码

    泛型擦除

反射配置文件

复制代码
 1 public class Demo {
 2 
 3     public static void main(String[] args) throws Exception {
 4         //反射配置文件实现
 5         //把咱们要运行的类和方法以键值对的形式写在文本中
 6         //咱们想要运行哪一个类里面的方法 只须要改配置文件便可
 7         /*步骤:
 8          * 1.准备配置文件,键值对
 9          * 2.IO读取配置文件,Reader
10          * 3.将文件中的键值对保存在Properties集合中,键值对就是类和方法名
11          * 4.经过反射获取指定类的class文件对象
12          * 5.经过class文件对象获取指定方法
13          * 6.运行方法
14          * */
15         FileReader fr=new FileReader("src/config.properties");
16         Properties pro=new Properties();
17         pro.load(fr);
18         String className=pro.getProperty("className");
19         String methodName=pro.getProperty("methodName");
20         Class c=Class.forName(className);
21         Object obj=c.newInstance();
22         Method method=c.getMethod(methodName);
23         method.invoke(obj);
24         
25     }
复制代码

配置文件:

 

复制代码
1 #className=com.oracle.demo04.Person
2 #methodName=eat
3 className=com.oracle.demo04.Student
4 methodName=study
5 className=com.oracle.demo04.Worker
6 methodName=work
复制代码
相关文章
相关标签/搜索