获取字节码文件对象
package reflectExercise;
/**
* 反射练习
*
*/
public class GetClass {
public static void main(String[] args) throws ClassNotFoundException {
// 反射 Reflect
// 在运行状态中,对于任何一个类,都可以知道这个类的所有属性和方法;对于任何一个对象,都能够调用其任意属性和方法
// 这种动态获取信息及调用对象方法的功能就是反射
// 利用反射创建的对象可以无视访问权限修饰符调用类中的内容
// 反射可以和配置文件结合使用,将要创建的对象信息和方法写在配置文件中,配置文件读取到什么类,就创建什么类
// 读取到什么方法,就调用什么方法
// 若需求变更时,就无需修改代码,直接修改配置文件即可
// 反射都是从class字节码文件中获取内容,所以说想要使用反射,必须先获取class字节码
// 获取字节码文件对象
// 1.使用Class类中的静态方法:Class.forName(“全类名(包名 + 类名)”)
Class studentClazz1 = Class.forName("reflectExercise.Student");
System.out.println(studentClazz1);
// 2.使用类中的class属性获取
Class studentClazz2 = Student.class;
System.out.println(studentClazz2);
// 3.通过实例对象获取字节码文件对象
Student student = new Student("张三", 18);
Class studentClazz3 = student.getClass();
System.out.println(studentClazz3);
// 通过三种方式获得的字节码文件对象是同一个
System.out.println(studentClazz1 == studentClazz2); // true
System.out.println(studentClazz2 == studentClazz3); // true
}
}
class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
反射获取构造方法
package reflectExercise;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* 获取构造方法
*/
public class ConstructorExercise {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 通过反射获取类中的构造方法
// 方法构成规则
// get 表示获取
// Declared 表示私有
// Constructor 构造方法
// s 表示获取所有(复数形式)
// get...方法会返回一个指定的Constructor对象,根据构造方法的参数类型(也需要字节码文件)指定
// get...s方法会返回一个Constructor[]数组,包含当前方法能够获得的所有构造方法
// 注:若获取到的构造方法是私有的,必须要临时修改其访问权限,否则无法使用
// 想要通过反射获取,必须先获取其字节码文件对象
Class clazz = Class.forName("reflectExercise.Person");
// 获取指定的构造方法
// 空参
Constructor constructor1 = clazz.getConstructor();
// 指定参数 是根据构造方法的参数类型进行查询的,传递的参数需要使用字节码文件对象
Constructor constructor2 = clazz.getConstructor(String.class, int.class);
// 使用get方法,不带Declared,无法获得非Public的构造方法
// Constructor constructor3 = clazz.getConstructor(String.class); // NoSuchMethodException
Constructor constructor3 = clazz.getDeclaredConstructor(String.class);
// 非private构造方法,可以直接使用(要根据获得的对应的构造方法传递参数)
Person p1 = (Person)constructor1.newInstance();
Person p2 = (Person)constructor2.newInstance("张三", 18);
System.out.println(p1);
System.out.println(p2);
// private构造方法,虽然可以通过Declared方法获取,但是无法直接使用
// Person p3 = (Person)constructor3.newInstance("张三"); // IllegalAccessException
// 需要临时修改其访问权限(暴力反射)
constructor3.setAccessible(true);
Person p3 = (Person)constructor3.newInstance("张三");
System.out.println(p3);
// 使用get...s方法获取
Constructor[] constructors = clazz.getConstructors();
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
}
}
class Person{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
反射获取成员变量
package reflectExercise;
import java.lang.reflect.Field;
/**
* 反射获取成员变量
*
*/
public class FieldExercise {
public static void main(String[] args) throws Exception {
// 获取字节码文件
// Class clazz = Class.forName("reflectExercise.Animal");
// // 反射获取成员变量的方法和反射获取构造方法的使用方法一致,不过多赘述
// Field number = clazz.getField("number");
// System.out.println(number);
// // 获取到private的成员变量,仍然无法直接使用
// Field name = clazz.getDeclaredField("name");
// System.out.println(name);
// Field age = clazz.getDeclaredField("age");
// System.out.println(age);
//
// Field[] fields = clazz.getDeclaredFields();
// for (Field field : fields) {
// System.out.println(field);
// }
// 通过反射获取一个类的成员变量并修改
// void set(Object obj, Object value) 赋值 Object get(Object obj) 获取值
Animal animal1 = new Animal("狗", 18, "123");
Animal animal2 = new Animal("猫", 18, "456");
System.out.println(animal1);
System.out.println(animal2);
System.out.println("----------------------------------------");
// 获取字节码文件对象
Class clazz = Class.forName("reflectExercise.Animal");
// 修改姓名
Field name = clazz.getDeclaredField("name");
// 对于private权限的变量,临时修改其访问权限
name.setAccessible(true);
name.set(animal1, "炫狗");
name.set(animal2, "哈机密");
// 修改年龄
Field age = clazz.getDeclaredField("age");
age.setAccessible(true);
age.set(animal1, 1);
age.set(animal2, 2);
// 修改编号
Field number = clazz.getDeclaredField("number");
number.set(animal1, "147");
number.set(animal2, "258");
System.out.println(animal1);
System.out.println(animal2);
}
}
class Animal{
private String name;
private int age;
public String number;
public Animal() {
}
public Animal(String name, int age, String number) {
this.name = name;
this.age = age;
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
", number='" + number + '\'' +
'}';
}
}
反射获取成员方法
package reflectExercise;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 反射获取成员方法
* invoke v.调用、实行
*/
public class MethodExercise {
public static void main(String[] args) throws Exception {
// 综合,通过反射完成一个对象创建,赋值,使用
Class clazz = Class.forName("reflectExercise.Car");
// 获取构造方法
Constructor constructor1 = clazz.getConstructor();
Car car1 = (Car)constructor1.newInstance();
// 获取成员变量
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(car1, "benz");
Field price = clazz.getDeclaredField("price");
price.setAccessible(true);
price.set(car1, "123456");
System.out.println(car1);
// 获取方法
Method run = clazz.getMethod("run");
run.invoke(car1);
System.out.println("--------------------------------------------");
// 通过set方法设置对象属性
Car car2 = (Car)constructor1.newInstance();
Method setName = clazz.getMethod("setName", String.class);
setName.invoke(car2, "bmw");
Method setPrice = clazz.getMethod("setPrice", String.class);
setPrice.invoke(car2, "456789");
// get方法得到对象属性
Method getName = clazz.getMethod("getName");
Method getPrice = clazz.getMethod("getPrice");
System.out.println((String) getName.invoke(car2));
System.out.println((String) getPrice.invoke(car2));
System.out.println(car2);
run.invoke(car2);
}
}
class Car{
private String name;
private String price;
public Car() {}
public Car(String name, String price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", price='" + price + '\'' +
'}';
}
public void run() {
System.out.println(this.name + " 害虫!!!");
}
}