1.目的是为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。2.包括:文件格式验证(是否以魔数 oxcafebabe 开头)、元数据验证、字节码验证和符号引用验证 3.可以考虑使用-Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
JVM 会在该阶段对静态变量,分配内存并初始化(对应数据类型的默认初始值如 0、0L、null、false 等)。这些变量所使用的内存都将在方法区中进行分配
/** * @author LeeZhi * @version 1.0 * 我们说明一个类加载的连接阶段-准备 */public class ClassLoad02 { public static void main(String[] args) {
}}class A{ //属性-成员变量-字段 //分析类加载的连接阶段-准备 属性是如何处理 //1. n1 是实例属性,不是静态变量,因此在准备阶段,是不会分配内存 //2. n2 是静态变量,分配内存n2是默认初始化0,而不是20 //3. n3 是static final是常量,他和静态变量不一样,因为一旦赋值就不变 n3 = 30 public int n1 =10; public static int n2 = 20; public static final int n3 = 30;}
虚拟机将常量池内的符号引用替换为直接引用的过程。
/** * @author LeeZhi * @version 1.0 * 演示类加载-初始化阶段 */ public class ClassLoad03 { public static void main(String[] args) { //1 加载B类,并生成B的class对象 //2. 链接num=0 //3. 初始化阶段 //依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句 /* clinit(){ System.out.println("B静态代码块被执行"); //num=300: num=100; } 合并:num = 100 */ //4. "B () 构造器被执行" //new B();//类加载 System.out.println(B.num);//100 如果直接使用类的静态属性,也会导致类的加载 } } class B{ static { System.out.println("B 静态代码块被执行"); num=300; } static int num = 100; public B(){ System.out.println("B () 构造器被执行"); } }
1.getName:获取全类名 2.getSimpleName:获取简单类名 3.getFields:获取所有 publicf 修饰的属性,包含本类以及父类的 4.getDeclaredFields:获取本类中所有属性 5.getMethods:获取所有 public 修饰的方法,包含本类以及父类的 6.getDeclaredMethods:获取本类中所有方法 7.getConstructors:获取所有 public 修饰的构造器,包含本类 8.getDeclaredConstructors:获取本类中所有构造器 9.getPackage:以 Package]形式返回包信息 10.getSuperClass:以 Class 形式返回父类信息 11.getInterfaces:以 Class[]形式返回接口信息 12.getAnnotations:以 Annotation[]形式返回注解信息
/** * @author LeeZhi * @version 1.0 * 演示如何通过反射获取类的结构信息 */public class ReflectionUtils { public static void main(String[] args) {
} //第一组方法API @Test public void api_01() throws ClassNotFoundException { /** * 1.getName:获取全类名 * 2.getSimpleName:获取简单类名 * 3.getFields:获取所有publicf修饰的属性,包含本类以及父类的 * 4.getDeclaredFields:获取本类中所有属性 * 5.getMethods:获取所有public修饰的方法,包含本类以及父类的 * 6.getDeclaredMethods:获取本类中所有方法 * 7.getConstructors:获取本类所有public修饰的构造器 * 8.getDeclaredConstructors:获取本类中所有构造器 * 9.getPackage:以Package]形式返回包信息 * 10.getSuperClass:以Class形式返回父类信息 * 11.getInterfaces:以Class[]形式返回接口信息 * 12.getAnnotations:以Annotation[]形式返回注解信息 */ //1.得到Class对象 Class<?> personCls = Class.forName("com.gbx.reflection.Person"); System.out.println(personCls.getName()); System.out.println(personCls.getSimpleName()); Field[] fields = personCls.getFields(); for (Field field : fields) { System.out.println("本类以及父类的属性:" + field.getName()); } Field[] declaredFields = personCls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("本类所有属性:"+declaredField.getName()); } Method[] methods = personCls.getMethods(); for (Method method : methods) { System.out.println("本类及父类的方法:" + method.getName()); } Method[] declaredMethods = personCls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("本类所有方法:" + declaredMethod.getName()); } Constructor<?>[] constructors = personCls.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println("本类的构造器:" + constructor.getName()); } Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) { System.out.println("本类中所有构造器:" + declaredConstructor.getName()); } System.out.println(personCls.getPackage()); Class<?> superclass = personCls.getSuperclass(); System.out.println("父类的class对象"+superclass); Class<?>[] interfaces = personCls.getInterfaces(); for (Class<?> anInterface : interfaces) { System.out.println("接口信息:" + anInterface); } Annotation[] annotations = personCls.getAnnotations(); for (Annotation annotation : annotations) { System.out.println("注解信息:" + annotation); } }}class A{ public String hobby; public void hi(){ }
public A() { }}interface IA{
}interface IB{
}class Person extends A implements IA,IB{ //属性 public String name; protected int age; String job; private double sal;
public Person() { }
public Person(String name) { this.name = name; }
private Person(String name,int age){
} //方法 public void m1(){
} protected void m2(){
} void m3(){
} private void m4(){
}}
1.getModifiers:以 int 形式返回修饰符[说明:默认修饰符是 0,public 是 1,private 是 2,protected 是 4,static 是 8,final 是 16] public(1)+static (8)=92.getType:以 Class 形式返回类型 3.getName:返回属性名
@Test public void api_02() throws ClassNotFoundException { //1.得到Class对象 Class<?> personCls = Class.forName("com.gbx.reflection.Person"); Field[] declaredFields = personCls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("本类所有属性:"+declaredField.getName() +"该属性的修饰值:"+declaredField.getModifiers() +"该属性的类型"+declaredField.getType()); } }
1.getModifiers:以 int 形式返回修饰符[说明:默认修饰符是 0,public 是 1,private 是 2,protected 是 4,static 是 8,final 是 16]2.getReturnType:以 Classj 形式获取返回类型 3.getName:返回方法名 4.getParameterTypes:以 Class[]返回参数类型数组
Method[] declaredMethods = personCls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("本类所有方法:" + declaredMethod.getName() +"该方法的访问修饰符"+declaredMethod.getModifiers() +"该方法返回类型"+declaredMethod.getReturnType()); //输出当前这个方法的形参数组情况 Class<?>[] parameterTypes = declaredMethod.getParameterTypes(); for (Class<?> parameterType : parameterTypes) { System.out.println("该方法形参类型:" + parameterType); } }
1.getModifiers:以 int 形式返回修饰符 2.getName:返回构造器名(全类名)3.getParameterTypes:以 Class[]返回参数类型数组
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) { System.out.println("本类中所有构造器:" + declaredConstructor.getName()); Class<?>[] parameterTypes = declaredConstructor.getParameterTypes(); for (Class<?> parameterType : parameterTypes) { System.out.println("该构造器的形参类型:" + parameterType); } }
1.方式一:调用类中的 oublic 修饰的无参构造器 2.方式二:调用类中的指定构造器
3.Class 类相关方法
4.Constructor 类相关方法
1.根据属性名获取 Field 对象
Field f=clazz 对象.getDeclaredField(属性名):
2.暴破:f.setAccessible(true);//f 是 Field
3.访问
f.set(o,值);syso(f.get(o));
4.如果是静态属性,则 set 和 get 中的参数 o,可以写成 null
/** * @author LeeZhi * @version 1.0 */public class ReflectAccessProperty {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { //1.得到Student类对应的Class对象 Class<?> stuClass = Class.forName("com.gbx.reflection.Student"); //2.创建对象 Object o = stuClass.newInstance();//o 得运行类型就是Student //3.使用反射得到 age属性对象 Field age = stuClass.getField("age"); age.set(o,18);//通过反射设置属性 System.out.println(o);
//4.使用反射操作name属性 Field name = stuClass.getDeclaredField("name"); //对name进行暴破 name.setAccessible(true); name.set(o,"小黄");// name.set(null,"子");//因为name是static属性,因此o也可以写出nulL System.out.println(o); }}class Student{ public int age; private static String name;
public Student() { }
@Override public String toString() { return "Student{" + "age=" + age + '}'; }
1.根据方法名和参数列表获取 Method 方法对象:Method m=clazz.getMethod(方法名,XX.class);
2.获取对象:Object o=clazz.newInstance();
3.暴破:m.setAccessible(true):
4.访问:Object returnValue=m.invoke(o,实参列表)://o 就是对象
5.注意:如果是静态方法,则 invoke 的参数 o,可以写成 null!
public class ReflectAccessMethod { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { //1.得到Boss类对应的Class对象 Class<?> bossCls = Class.forName("com.gbx.reflection.Boss"); //2.创建对象 Object o = bossCls.newInstance(); //3.调用public的hi方法 //Method hi = bossCls.getMethod("hi"); //3.1得到hi方法对象 Method hi1 = bossCls.getDeclaredMethod("hi",String.class); //3.2调用 hi1.invoke(o,"Lee");
//4.调用 private static 方法 //4.1得到 say 方法对象 Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class); say.setAccessible(true); System.out.println(say.invoke(100, "小黄", "女")); //4.3因为say方法是static的,还可以这样调用,可以传入null System.out.println(say.invoke(null,200,"李四",'女')); //5.在反射中,如果方法有返回值,统一返回0bjct,但是他运行类型和方法定义的返回类型一致 Object reVal=say.invoke(null,300,"王五",'男'); System.out.println("reVal的运行类型="+reVal.getClass());//String }
}class Boss{ public int age; private static String name;
private static String say(int n,String s,char c){ return n +" "+s +" "+c; } public void hi(String s){ System.out.println("hi" + s); }}