概念
允许对成员变量,成员方法和构造方法的信息进行编程访问
获取class对象的三种方式
(1)、Class.forName("全类名") 编译
(2)、类名.class 类加载
(3)、对象.getClass() 运行
import com.myreflect.bean.Student;
public class MyReflectExer01 {
public static void main(String[] args) throws ClassNotFoundException {
/*
获取class对象的三种方式**
(1)、Class.forName("全类名")
(2)、类名.class
(3)、对象.getClass();
**/
//1.第一种方式
//全类名 = 包名 + 类名
//最为常用
Class<?> clazz1 = Class.forName("com.myreflect.bean.Student");
//2.第二种方式
//一般更多时当作参数进行传递
Class clazz2 = Student.class;
//3.第三种方式
//当已经创建对象时,才可以使用
Student student = new Student();
Class clazz3 = student.getClass();
System.out.println(clazz1 == clazz2);
System.out.println(clazz2 == clazz3);
}
}
利用反射获取构造方式
Class类用于获取构造方法的方法
Constructer<?>[] getConstructors()
Constructer<?>[] getDeclaredConstructors()
Constructer<T> getConstructor(Class<?> parameterTypes)
Constructer<?> getDeclaredConstructor(Class<?> parameterTypes)
Constructor类中用于创建对象的方法
T newInstance(Object...initargs)
setAccesible(boolean flag)
import com.myreflect.bean.Student1;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class MyReflectExer02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/*
Class类用于获取构造方法的方法
Constructer<?>[] getConstructors()
Constructer<?>[] getDeclaredConstructors()
Constructer<T> getConstructor(Class<?> parameterTypes)
Constructer<?>[] getDeclaredConstructor(Class<?> parameterTypes)
Constructor类中用于创建对象的方法
T newInstance(Object...initargs)
setAccesible(boolean flag)
* */
//1.获取class字节码文件对象
Class clazz = Class.forName("com.myreflect.bean.Student1");
//2.获取构造方法
//获取公共的构造方法
System.out.println("获取公共的构造方法");
Constructor[] constructors = clazz.getConstructors();
for (Constructor con : constructors) {
System.out.println(con);
}
//获取所有的构造方法
System.out.println("所有的构造方法");
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//获取单个构造法
System.out.println("获取单个构造法");
Constructor constructor = clazz.getConstructor();
System.out.println(constructor);
Constructor constructor1 = clazz.getDeclaredConstructor(String.class);
System.out.println(constructor1);
Constructor constructor2 = clazz.getDeclaredConstructor(int.class);
System.out.println(constructor2);
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(declaredConstructor);
//获取权限修饰符,通过整数的形式输出
System.out.println("获取权限修饰符");
int modifiers = declaredConstructor.getModifiers();
System.out.println(modifiers);
//获取构造方法的参数
System.out.println("获取构造方法的参数");
Parameter[] parameters = declaredConstructor.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//通过获取到的构造方法,创建对象
//暴力反射:临时取消权限校验
constructor2.setAccessible(true);
Student1 stu =(Student1) constructor2.newInstance( 23);
System.out.println(stu);
}
}
运行结果:
获取公共的构造方法
public com.myreflect.bean.Student1(java.lang.String,int)
public com.myreflect.bean.Student1()
所有的构造方法
protected com.myreflect.bean.Student1(java.lang.String)
private com.myreflect.bean.Student1(int)
public com.myreflect.bean.Student1(java.lang.String,int)
public com.myreflect.bean.Student1()
获取单个构造法
public com.myreflect.bean.Student1()
protected com.myreflect.bean.Student1(java.lang.String)
private com.myreflect.bean.Student1(int)
public com.myreflect.bean.Student1(java.lang.String,int)
获取权限修饰符
1
获取构造方法的参数
java.lang.String arg0
int arg1
Student{name = null, age = 23}
Process finished with exit code 0
public class Student1 {
private String name;
private int age;
public Student1() {
}
public Student1(String name, int age) {
this.name = name;
this.age = age;
}
private Student1(int age) {
this.age = age;
}
protected Student1(String name) {
this.name = name;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
利用反射获取成员变量
Class类用于获取成员变量的方法
Field[] getFields() 返回所有公共成员变量对象的数组
Field[] getDeclearedFields() 返回所有成员变量对象的数组
Field getField() 返回单个公共成员变量对象
Field getDeclearedField() 返回单个成员变量对象
Field类中用于创建对象的方法
void set(Object obj,Object value) 赋值
Object get(Object obj) 获取值
import com.myreflect.bean.Student2;
import java.lang.reflect.Field;
public class MyReflectExer03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
/*
Class类用于获取成员变量的方法
Field[] getFields() 返回所有公共成员变量对象的数组
Field[] getDeclearedFields() 返回所有成员变量对象的数组
Field getField() 返回单个公共成员变量对象
Field getDeclearedField() 返回单个成员变量对象
Field类中用于创建对象的方法
void set(Object obj,Object value) 赋值
Object get(Object obj) 获取值
* */
//1.获取class字节码文件对象
Class clazz = Class.forName("com.myreflect.bean.Student2");
//2.获取所有成员变量
Field[] fields = clazz.getFields();
System.out.println("获取所有公共成员变量");
for (Field field1 : fields) {
System.out.println(field1);
}
Field[] declaredFields = clazz.getDeclaredFields();
System.out.println("获取所有成员变量");
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//3.获取单个成员变量
System.out.println("获取单个成员变量");
Field gender = clazz.getField("gender");
System.out.println(gender);
Field declaredField = clazz.getDeclaredField("name");
System.out.println(declaredField);
//4.获取权限修饰符
int modifiers = declaredField.getModifiers();
System.out.println("获取权限修饰符:"+modifiers);
//获取成员变量的名字
String name = declaredField.getName();
System.out.println("成员变量的名字:"+name);
//获取成员变量的数据类型
Class<?> type = declaredField.getType();
System.out.println("成员变量的类型:"+type);
//获取成员变量记录的值
Student2 stu = new Student2("张三", 23, "男");
declaredField.setAccessible(true);
String student = (String) declaredField.get(stu);
System.out.println(student);
//修改对象里面记录的值
declaredField.set(stu,"李四");
System.out.println(stu);
}
}
运行结果:
获取所有公共成员变量
public java.lang.String com.myreflect.bean.Student2.gender
获取所有成员变量
private java.lang.String com.myreflect.bean.Student2.name
private int com.myreflect.bean.Student2.age
public java.lang.String com.myreflect.bean.Student2.gender
获取单个成员变量
public java.lang.String com.myreflect.bean.Student2.gender
private java.lang.String com.myreflect.bean.Student2.name
获取权限修饰符:2
成员变量的名字:name
成员变量的类型:class java.lang.String
张三
Student2{name = 李四, age = 23, gender = 男}
Process finished with exit code 0
public class Student2 {
private String name;
private int age;
public String gender;
public Student2() {
}
public Student2(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取
* @return gender
*/
public String getGender() {
return gender;
}
/**
* 设置
* @param gender
*/
public void setGender(String gender) {
this.gender = gender;
}
public String toString() {
return "Student2{name = " + name + ", age = " + age + ", gender = " + gender + "}";
}
}
Class类用于获取成员方法的方法
Method[] getMethods() 返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods() 返回所有成员方法对象的数组,不包括继承的
Method[] getMethod(String name,Class<?>...parameterTypes) 返回单个公共成员方法对象 Method[] getDeclaredMethod(String name,Class<?>...parameterTypes) 返回单个成员方法对象
Method类中用于创建对象的方法
Object invoke(Object obj,Object..args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
import com.myreflect.bean.Student3;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class MyReflectExer04 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
/*
Class类用于获取成员方法的方法
Method[] getMethods() 返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods() 返回所有成员方法对象的数组,不包括继承的
Method[] getMethod(String name,Class<?>...parameterTypes) 返回单个公共成员方法对象
Method[] getDeclaredMethod(String name,Class<?>...parameterTypes) 返回单个成员方法对象
Method类中用于创建对象的方法
Object invoke(Object obj,Object..args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
* */
//1.获取Class字节码文件对象
Class clazz = Class.forName("com.myreflect.bean.Student3");
//2.获取成员方法
System.out.println("获取公共成员方法(包括父类中的所有的公共成员方法):");
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("获取本类中的所有方法,但不包含父类中的方法");
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
//3.获取单个成员方法
System.out.println("获取单个成员方法");
Method eatMethod = clazz.getDeclaredMethod("eat", String.class);
System.out.println(eatMethod);
//获取方法的修饰符
int modifiers = eatMethod.getModifiers();
System.out.println(modifiers);
//获取方法的名字
String name = eatMethod.getName();
System.out.println(name);
//获取方法的形参
System.out.println("方法的形参");
Parameter[] parameters = eatMethod.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//获取方法的异常
System.out.println("获取方法抛出的异常");
Class<?>[] exceptionTypes = eatMethod.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
//方法运行
/*Object invoke(Object obj,Object..args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)*/
Student3 student3 = new Student3();
//参数一student3:表示方法的调用者
//参数2肯德基:表示在调用时传递大的实际参数
eatMethod.setAccessible(true);
String invoke = (String)eatMethod.invoke(student3, "肯德基");
System.out.println(invoke);
}
}
import java.io.IOException;
public class Student3 {
private String name;
private int age;
public Student3() {
}
public Student3(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public void sleep(){
System.out.println("睡觉");
}
private String eat(String something) throws IOException,NullPointerException,NoSuchFieldException {
System.out.println("在吃"+something);
return "奥里给";
}
private void eat(String something,int a){
System.out.println("在吃"+something);
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
反射的作用
(1)、获取一个类里面所有的信息,获取到之后,再执行其他的业务逻辑(获取任意一个类中的所有信息)
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class MyReflectDDemo {
public static void main(String[] args) throws IllegalAccessException, IOException {
/*
* 对于任意一个对象,都可以把对象所有的字段名和值,保存到文件夹中去
* */
Student stu = new Student("小A", 23, '女', 167.5, "睡觉");
Teacher t = new Teacher("播妞", 10000);
saveObject(t);
}
private static void saveObject(Object obj) throws IllegalAccessException, IOException {
//1.获取Class字节码文件对象
Class clazz = obj.getClass();
//创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\IdeaProject\\StudyProject\\Collection\\myreflect\\src\\a.txt"));
//2.获取对象中的所有成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
//3.临时取消权限
declaredField.setAccessible(true);
//4.获得变量名
String name = declaredField.getName();
//5.获得值
Object value = declaredField.get(obj);
//写出数据
bw.write(name + "=" + value);
bw.newLine();//换行
}
bw.close();
}
}
public class Student {
private String name;
private int age;
private char gender;
private double height;
private String hobby;
public Student() {
}
public Student(String name, int age, char gender, double height, String hobby) {
this.name = name;
this.age = age;
this.gender = gender;
this.height = height;
this.hobby = hobby;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取
* @return gender
*/
public char getGender() {
return gender;
}
/**
* 设置
* @param gender
*/
public void setGender(char gender) {
this.gender = gender;
}
/**
* 获取
* @return height
*/
public double getHeight() {
return height;
}
/**
* 设置
* @param height
*/
public void setHeight(double height) {
this.height = height;
}
/**
* 获取
* @return hobby
*/
public String getHobby() {
return hobby;
}
/**
* 设置
* @param hobby
*/
public void setHobby(String hobby) {
this.hobby = hobby;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", height = " + height + ", hobby = " + hobby + "}";
}
}
public class Teacher {
private String name;
private double salary;
public Teacher() {
}
public Teacher(String name, double salary) {
this.name = name;
this.salary = salary;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return salary
*/
public double getSalary() {
return salary;
}
/**
* 设置
* @param salary
*/
public void setSalary(double salary) {
this.salary = salary;
}
public String toString() {
return "Teacher{name = " + name + ", salary = " + salary + "}";
}
}
(2)、结合配置文件,动态的创建对象并调用方法(结合配置文件动态创建对象)
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class MyReflectDDemo {
public static void main(String[] args) throws IllegalAccessException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
/*
* 反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
* */
//1.读取配置文件中的信息
Properties properties = new Properties();
FileInputStream fileInputStream = new FileInputStream("myreflect\\prop.properties");
properties.load(fileInputStream);
fileInputStream.close();
System.out.println(properties);
//2.获取全类名和方法名
String className = (String)properties.get("classname");
String methodName = (String) properties.get("method");
System.out.println(className);
System.out.println(methodName);
//3.利用反射创建对象并运行方法
Class clazz = Class.forName(className);
//获取构造方法
Constructor dc = clazz.getDeclaredConstructor();
Student student = (Student) dc.newInstance();
System.out.println(student);
//获取成员方法并运行
Method method = clazz.getMethod(methodName);
method.setAccessible(true);
method.invoke(student);
}
}
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void study(){
System.out.println("学生在学习!");
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
public class Teacher {
private String name;
private double salary;
public Teacher() {
}
public Teacher(String name, double salary) {
this.name = name;
this.salary = salary;
}
public void teach(){
System.out.println("老师在教书!");
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return salary
*/
public double getSalary() {
return salary;
}
/**
* 设置
* @param salary
*/
public void setSalary(double salary) {
this.salary = salary;
}
public String toString() {
return "Teacher{name = " + name + ", salary = " + salary + "}";
}
}
类装载的执行过程
类加载的过程:加载、链接(验证、准备、解析)、初始化
1、加载
类加载器会读取类的二进制数据(即.class文件),然后将其加载到JVM内存中。
2、链接
该阶段细分为以下几个子阶段:
验证
确保加载的.class文件符合java虚拟机规范的要求,不会对JVM造成危害。
准备
为类的静态变量分配内存,并设置默认初始值。
解析
将类中的符号引用转换为直接引用,比如将方法调用的符号引用解析为实际方法的直接引用。
3、初始化
涉及执行静态初始化器(如果有),并对类中的静态字段进行初始化赋值。初始化阶段包括执行静态初始化和静态变量赋予成员指定的初始化值。