用到的类和文件
前期准备
创建一个Person对象
public class Person {
//私有成员变量
private String name;
//成员变量
int age;
//公共成员变量
public String address;
//多参构造器
Person(String name, int age) {
this.name = name;
this.age = age;
}
//私有带参构造器
private Person(String name) {
this.name = name;
}
//公共无参构造器
public Person() {
}
//公共多参构造器
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//公共方法
public void show() {
System.out.println("show");
}
//公共带参方法
public void method(String s) {
System.out.println("method " + s);
}
//公共带参带返回值方法
public String getString(String s, int i) {
return s + "-->" + i;
}
//私有无参方法
private void function() {
System.out.println("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
常用的反射方法
public class Main {
//获得Class对象
public static void getclass() throws Exception {
//1.通过对象调用 getClass() 方法来获取
Person person = new Person();
Class<? extends Person> class1 = person.getClass();
//2.通过 类名.class 的方式得到
// 该方法最为安全可靠,程序性能更高
// 说明所有类中都有隐藏变量class
Class<Person> class2 = Person.class;
//3.通过 Class 对象的 forName() 静态方法来获取
// 用的最多,会抛异常
Class<?> class3 = Class.forName("com.Person");
//一个类在jvm中只会有一个class实例,所以下面结果都为true
System.out.println(class1.equals(class2));
System.out.println(class2.equals(class3));
}
// 获取类的所有构造方法
public static void getAllConstruct() throws Exception{
Class<?> aClass = Class.forName("com.Person");
//获得类的所有构造方法的列表
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor.toString());
}
}
//获取无参构造方法
public static void getConstruct1() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1.获取class对象
Class<?> aClass = Class.forName("com.Person");
//2.获取无参构造方法
Constructor<?> class_construct = aClass.getDeclaredConstructor();
//3.利用无参构造生成对象
Object o = class_construct.newInstance();
//3.1如果只需要利用无参构造来创建实例
// 那么也可以不用获取构造器
// 直接使用newInstance方法
Object o1 = aClass.newInstance();
System.out.println(o);
System.out.println(o1);
}
//获取带参构造方法
public static void getConstruct2() throws Exception{
Class<?> aClass = Class.forName("com.Person");
//com.Person类中需要有一个(String name, int age, String address)的构造器
Constructor<?> declaredMethod = aClass.getDeclaredConstructor(String.class, int.class,String.class);
Object o = declaredMethod.newInstance("名字", 24,"地址");
System.out.println(o);
}
//获取private修饰的构造方法
public static void getConstruct3() throws Exception{
Class<?> aClass = Class.forName("com.Person");
Constructor con = aClass.getDeclaredConstructor(String.class);
//给与访问权限
con.setAccessible(true);
Object o = con.newInstance("私有带参构造器被创建");
System.out.println(o);
}
//给成员变量赋值
public static void setData() throws Exception {
Class<?> aClass = Class.forName("com.Person");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
Object o = declaredConstructor.newInstance();
System.out.println(o);
//根据参数名设置值
Field name = aClass.getDeclaredField("name");
//给与权限
name.setAccessible(true);
//设置参数值
name.set(o,"名字");
System.out.println(o);
}
//获取成员变量
public static void getData() throws Exception{
Class<?> aClass = Class.forName("com.Person");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
Object o = declaredConstructor.newInstance();
//根据参数名生成字段"对象",此处的name字段是私有的
Field name = aClass.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"名字");
//通过字段"对象"的get方法获取字段值,参数是字段所在的对象
System.out.println(name.get(o));
}
//获取无参无返回值成员方法
public static void getMethod1() throws Exception{
/**
* 1、public 方法 getMethod(String name, Class<?>... parameterTypes):获取所有方法,包括父类的
* 参数 : name:方法的名称 parameterTypes:该方法的参数列表
* 2、public 方法 getDeclaredMethod(String name, Class<?>... parameterTypes):获取所有子类定义的方法
* 参数 : name:方法的名称 parameterTypes:该方法的参数列表
*/
Class<?> aClass = Class.forName("com.Person");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
Object o = declaredConstructor.newInstance();
//获取需要的方法对象
Method show = aClass.getDeclaredMethod("show");
/**
* public Object invoke(Object obj, Object... args)
* obj - 被调用的对象 args - 用于方法调用的参数
*/
show.invoke(o);
}
//获取获取有参有返回值成员方法,并调用
public static void getMethod2() throws Exception{
Class<?> aClass = Class.forName("com.Person");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
Object o = declaredConstructor.newInstance();
//获取带参无返回值方法
Method method = aClass.getDeclaredMethod("method", String.class);
method.invoke(o,"带参无返回值");
//获取带参带返回值方法
Method getString = aClass.getDeclaredMethod("getString", String.class, int.class);
Object invoke = getString.invoke(o,"带参有返回值",1);
System.out.println(invoke);
}
//获取privste成员方法
public static void getMethod3() throws Exception{
Class<?> aClass = Class.forName("com.Person");
Object o = aClass.newInstance();
Method function = aClass.getDeclaredMethod("function");
//给私有方法设置权限
function.setAccessible(true);
function.invoke(o);
}
public static void main(String[] args) throws Exception {
// getclass();
// getAllConstruct();
// getConstruct1();
// getConstruct2();
// getConstruct3();
// setData();
// getData();
// getMethod1();
// getMethod2();
// getMethod3();
}
}
利用反射不改代码更改运行对象
前期准备
创建一个reflect.txt文本和Service1和Service2两个类
reflect.txt文本
Service1类
public class Service1 {
public void doService1(){
System.out.println("执行了Service1的doService1方法");
}
}
Service2类
public class Service2 {
public void doService2(){
System.out.println("执行了Service1的doService2方法");
}
}
代码实现
//通过文本改变代码执行所调用的类和方法
public static void change() throws Exception{
//reflect.txt中获取类名称和方法名称
File springConfigFile = new File("E:\\lcy\\project\\APIFuns\\src\\test\\java\\com\\reflect.txt");
Properties springConfig= new Properties();
springConfig.load(new FileInputStream(springConfigFile));
String className = (String) springConfig.get("class");
String methodName = (String) springConfig.get("method");
//通过反射获取对象
Class<?> aClass = Class.forName(className);
Object o = aClass.newInstance();
//通过反射获取方法
Method declaredMethod = aClass.getDeclaredMethod(methodName);
declaredMethod.invoke(o);
}
越过泛型检查
使类型为String的list集合添加int类型数据
//通过反射越过泛型检查
public static void notCheck() throws Exception{
ArrayList<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
Method add = list.getClass().getDeclaredMethod("add", Object.class);
add.invoke(list,5);
for (Object s : list) {
System.out.println(s);
}
}