一、类的加载
当我们程序在运行后,第一次使用某个类的时候,会将此类的class文件读取到内存,并将此类的所有信息储存到一个Class对象中
类的加载实时机:
// 类的加载时机
Student student;// 仅仅是在栈内存中声明,并没有完全加载Student类
//1.创建类的实例
new Student();
// 2.类的静态变量或者为静态变量赋值
Student.name = "肥兄";
// 3.类的静态方法
Student.method();
// 4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
Class<?> aClass = Class.forName("cn.dkt.demo05_类的加载");
// 5.初始化某个类的子类
new SmallStudent();
// 6.直接使用java.exe命令来运行某个主类
二、类的加载器
概述:是负责将磁盘上的某个class文件读取到内存并生成Class对象
如何获取类加载器
类的字节码对象.getClassLoader()
Java中有三种类加载器,它们分别用于加载不同种类的class
- 启动类加载器:用于加载系统类库<java_home>\bin目录下的class,比如 .jar
- 扩展类加载器:用于加载扩展类库<java_home>\lib\ext目录下的class
- 应用程序加载器:用于加载我们自定义类的加载器
代码演示:
// 获取 Test类的加载器
ClassLoader classLoader1 = Test.class.getClassLoader();
System.out.println(classLoader1);
// 获取 Student类加载器
ClassLoader classLoader2 = Student.class.getClassLoader();
System.out.println(classLoader2);
// 获取 String类的加载器
ClassLoader classLoader3 = String.class.getClassLoader();
System.out.println(classLoader3);
三、Class对象的获取方式
1.通过类名.getClass
2.通过对象名称.getClass()
3.通过Class的静态方法获得:public static Class<?> forName(String className)
注意:每一个类的Class对象都只有一个
// 通过Class静态方法获得
Class<?> c3 = Class.forName("cn.dkt.demo05_类的加载.Student");
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
四、Class类常用方法
String getSimpleName():获得类的名字字符串:类名
String getName():获得类全名:包+类名
T newInstance():创建Class对象关联类的对象
// 获得Student类的Class对象
Class<Student> c = Student.class;
// 获得类名字符串
String name = c.getSimpleName();
// 获得类全名
String name1 = c.getName();
System.out.println(name1);//cn.dkt.demo05_类的加载.Student
// 创建Student对象
Student student = c.newInstance(); // 其实就相当于调用了Student类中的无参构造方法
System.out.println(student); //6e8dacdf
五、反射之操作构造方法
Constructor概述:
类中的每一个构造方法都是一个Constructor类的对象
反射之操作构造方法目的
获得Constructor对象来创建类的对象
使用:
1.如何通过反射获取一个类的构造方法:Class类的方法
- public Constructor<T> getConstructor(Class<?>... parameterTypes)
根据参数类型获得对应的Constructor对象
只能获得public修饰的构造方法
- public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
根据参数类型获得对应的Constructor对象
可以是public、protected、默认、private修饰符修饰的构造方法
- public Constructor<?>[] getConstructors()
获得类中的所有构造方法,只能获取public修饰的
- public Constructor<?>[] getDeclaredConstructors()
获得类中所有的构造方法
可以是public、protected、默认、private修饰符修饰的构造方法
2.如何通过反射执行获取的构造方法:Constructor的方法
- public T newInstance(Object ... initargs)
根据指定的参数创建对象
- public void setAccessible(boolean flag)
设置“暴力反射” : 是否取消权限检查,true是取消权限检查,false是不取消
代码演示:
// 获得Student的Class对象
Class<Student> c = Student.class;
// 获取单个构造方法
// 获取无参构造方法
Constructor<Student> constructor1 = c.getDeclaredConstructor();
System.out.println(constructor1);
// 获取满参构造方法
Constructor<Student> constructor2 = c.getDeclaredConstructor(String.class,int.class);
System.out.println(constructor2);
// 获取单参的构造方法
Constructor<Student> constructor3 = c.getDeclaredConstructor(String.class);
System.out.println(constructor3);
Constructor<Student> constructor4 = c.getDeclaredConstructor(int.class);
System.out.println(constructor4);
System.out.println("============================================");
// 获取所有构造方法
Constructor<?>[] constructors = c.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("============================================");
// 通过执行 constructor1 表示的构造方法来创建Student对象
Student s1 = constructor1.newInstance();
System.out.println(s1);
// 通过执行 constructor2 表示的构造方法来创建Student对象
Student s2 = constructor2.newInstance("张冬晖",18);
System.out.println(s2);
// 通过执行 constructor3 表示的构造方法来创建Student对象
// 取消constructor3表示的构造方法的权限检查
constructor4.setAccessible(true);
Student s4 = constructor4.newInstance(18);
System.out.println(s4);
六、反射之操作成员方法
Method类概述
每一个成员方法都是一个Method对象
反射之操作成员方法的目的
操作Method对象来调用成员方法
使用:
1.如何通过反射获得类中的成员方法:Class类的方法
- public Method getMethod(String name, Class<?>...parameterTypes)
根据方法名称和参数类型获得对应的方法对象,只能获得public的
考虑到方法有重载,所以还需要加上可变参数作为参数来辨别具体是哪个方法要调用
2.如何通过反射执行获取类中的成员方法:Method方法
public class Test {
public static void main (String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取Student的Class对象
Class<Student> c = Student.class;
/*
* 获取单个方法
* */
Method show1 = c.getDeclaredMethod("show1");
System.out.println(show1);
Method show2 = c.getDeclaredMethod("show2",int.class);
System.out.println(show2);
Method show3 = c.getDeclaredMethod("show3");
System.out.println(show3);
Method show4 = c.getDeclaredMethod("show4", String.class);
System.out.println(show4);
Method show5 = c.getDeclaredMethod("show5", int.class);
System.out.println(show5);
System.out.println("========================================================================");
/*
* 获取所有方法
* */
Method[] declaredMethods = c.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("========================================================================");
// 通过反射创建Student对象
Student student = c.getDeclaredConstructor().newInstance();
// 通过反射执行show1表示的show1方法
show1.invoke(student);
// 通过反射执行show1表示的show1方法
show2.invoke(student,10);
// 通过反射执行show1表示的show1方法
show3.setAccessible(true);
show3.invoke(student);
// 通过反射执行show1表示的show1方法
show4.setAccessible(true);
show4.invoke(student,"哈哈");
// 通过反射执行show1表示的show1方法
Object invoke1 = show5.invoke(student,20);
System.out.println(invoke1);
}
}
public class Student {
public void show1(){
System.out.println("show1 方法");
}
public void show2(int num){
System.out.println("show2 方法" + num);
}
private void show3(){
System.out.println("show3 方法");
}
private void show4(String str){
System.out.println("show4 方法" + str);
}
public int show5(int num){
System.out.println("show5 方法" + num);
return 100;
}
}
七、反射之操作成员变量
Field类概述
每一个成员变量都是一个Field类的对象
反射之操作成员变量的目的
通过Field对象给对应的成员变量赋值和取值
使用:
1.如果通过反射获取类的成员变量:Class类的方法
- public Field getField(String name)
- public Field[] getFields()
- public Field getDeclaredField(String name)
- public Field[] getDeclaredFields()
2.如何通过反射访问获取类的成员变量:Field类的对象
- public Class<?> getType()
- public void set(Object obj, Object value)
- public Object get(Object obj)
- public void setAccessible(boolean flag)
// 定义学生类
public class Student {
public String name;
private int age;
}
public class Test {
public static void main (String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取Student类的Class对象
Class<Student> c = Student.class;
/*
* 获取单个成员变量
* */
// 通过反射获取name成员变量
Field name = c.getField("name");
System.out.println(name);
// 通过反射获取age成员变量
Field age = c.getDeclaredField("age");
System.out.println(age);
System.out.println("=======================================");
/*
* 获取所有成员变量
* */
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("=======================================");
// 通过反射获取Student对象
Student student = c.getDeclaredConstructor().newInstance();
// 获取表示name属性的类型
System.out.println(name.getType());
// 获取表示age属性的类型
System.out.println(age.getType());
System.out.println("=======================================");
// 取消name或者age属性的权限检查
age.setAccessible(true);
// 通过反射给name或者age属性赋值
name.set(student,"张三");
age.set(student,18);
System.out.println("=======================================");
// 通过反射获取name属性的值
System.out.println(name.get(student));
// 通过反射获取age的值
System.out.println(age.get(student));
}
}