类加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过 加载,连接,初始化三步 来实现对这个类进行初始化。
加载
是指将 class 文件读入内存,并为之创建一个 Class 对象。 任何类被使用时系统都会建立一个 Class 对象。
连接
类加载的时机
创建类的实例
new Person()
访问类的静态变量,或者为静态变量赋值
Integer.MAX_VALUE
调用类的静态方法
Executors.newCachedThreadPool()
初始化某个类的子类
new Person() 。 Person extends Human
直接使用 java.exe 命令来运行某个主类
java HelloWrold
使用反射形式来强制创建某个类或接口对应的 java.lang.Class 对象
Classs.for(“com.enjoyms.Person”)
遵循原则 需要时才加载
类加载器
类加载器负责将 .class 文件加载到内存中,并为之生成对应的 Class 对象。
类加载器的分类
Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责 Java 核心类的加载
比如 System.String 等。在 JDK 中 JRE 的 lib 目录下 rt.jar 文件中
Extension ClassLoader 扩展加载器
负责 JRE 的扩展目录中 jar 包的加载
在 JDK 中 JRE 的 lib 目录下 ext 目录
System ClassLoader 系统类加载器
负责在 JVM 启动时加载来自 java 命令的 class 文件,以及 classpath 环境变量所指定的 jar 包和类路径
比如我们自己写的 class 文件就是这个加载器负责加载
反射
JAVA 反射机器是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
对于任意一个对象,都能通过反射调用它的任意一个方法和属性
这种动态获取信息以及动态调用对象的方法的功能称为 java 语言的反射机制
要想解刨一个类,必须先要获取到该类的字节码文件对象
解刨使用的就是 Class 类中的方法,所以先要获取到每一个字节码文件对应的 Class 类型的对象
通过反射加载类的三种方式
- Object 类的 getClass() 方法,判断两个对象是否是同一字节码文件
- 静态属性 class,锁对象
- Class 类中静态方法 forName() 读取配置文件
演示
先创建一个 Person 类来演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.enjoyms.reflect;
public class Person {
private String name; public int age;
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }
public Person(String name) { this.name = name; } }
|
创建 Main 方法类通过三种不同方式创建:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package com.enjoyms.reflect;
import java.io.BufferedReader; import java.io.FileReader;
public class Main { public static void main(String[] args) throws Exception {
Person person1 = new Person(); Class clz1 = person1.getClass();
Class clz2 = Person.class;
Class clz3 = Class.forName("com.enjoyms.reflect.Person");
System.out.println(clz1.hashCode()); System.out.println(clz2.hashCode()); System.out.println(clz3.hashCode());
String className = "com.enjoyms.reflect.Person"; Class clz = Class.forName(className); FileReader fr = new FileReader("info.txt"); BufferedReader br = new BufferedReader(fr); String className1 = br.readLine(); Class clz11 = Class.forName(className1);
} }
|
通过反射获取构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.enjoyms.reflect;
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException;
public class Main1 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clz = Person.class;
Constructor c1 = clz.getConstructor();
Person person = (Person) c1.newInstance(); System.out.println(person);
Constructor c2 = clz.getConstructor(String.class); Person person1 = (Person) c2.newInstance("小明"); System.out.println(person1);
} }
|
通过反射获取成员属性和设置成员属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| package com.enjoyms.reflect;
import java.lang.reflect.Field;
public class Main3 { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Class clz = Person.class;
Field ageFiled = clz.getField("age"); System.out.println(ageFiled);
Person person = new Person(); ageFiled.set(person,30); System.out.println(person);
Field nameField = clz.getDeclaredField("name"); System.out.println(nameField);
nameField.setAccessible(true); nameField.set(person,"小红"); System.out.println(person);
Object value = nameField.get(person); System.out.println(value);
} }
|
通过反射获取方法,并且越过泛型检查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.enjoyms.reflect;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List;
public class Main2 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List<Integer> list = new ArrayList<Integer>();
list.add(1); list.add(2); list.add(3);
Class clz = list.getClass();
Method method = clz.getMethod("add", Object.class);
method.invoke(list,"hello"); System.out.println(list);
} }
|
通过反射写一个通过的方法,设置对象属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package com.enjoyms.reflect;
import java.lang.reflect.Field;
public class Main4 {
public static void setFieldValue(Object obj, String fieldName, String fieldValue){ Class clz = obj.getClass();
try { Field field = clz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, fieldValue);
} catch (Exception e) { e.printStackTrace(); } } }
|