文章目录
反射
Java是面向对象语言,则Java编译生成的字节码文件应该也是一个对象,而这个对象不需要我们定义,Java已经事先定义好了一个类叫做Class,Class类是用来描述现实事物的,是Java语言的最基本单位,类作为一个概念存在,概念本身也是一个对象而我们使用Class类来描述这个概念类。而通过反射技术就可以获取到字节码文件对象。
而通过反射技术使用这个字节码文件对象就可以获取到一个类的所有信息,包括私有。
Class 获取类对象
获取到堆区中的字节码文件对象的三种方式:
1.通过Object类的getClass方法
缺陷: 必须要显示创建对象才能够获取到对应的字节码文件对象
2.通过数据类型的class属性
缺点: 必须在代码中进行硬编码,当生产环境下切换类的时候需要修改源代码
优点:
1.不需要创建对象
2.当一个方法的形参需要我们传入的是一个Class类型的时候,可以用方式二,很方便
public void method(Class c){}
method(Student.class);
3.通过Class类的一个静态方法static Class<?> forName(String className)
public class ReflectDemo01 {
public static void main(String[] args) throws Exception {
//1.通过Object类的getClass方法
Student s1 = new Student("张三", 18, "深圳", 1.80);
Class<? extends Student> c1 = s1.getClass();
//通过数据类型的class属性
Class<Student> c2 = Student.class;
//通过Class类的一个静态方法 Class.forName()
Class<?> c3 = Class.forName("sz.lz.reflectCode.Student");
}
}
Constructor 获取构造方法对象
常用方法
Constructor<?>[] getConstructors() 获取到所有公有修饰的构造方法对象数组
Constructor<?>[] getDeclaredConstructors() 获取所有构造方法对象数组,包括私有
Constructor getConstructor(Class<?>… parameterTypes) 获取单个公有修饰构造方法对象
Constructor getDeclaredConstructor(Class<?>… parameterTypes) 获取所有单个修饰的构造方法对象,包括私有
public class ReflectDemo01 {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName(classPath);
// 通过字节码文件对象来获取构造方法对象
Constructor<?>[] constructors = c.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("=================");
Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
for (Constructor<?> constructor : declaredConstructors) {
System.out.println(constructor);
}
System.out.println("===================");
// 获取无参构造方法对象
Constructor<?> con = c.getConstructor();
System.out.println(con);
// 获取全参数构造方法对象
// public com.sxt.reflectdemo02.Student(java.lang.String,int,java.lang.String,double)
Constructor<?> con2 = c.getConstructor(String.class, int.class, String.class, double.class);
System.out.println(con2);
// 获取私有构造方法对象
// Constructor<?> con3 = c.getConstructor(String.class, int.class);
// java.lang.NoSuchMethodException
// System.out.println(con3);
// Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
Constructor<?> con3 = c.getDeclaredConstructor(String.class, int.class);
System.out.println(con3);
}
}
public class Student {
private String name;
private int age;
private String address;
private double height;
public Student() {
super();
}
private Student(String name, int age) {
this.name = name;
this.age = age;
}
Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public Student(String name, int age, String address, double height) {
super();
this.name = name;
this.age = age;
this.address = address;
this.height = height;
}
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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", address=" + address + ", height=" + height + "]";
}
}
Constructor 创建对象
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
//因为传入的是一个字符串,而这个字符串可以通过配置文件配置读取
properties.load(new FileReader("config/classinfo.properties"));
String classPath = properties.getProperty("className");
// 通过反射获取字节码文件对象
Class<?> c = Class.forName(classPath);
// 通过字节码文件对象获取构造方法对象
Constructor<?> con = c.getConstructor();
// 通过构造方法对象创建对象
Object instance = con.newInstance();
System.out.println(instance);
// 获取全参构造方法对象
Constructor<?> con2 = c.getConstructor(String.class, int.class, String.class, double.class);
Object instance2 = con2.newInstance("老王", 20, "深圳", 1.70);
System.out.println(instance2);
// 获取私有构造方法对象并且创建对象,这里如果没有打开访问权限会抛出java.lang.IllegalAccessException
Constructor<?> con3 = c.getDeclaredConstructor(String.class, int.class);
// 打开访问权限
//不建议通过反射暴力访问私有成员,从而赋值
con3.setAccessible(true);
Object instance3 = con3.newInstance("老李", 20);
System.out.println(instance3);
}
Field 获取成员变量对象并且赋值
常用方法
Field[] getFields() 获取所有公有的成员变量对象,包括父类的公有成员
Field[] getDeclaredFields() 获取所有本类的成员,包括私有
Field getDeclaredField(String name) 获取成员属性,包括私有
Field getField(String name) 获取公有的成员属性,包括父类
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("sz.lz.reflectCode.Student");
// 通过字节码文件对象获取成员变量对象
// Field[] fields = c.getFields();
// for (Field field : fields) {
// System.out.println(field);
// }
// System.out.println("===============");
// Field[] declaredFields = c.getDeclaredFields();
// for (Field field : declaredFields) {
// System.out.println(field);
// }
// System.out.println("===============");
// Field nameField = c.getField("name");
// System.out.println(nameField);
//上面是单纯的获取,下面是获取并且赋值
Field heightField = c.getDeclaredField("height");
System.out.println(heightField);
Constructor<?> con = c.getConstructor();
Object instance = con.newInstance();
Field nameField = c.getField("name");
Object obj = nameField.get(instance);
System.out.println(obj);
nameField.set(instance, "张三");
System.out.println(instance);
System.out.println(nameField.getModifiers());
System.out.println(nameField.getName());
//因为Student的height属性为是private修饰的所以需要用getDeclaredField(String name)
Field heightField = c.getDeclaredField("height");
heightField.setAccessible(true);
heightField.set(instance, 1.80);
System.out.println(instance);
}
}
method 获取成员方法对象并且调用
常用方法
Method[] getMethods() 获取所有公有修饰的成员方法对象,包括父类公有方法
Method[] getDeclaredMethods() 获取本类所有成员方法对象,包括私有方法
Method getMethod(String name, Class<?>… parameterTypes) 获取公有的成员方法对象
Method getDeclaredMethod(String name, Class<?>… parameterTypes) 获取私有成员方法对象
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("sz.lz.reflectCode.Student");
Object instance = c.getConstructor().newInstance();
// 通过字节码文件对象获取成员方法对象
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("=================");
Method[] declaredMethods = c.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println("==================");
// 获取method方法
// Method getMethod(String name, Class<?>... parameterTypes)
Method method = c.getMethod("method");
System.out.println(method);
Object invoke = method.invoke(instance);
System.out.println(invoke);
System.out.println("==================");
// 获取setName方法并且赋值
Method setNameMethod = c.getMethod("setName", String.class);
setNameMethod.invoke(instance, "老周");
// 获取getName方法
Method getNameMethod = c.getMethod("getName");
Object result = getNameMethod.invoke(instance);
System.out.println(result);
// 获取add方法并且调用
Method addMethod = c.getMethod("add", int.class, int.class);
Object result3 = addMethod.invoke(instance, 10, 20);
System.out.println(result3);
// 获取私有方法并且调用
Method showMethod = c.getDeclaredMethod("show");
showMethod.setAccessible(true);
showMethod.invoke(instance);
}
}
Array 获取数组对象并且赋值
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("sz.lz.reflectCode.Demo");
Object instance = c.getConstructor().newInstance();
Field arrField = c.getDeclaredField("arr");
Object arr = arrField.get(instance);
// if (arr instanceof int[]) {
// int[] array = (int[]) arr;
// System.out.println(Arrays.toString(array));
// }
// int i = Array.getInt(arr, 0);
// System.out.println(i);
// Object obj = Array.get(arr, 0);
// System.out.println(obj);
// System.out.println(Array.get(arr, 1));
// System.out.println(Array.get(arr, 2));
//// System.out.println(Array.get(arr, 3));
// int length = Array.getLength(arr);
// System.out.println(length);
for (int i = 0; i < Array.getLength(arr); i++) {
System.out.println(Array.get(arr, i));
}
Array.set(arr, 2, 100);
System.out.println(Array.get(arr, 2));
// 通过反射创建数组
Object arrObj = Array.newInstance(String.class, 5);
for (int i = 0; i < Array.getLength(arrObj); i++) {
System.out.println(Array.get(arrObj, i));
}
Object arrobj2 = Array.newInstance(int.class, 2, 3);
// Object oneDimensson1 = Array.newInstance(int.class, 1);
// Object oneDimensson2 = Array.newInstance(int.class, 2);
//
// Array.set(arrobj2, 0, oneDimensson1);
// Array.set(arrobj2, 1, oneDimensson2);
if (arrobj2 instanceof int[][]) {
int[][] array = (int[][]) arrobj2;
System.out.println(array);
}
}
}
class Demo {
int[] arr = new int[3];
public Demo() {
arr[0] = 10;
arr[1] = 20;
}
}