Java 类加载机制和反射机制
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
开发工具与关键技术:
作者:陈剑波
撰写时间:2019年08月08日
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
一、Java类加载机制
jvm把class文件加载到内存,并对数据进行校验、解析和初始化,最终形成jvm可以直接使用的java类型的过程。
Java类的生命周期:加载-》验证-》准备-》解析-》初始化-》使用-》卸载
(1)加载:
将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。
(2)链接: 将java类的二进制代码合并到jvm的运行状态之中的过程。
1. 验证:确保加载的类信息符合jvm规范,没有安全方面的问题。
2. 准备:正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。
3.解析:虚拟机常量池内的符号引用替换为直接引用的过程。(比如String s ="aaa",转化为 s的地址指向“aaa”的地址)
(3)初始化:
初始化阶段是执行类构造器方法的过程。类构造器方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的。
1.当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先初
始化其父类的初始化。
2.虚拟机会保证一个类的构造器方法在多线程环境中被正确加锁和同步。
3.当访问一个java类的静态域时,只有真正声明这个静态变量的类才会被初始
化。
示例代码:
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* @author KO.ZERO 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
* 对于任意一个对象,都能够调用它的任意一个方法和属性;
*/
public class ReflectDemo implements Serializable {
public static void main(String[] args) throws Exception {
// 通过一个对象获得完整的包名和类名
ReflectDemo demo = new ReflectDemo();
// getClass():返回此对象的运行时类。返回的类对象是由所表示类的静态同步方法锁定的对象。
// getName():返回由这个类对象表示的实体(类、接口、数组类、基本类型或void)的名称,作为字符串。
System.out.println("获得对象完整的包名和类名" + demo.getClass().getName());
// 实例化Class类对象
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;
class1 = Class.forName("com.ko2.demo.ReflectDemo");
class2 = new ReflectDemo().getClass();
class3 = ReflectDemo.class;
Class<?> class4 = ReflectDemo.class.getClassLoader().loadClass(
"com.ko2.demo.ReflectDemo");
System.out.println("类名:" + class1.getName());
System.out.println("类名:" + class2.getName());
System.out.println("类名:" + class3.getName());
System.out.println("类名:" + class4.getName());
// 获取对象的父类与实现的接口
// 取得父类
// getSuperclass():返回表示该类表示的实体(类、接口、基本类型或void)的超类。如果该类表示对象类、接口、基本
// 类型或void,则返回null。如果此对象表示数组类,则返回表示对象类的类对象。
Class<?> parentClass = class1.getSuperclass();
System.out.println("class1的父类为:" + parentClass.getName());
// 获取所有的接口
Class<?> intes[] = class1.getInterfaces();
System.out.println("class1实现的接口有:");
for (int i = 0; i < intes.length; i++) {
System.out.println((i + 1) + ":" + intes[i].getName());
}
// 通过反射机制调用某个类的方法
// 调用TestReflect类中的reflect1方法
Method method = class1.getMethod("reflect1");
method.invoke(class1.newInstance());
// Java 反射机制 - 调用某个类的方法1.
// 调用TestReflect的reflect2方法
method = class1.getMethod("reflect2", int.class, String.class);
// Java 反射机制 - 调用某个类的方法2.
method.invoke(class1.newInstance(), 24, "列小龙");
//获取某个类的全部属性
Class<?> class6 = Class.forName("com.ko2.demo.Person");
// 取得本类的全部属性
Field[] field = class6.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 权限修饰符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = field[i].getType();
System.out.println(priv + " " + type.getName() + " "
+ field[i].getName() + ";");
}
//获取某个类的全部方法
Method method2[] = class1.getMethods();
for (int i = 0; i < method2.length; ++i) {
Class<?> returnType = method2[i].getReturnType();
Class<?> para[] = method2[i].getParameterTypes();
int temp = method2[i].getModifiers();
System.out.print(Modifier.toString(temp) + " ");
System.out.print(returnType.getName() + " ");
System.out.print(method2[i].getName() + " ");
System.out.print("(");
for (int j = 0; j < para.length; ++j) {
System.out.print(para[j].getName() + " " + "arg " + j);
if (j < para.length - 1) {
System.out.print(",");
}
}
//getExceptionTypes():返回一个类对象数组,该数组表示由该方法对象表示的底层方法声明要抛出的异常的类型。
//如果方法在其抛出子句中声明没有异常,则返回长度为0的数组。
Class<?> exce[] = method2[i].getExceptionTypes();
if (exce.length > 0) {
System.out.print(") throws ");
for (int k = 0; k < exce.length; ++k) {
System.out.print(exce[k].getName() + " ");
if (k < exce.length - 1) {
System.out.print(",");
}
}
} else {
System.out.print(")");
}
System.out.println();
}
}
public void reflect1() {
System.out.println("Java 反射机制 - 调用某个类的方法1.");
}
public void reflect2(int age, String name) {
System.out.println("Java 反射机制 - 调用某个类的方法2.");
System.out.println("age -> " + age + ". name -> " + name);
}
}
class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) throws Exception {
if (age < 0 || age > 120) {
System.out.println("年龄不符合要求");
return;
} else {
this.age = age;
}
}
}
运行结果:
获得对象完整的包名和类名com.ko2.demo.ReflectDemo
类名:com.ko2.demo.ReflectDemo
类名:com.ko2.demo.ReflectDemo
类名:com.ko2.demo.ReflectDemo
类名:com.ko2.demo.ReflectDemo
class1的父类为:java.lang.Object
class1实现的接口有:
1:java.io.Serializable
Java 反射机制 - 调用某个类的方法1.
Java 反射机制 - 调用某个类的方法2.
age -> 24. name -> 列小龙
private java.lang.String name;
private int age;
public static void main ([Ljava.lang.String; arg 0) throws java.lang.Exception
public void reflect1 ()
public void reflect2 (int arg 0,java.lang.String arg 1)
public final void wait (long arg 0,int arg 1) throws java.lang.InterruptedException
public final native void wait (long arg 0) throws java.lang.InterruptedException
public final void wait () throws java.lang.InterruptedException
public boolean equals (java.lang.Object arg 0)
public java.lang.String toString ()
public native int hashCode ()
public final native java.lang.Class getClass ()
public final native void notify ()
public final native void notifyAll ()