java代码运行的三个阶段

 第一阶段:源代码编译为了字节码(.class文件)
 第二阶段:就是类加载器将字节码文件加载到内存中
 第三阶段:程序运行时
类加载
将 class 文件读取到内存中的过程,称为类加载
 class 文件的加载由 ClassLoader 完成,称为类加载器
三种类型:
- BootstrapClassLoader:启动类加载器,用C++编写的,由JVM在启动时加载初始化的,主要负责加载 /jre/lib 下的类
- ExtClassLoader:扩展类,由BootstrapClassLoader加载,主要负责加载 /jre/lib/ext 下的类
- AppClassLoader:系统类加载器,由BootstrapClassLoader加载,主要负责加载 classpath下的类
可以使用 类名.class.getClassLoader() 获取当前类的类加载器。
 class 文件读取到内存中会被封装为 java.lang.Class 类的对象
反射
在程序运行状态中:
- 对于任意一个类,都能够获取这个类的所以属性或方法。
- 对于任意一个对象,都能够调用这个对象的任意属性或方法。
这种运行时动态获取信息以及动态调用对象方法的功能称为反射 reflection。
j
相关API
反射相关的API都在 java.lang 包中
| 类接口名 | 作用 | 
|---|---|
| Class | 表示运行中的类或接口 | 
| Field | 表示类中的属性 | 
| Method | 表示类中的方法 | 
| Constructor | 表示类中的构造方法 | 
| Package | 表示类所属的包 | 
| Modifier | 表示修饰符 | 
| Annotation | 表示注解 | 
操作class对象
简介
运行中的 class 文件通过 Class 对象来表示的
- Class 对象是在类加载时由 JVM 自动创建的,一个类在 JVM 中只会有一个 Class 对象
- Class 类没有公共构造方法,不能自己创建 Class 对象,但可以获取其示例并进行操作。
Class是反射的核心类,要想操作类中的属性和方法,都必须从获取 Class 对象开始。
获取Class对象
三种方式:
 1、调用 Class 类的 forName() 静态方法
 2、调用类的 class 属性
 3、调用对象的 getClass() 方法

 第一个阶段,字节码文件(.class文件)没有进内存,需要手动的加载进内存,生成 Class 类对象,所以使用 Class.forName("com.xxx.xx")。
 第二个阶段,字节码文件(.class文件)已经加载到内存了,也就是说这个对象已经有了,所以不需要加载了只需要获取,这时候知道类名了(如上的Persion),所以使用 类名.class。
 第三个阶段,已经知道有 p = new Persion p 对象了,p 对象是继承 Object 类的,Object 类就有 getClass() 方法
举例
package cn.xxx.reflect;
import cn.xxx.domain.Person;
import cn.xxx.domain.Student;
public class ReflectDemo1 {
    public static void main(String[] args) throws Exception {
        //1.Class.forName("全类名")
        Class cls1 = Class.forName("cn.xxx.domain.Person");
        System.out.println(cls1);
        //2.类名.class
        Class cls2 = Person.class;
        System.out.println(cls2);
        //3.对象.getClass()
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);
        //== 比较三个对象
        System.out.println(cls1 == cls2);//true
        System.out.println(cls1 == cls3);//true
        // 得出结论:同一个字节码文件(.class)在一次程序运行过程中,只会被加载一次,无论通过那种方式获取的Class对象都是同一个。
        Class c = Student.class;
        System.out.println(c == cls1); // false
    }
}
三种方式使用场景:
 方式一:多用于配置文件,将类名定义在配置文件中。读取文件,加载类。
 方式二:多用于参数的传递
 方式三:多用于对象的获取字节码的方式
Class对象常用方法
上一步我们获取到了 Class 对象,接下来我们看看Class对象有哪些方法
以下例子中的 Persion 对象是这个
package cn.xxx.domain;
public class Person {
    private String name;
    private int age;
    public String a;
    protected String b;
    String c;
    private String d;
    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 +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
    public void eat(){
        System.out.println("eat...");
    }
    public void eat(String food){
        System.out.println("eat..."+food);
    }
}
操作Field
获取成员变量们
-  Field[] getFields()
-  Field getField(String name)
-  Field[] getDeclaredFields()
-  Field getDeclaredField(String name)
注意:以上带 Declared 的,表示忽略修饰符,比如 getFields 可以获取 public 修饰符的成员,但是 getDeclaredFields 不管公有私有都能获取到。
package cn.xxx.reflect;
import cn.xxx.domain.Person;
import java.lang.reflect.Field;
public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class personClass = Person.class;
        /*
             1. 获取成员变量们
                 * Field[] getFields()
                 * Field getField(String name)
                 * Field[] getDeclaredFields()
                 * Field getDeclaredField(String name)
         */
        //1.Field[] getFields()获取所有public修饰的成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("------------");
        //2.Field getField(String name)
        Field a = personClass.getField("a");
        //获取成员变量a 的值
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);
        //设置a的值
        a.set(p,"张三");
        System.out.println(p);
        System.out.println("===================");
        //Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //Field getDeclaredField(String name)
        Field d = personClass.getDeclaredField("d");
        //忽略访问权限修饰符的安全检查
        d.setAccessible(true);//暴力反射
        Object value2 = d.get(p);
        System.out.println(value2);
    }
}
操作Constructor
获取构造方法们
-  Constructor<?>[] getConstructors()
-  Constructor<T> getConstructor(类<?>... parameterTypes)
-  Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
-  Constructor<?>[] getDeclaredConstructors()
package cn.xxx.reflect;
import cn.xxx.domain.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class personClass = Person.class;
        
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //创建对象
        Object person = constructor.newInstance("张三", 23);
        System.out.println(person);
        System.out.println("----------");
        Constructor constructor1 = personClass.getConstructor();
        System.out.println(constructor1);
        //创建对象
        Object person1 = constructor1.newInstance();
        System.out.println(person1);
        Object o = personClass.newInstance();
        System.out.println(o);
        //constructor1.setAccessible(true);
    }
}
操作Method
获取成员方法们:
-  Method[] getMethods()
-  Method getMethod(String name, 类<?>... parameterTypes)
-  Method[] getDeclaredMethods()
-  Method getDeclaredMethod(String name, 类<?>... parameterTypes)
package cn.xxx.reflect;
import cn.xxx.domain.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ReflectDemo4 {
    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class personClass = Person.class;
        //获取指定名称的方法
        Method eat_method = personClass.getMethod("eat");
        Person p = new Person();
        //执行方法
        eat_method.invoke(p);
        Method eat_method2 = personClass.getMethod("eat", String.class);
        //执行方法
        eat_method2.invoke(p,"饭");
        System.out.println("-----------------");
        //获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            String name = method.getName();
            System.out.println(name);
            //method.setAccessible(true);
        }
    }
}
操作类名
获取类名
 * String getName()
package cn.xxx.reflect;
import cn.xxx.domain.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ReflectDemo5 {
    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class personClass = Person.class;
        //获取类名
        String className = personClass.getName();
        System.out.println(className);//cn.xxx.domain.Person
    }
}
操作注解
对于生命周期为运行期间(RUNTIME)的注解。
// 获取类上的注解
Class cls = Student.class;
// 获取所有注解
Annotation[] annotation = cls.getAnnotation();
// 获取属性上的注解
// 获取方法上的注解
...
相关文档
java8 API









![Java并发编程(六)线程池[Executor体系]](https://img-blog.csdnimg.cn/c949d95312e44bc99e8a0d016a79a218.png)








