一、加载器
* 类的加载器
* 启动类、扩展类、系统类
* 启动类(Bootstrap)负责启动jvm
* 扩展类(Extension)早期,扩展包
* 系统类(System)负责加载系统类路径
* 加载-验证-准备-解析-初始化
* 加载:类加载的一个过程:通过一个类的完全限定查找此类的字节码文件,并利用字节码文件创建一个class文件
* 验证:目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全,主要包含四种:文件格式验证,元数据验证,字节码验证符号引用验证
* 准备:为类变量分配内存并设置该类变量的初始值即0,这里不包含final修饰的static,因为final在编译的时候就分配了注意这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到java堆中
* 解析:将类的二进制数据中的符号引用替换成直接引用。说明一下:符号引用:符号引用是以一组符号来描述所引用的目标,符号可以是任何的字面形式的字面量,只要不会出现冲突能够定位到就行。布局和内存无关。直接引用:是指向目标的指针,偏移量或者能够直接定位的句柄。该引用是和内存中的布局有关的,并且一定加载进来的。
* 初始化:初始化是为类的静态变量赋予正确的初始值,准备阶段和初始化阶段看似有点矛盾,其实是不矛盾的,如果类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行链接的验证这一步骤,验证通过后准备阶段,给a分配内存,因为变量a是static的,所以此时a等于int类型的默认初始值0,即a=0,然后到解析(后面在说),到初始化这一步骤时,才把a的真正的值10赋给a,此时a=10。
@Test
public void test01(){
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//系统类的加载器
//app
System.out.println(systemClassLoader.getName());
//扩展类加载器
//platform
System.out.println(systemClassLoader.getParent().getName());
//启动类加载器
//Cannot invoke "java.lang.ClassLoader.getName()" because the return value of "java.lang.ClassLoader.getParent()" is null
//c/c++编写,底层代码,无法查看
//System.out.println(systemClassLoader.getParent().getParent().getName());
}
类的输出:以下五种
@Test
public void test02(){
//类名.class
Class<Emp> empClass = Emp.class;
//class com.lihaozhe.enmudemo.Emp
System.out.println(empClass);
//com.lihaozhe.enmudemo.Emp
System.out.println(empClass.getName());
//Emp
System.out.println(empClass.getSimpleName());
}
@Test
public void test03(){
//实例化对象,实例化时会调用静态代码块
Emp emp = new Emp();
Class<? extends Emp> empClass = emp.getClass();
System.out.println(empClass);
System.out.println(empClass.getName());
System.out.println(empClass.getSimpleName() );
}
@Test
public void test04(){
//Class.forName("全名"),会调用静态代码块
try {
Class<?> empClass = Class.forName("com.lihaozhe.enmudemo.Emp");
System.out.println(empClass);
System.out.println(empClass.getName());
System.out.println(empClass.getSimpleName() );
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Test
public void test05(){
//通过类的加载器
ClassLoader classLoader = Person.class.getClassLoader();
try {
Class<?> loadClass = classLoader.loadClass("com.lihaozhe.enmudemo.Emp");
System.out.println(loadClass);
System.out.println(loadClass.getName());
System.out.println(loadClass.getSimpleName() );
}catch (ClassNotFoundException e){
throw new RuntimeException(e);
}
}
@Test
public void test06(){
//基本数据类型
Class<Integer> type = Integer.TYPE;
System.out.println(type);
System.out.println(type.getName());
System.out.println(type.getSimpleName());
}
二、反射
1、反射之类的调用
(1)
@Test
public void test01() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
// 2、使用该类的Class对象将该类实例化(java8之前)
try {
Emp emp = empClass.newInstance();
emp.setName("李昊哲");
System.out.println(emp.getName());
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
(2)
@Test
public void test02() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
try {
// 2 获取该Class对象的构造方法
Constructor<Emp> constructor = empClass.getConstructor();
// 3、使用该类的构造方法将该类实例化(java8+)
Emp emp = constructor.newInstance();
emp.setName("李昊哲");
System.out.println(emp.getName());
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
throw new RuntimeException(e);
}
}
(3)
@Test
public void test03() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
try {
// 2 获取该Class对象的构造方法
Constructor<Emp> constructor = empClass.getConstructor(String.class, Integer.class, Integer.class);
// 3、使用该类的构造方法将该类实例化(java8+)
Emp emp = constructor.newInstance("李昊哲", 18, 1);
System.out.println(emp);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
throw new RuntimeException(e);
}
}
2、反射之方法调用
(1)
@Test
public void test04() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
try {
// 2、根据方法名字获取该类中的方法
Method method = empClass.getMethod("haha");
// 3、执行该类中的方法
method.invoke(empClass);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
(2)
@Test
public void test05() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
try {
// 2、根据方法名字获取该类中的方法
Method method = empClass.getMethod("heihei");
// 3 获取该Class对象的构造方法
Constructor<Emp> constructor = empClass.getConstructor();
// 4、使用该类的构造方法将该类实例化(java8+)
Emp emp = constructor.newInstance();
// 5、执行该类中的方法
method.invoke(emp);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
throw new RuntimeException(e);
}
}
(3)
@Test
public void test06() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
try {
// 2、根据方法名字获取该类中的方法
Method method = empClass.getDeclaredMethod("hehe");
// 3 获取该Class对象的构造方法
Constructor<Emp> constructor = empClass.getConstructor();
// 4、使用该类的构造方法将该类实例化(java8+)
Emp emp = constructor.newInstance();
// 5、设置方法可以访问权限
method.setAccessible(true);
// 6、执行该类中的方法
method.invoke(emp);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
throw new RuntimeException(e);
}
}
(4)
@Test
public void test07() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
try {
// 2、根据方法名字获取该类中的方法
Method method = empClass.getDeclaredMethod("sum", Integer.class, Integer.class);
// 3 获取该Class对象的构造方法
Constructor<Emp> constructor = empClass.getConstructor();
// 4、使用该类的构造方法将该类实例化(java8+)
Emp emp = constructor.newInstance();
// 5、设置方法可以访问权限
method.setAccessible(true);
// 6、执行该类中的方法
Integer num = (Integer) method.invoke(emp, 10, 20);
System.out.println(num);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
throw new RuntimeException(e);
}
}
3、反射之属性
(1)
@Test
public void test08() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
try {
// 2、获取该Class对象的构造方法
Constructor<Emp> constructor = empClass.getConstructor();
// 3、使用该类的构造方法将该类实例化(java8+)
Emp emp = constructor.newInstance();
// 4、 获取私有成员变量
Field nameField = empClass.getDeclaredField("name");
Field ageField = empClass.getDeclaredField("age");
Field genderField = empClass.getDeclaredField("gender");
// 5、设置属性可以访问权限
nameField.setAccessible(true);
ageField.setAccessible(true);
genderField.setAccessible(true);
// 6、 给属性赋值
nameField.set(emp, "李昊哲");
ageField.set(emp, 18);
genderField.set(emp, 1);
// 7、 读取属性值
String name = (String) nameField.get(emp);
System.out.println(name);
Integer age = (Integer) ageField.get(emp);
System.out.println(age);
Integer gender = (Integer) genderField.get(emp);
System.out.println(gender);
// 获取所有属性
Field[] declaredFields = empClass.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
System.out.println(field.get(emp));
}
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException |
NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
(2)
@Test
public void test09() {
// 1、获取该类的Class对象
Class<Emp> empClass = Emp.class;
try {
// 2、获取该Class对象的构造方法
Constructor<Emp> constructor = empClass.getConstructor();
// 3、使用该类的构造方法将该类实例化(java8+)
Emp emp = constructor.newInstance();
// 4、 获取私有成员变量
Field nameField = empClass.getDeclaredField("name");
Field genderField = empClass.getDeclaredField("gender");
// 5、设置属性可以访问权限
nameField.setAccessible(true);
genderField.setAccessible(true);
// 6、 给属性赋值
nameField.set(emp, "李昊哲");
genderField.set(emp, 1);
// 7、 读取属性值
String name = (String) nameField.get(emp);
System.out.println(name);
Integer gender = (Integer) genderField.get(emp);
System.out.println(gender);
// 获取所有属性
Field[] declaredFields = empClass.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
if (field.get(emp) != null ) {
System.out.println(field.get(emp));
}
}
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException |
NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
附:反射代码演示使用的类
public class Emp {
private String name;
private Integer age;
private Integer gender;
static {
System.out.println("我是静态代码块");
}
{
System.out.println("我是构造代码块");
}
public Emp() {
System.out.println("我是无参构造方法");
}
public Emp(String name, Integer age, Integer gender) {
System.out.println("我是有参构造方法");
this.name = name;
this.age = age;
this.gender = gender;
}
public static void haha() {
System.out.println("我是public static修饰的方法");
System.out.println("仰天长啸");
}
public void heihei() {
System.out.println("我是public修饰的方法");
System.out.println("嘿嘿嘿");
}
private void hehe() {
System.out.println("我是private修饰的方法");
System.out.println("粉面含春威不露,丹唇未起笑先闻");
}
public Integer sum(Integer a, Integer b) {
return a + b;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public int getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
}