反射
反射的概念:
Java中的反射是在运行状态中动态的获取类, 类属性, 类方法, 类构造方法等内部信息的机制。使用反射可以让代码具有更强的普适性。
反射的使用:
实体类
package com.lyc.demo;
public class Dog {
String name;
public int age;
private char sex;
public Dog() {
}
public Dog(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public static void test1(){
System.out.println("这是一个公共的方法");
}
private static void test(int age){
System.out.println("这是一个私有的方法");
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
1、获取Class对象
为什么要获取Class对象?我们都知道Java程序是先编译后运行,编译就是将程序编译为一个xxx.class的文件。这时所有的东西都存储在这个class文件上。当xxx.class文件被类加载器加载到虚拟机中,我们可以通过.class文件获取原始类中的所有的信息。因此只有了class对象才能找到关于类的属性、方法、构造方法。
获取class对象的三种方式:
package com.lyc.demo;
public class Demo06 {
public static void main(String[] args) throws ClassNotFoundException {
//方式一
Class<Dog> dogClass = Dog.class;
System.out.println(dogClass);
//方式二 forName():需要全限定类名
Class<?> aClass = Class.forName("com.lyc.demo.Dog");
System.out.println(aClass);
//方式三
Class<? extends Dog> aClass1 = new Dog().getClass();
System.out.println(aClass1);
}
}
2、获取Constructor对象
与构造方法有关的方法。该方法都是用Class对象去调用。
Constructor<?>[] | getConstructors() 返回包含一个数组 Constructor 对象反射由此表示Class的所有公共构造 方法对象。 |
---|---|
Constructor<?>[] | getDeclaredConstructors() 返回一个反映 Constructor 对象表示的类声明的所有 Constructor 对象的数组 类 。 |
Constructor<T> | getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映 Constructor 对象表示的类 |
Constructor<T> | getDeclaredConstructor(类<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映 Constructor 对象表示的类或接口的指定 构造方法对象 |
下面这个方法是Construct对象调用
T | newInstance(Object... initargs) 使用此 Constructor 对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。 |
---|---|
方法的使用案例:
package com.lyc.demo;
import java.lang.reflect.Constructor;
public class Demo03 {
public static void main(String[] args) throws NoSuchMethodException {
/**
* 反射获取构造方法
*/
Class<Dog> dogClass = Dog.class;
System.out.println("获取所有公共的构造方法:");
Constructor<?>[] constructors = dogClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("获取无参构造");
Constructor<Dog> constructor = dogClass.getConstructor(null);
System.out.println(constructor);
System.out.println("获取有参构造");
Constructor<Dog> constructor1 = dogClass.getConstructor(String.class, int.class, char.class);
System.out.println(constructor1);
}
}
3、获取Method对象
Method[] | getMethods()获取当前类或者父类的公开的所有的方法 |
---|---|
Method[] | getDeclaredMethods() 获取当前类所有的方法,但是不能获取父类的方案 |
Method | getMethod(String name, 类<?>... parameterTypes) 返回一个 方法 对象,它反映此表示的类或接口的指定公共成 |
Method | getDeclaredMethod(String name, 类<?>... parameterTypes) 返回一个 方法 对象,它反映此表示的类或接口的指定声明的方法 类 对象。 |
Method下的方法
Object | invoke(Object obj, Object… args)在具有指定参数的 方法 对象上调用此 方法 对象 |
---|---|
package com.lyc.demo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo04 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
/**
* 反射获取方法
*/
Class<Dog> dogClass = Dog.class;
System.out.println("获取本类和父类的所有的公共方法");
Method[] methods = dogClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("获取本类所有的方法");
Method[] methods1 = dogClass.getDeclaredMethods();
for (Method method : methods1) {
System.out.println(method);
}
Dog dog = dogClass.newInstance(); //获取dog对象
System.out.println("获取单个无参方法");
Method test1 = dogClass.getMethod("test1");
test1.invoke(dog);
System.out.println(test1);
System.out.println("获取单个私有含参方法");
Method test = dogClass.getDeclaredMethod("test", int.class);
test.setAccessible(true); //对于私有方法要先解除私有限定
test.invoke(dog,12); //在具有指定参数的`方法`对象上调用此`方法`对象
System.out.println(test);
}
}
对于私有的方法我们可以使用setAccessible()
方法解除私有限定。
4、获取Field对象
Field | getDeclaredField(String name) 返回一个 Field 对象,它反映此表示的类或接口的指定已声明字段 类 对象。 |
---|---|
Field[] | getDeclaredMethod(String name, 类<?>... parameterTypes) 返回一个 方法 对象,它反映此表示的类或接口的指定声明的方法 类 对象 |
Field | getField(String name) 返回一个 Field 对象,它反映此表示的类或接口的指定公共成员字段 类 对象。 |
Field[] | getFields() 返回包含一个数组 Field 对象反射由此表示的类或接口的所有可访问的公共字段 类 对象。 |
package com.lyc.demo;
import java.lang.reflect.Field;
public class Demo05 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
Class<Dog> dogClass = Dog.class;
System.out.println("获取所有公开属性");
Field[] fields = dogClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("获取所有属性");
Field[] fields1 = dogClass.getDeclaredFields();
for (Field field : fields1) {
System.out.println(field);
}
Dog dog = dogClass.newInstance(); //获取dog对象
System.out.println("获取单个公共属性");
Field age = dogClass.getField("age");
age.set(dog,2); //对属性进行赋值
System.out.println(age);
System.out.println("获取非公共单个属性");
Field sex = dogClass.getDeclaredField("sex");
sex.setAccessible(true); //解除私有限定
sex.set(dog,'公'); //对私有属性进行赋值
System.out.println(sex);
//打印赋值结果
System.out.println(dog);
}
}