反射
1. 反射
1.1 获取Method对象
1.1.1 一个成员方法你所关注的点
通过正常的途径调用一个成员方法:
权限修饰符 [静态/abstract/final] 返回值类型 方法名(形式参数列表)
调用方法:
类对象.方法名(实际参数);
类名.方法名(实际参数);
方法的重载:
1. 在同一个类内,或者接口内
2. 要求方法名必须一致
3. 要求当前方法的形式参数列表数据类型,个数,顺序必须不一致。
对于一个方法而言:
1. 方法名
2. 形式参数列表
1.1.2 Method涉及到的方法
Method[] getMethods();
获取类内所有非私有化成员方法对象数组,包括从父类继承而来子类可以使用的成员方
法。
Method[] getDeclaredMethods();
获取类内所有成员方法对象数组,有且只有当前类内的特有方法,不包括父类继承给子类
使用的方法,同时可以获取私有化方法。
Method getMethod(String methodName, Class... parameterTypes);
根据指定的方法名,和对应的参数类型来获取指定的非私有化成员方法类对象
案例:
无参数方法 public void game();
cls.getMethod("game");
有参数方法 public void game(String);
cls.getMethod("game", String.class);
Method getDeclaredMethod(String methodName, Class... parameterTypes);
根据指定的方法名,和对应的参数类型获取类内的任意成员方法,包括私有化成员方法,
不包括从父类继承而来的方法。
案例:
有参数私有化方法 private void testPrivate(String);
cls.getDeclaredMethod("testPrivate", String.class);
Object invoke(Object obj, Object... parameters);
Object obj 是执行当前方法的对象。
Object... parameters 当前方法执行所需实际参数,为不定长参数
Method类对象调用,传入执行当前方法的对象和对应当前方法的实际参数,执行当前方法。
package com.qfedu.a_reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class GetMethodObject {
public static void main(String[] args)
throws ClassNotFoundException, NoSuchMethodException, SecurityException,
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class cls1 = Class.forName("com.qfedu.a_reflect.Person");
Method[] methods = cls1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println();
Method[] declaredMethods = cls1.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println();
Method game1 = cls1.getMethod("game");
Method game2 = cls1.getMethod("game", String.class);
System.out.println(game1);
System.out.println(game2);
System.out.println();
Method private1 = cls1.getDeclaredMethod("testPrivate");
Method private2 = cls1.getDeclaredMethod("testPrivate", String.class);
System.out.println(private1);
System.out.println(private2);
System.out.println();
Object object = cls1.getConstructor().newInstance();
game1.invoke(object);
game2.invoke(object, "我的世界");
private1.setAccessible(true);
private2.setAccessible(true);
private1.invoke(object);
private2.invoke(object, "韭菜猪肉");
}
}
1.2 获取Field对象
1.2.1 成员变量你关注什么???
关注内容:
权限修饰符 [static/fianl] 数据类型 名字
成员变量的唯一性:
成员变量名字
在成员变量对象Field中,可以获取当前成员变量数据类型,权限修饰符标记,关键字修饰标记
原本:
类对象.set成员变量名(数据);
类对象.get成员变量名();
1.2.2 Field涉及到的方法
Field[] getFields();
获取当前类内所有非私有化成员变量类对象数组
Field[] getDeclaredFields();
获取当前类内所有成员变量类对象数组,包括私有化成员变量
Field getField(String fieldName);
根据指定的成员变量名字获取对应的非私有化成员变量类对象
Field getDeclaredField(String fieldName);
根据指定的成员变量名字获取对应的成员变量类对象,包括私有化成员变量类对象。
void set(Object obj, Object value);
Object obj 哪一个对象的成员变量
Object value 对应当前成员变量的数据
通过Field类对象调用,传入参数是当前操作的哪一个类对象明确说明和对应的赋值数据
Object get(Object obj);
Object obj 明确哪一个对象的成员变量
通过Field类对象调用,获取指定对象的对应成员变量数据,返回值是对应成员变量数据内容为Object类型
补充方法:
String getName();
Class getType();
1.3 反射案例实现
package com.qfedu.b;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
import javax.accessibility.Accessible;
public class Demo1 {
public static void main(String[] args)
throws FileNotFoundException, IOException, ClassNotFoundException,
InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException, SecurityException {
Properties properties = new Properties();
properties.load(new FileInputStream("./src/worker.properties"));
System.out.println(properties.getProperty("className"));
System.out.println(properties.getProperty("id"));
System.out.println(properties.getProperty("name"));
System.out.println(properties.getProperty("gender"));
System.out.println();
String className = properties.getProperty("className");
Class<?> cls = Class.forName(className);
Object obj = cls.getConstructor().newInstance();
Field[] declaredFields = cls.getDeclaredFields();
AccessibleObject.setAccessible(declaredFields, true);
for (Field field : declaredFields) {
if ("id".equals(field.getName())) {
Class<?> type = field.getType();
if (type == int.class) {
field.set(obj, Integer.valueOf(properties.getProperty("id")));
}
}
if ("name".equals(field.getName())) {
field.set(obj, properties.getProperty("name"));
}
if ("gender".equals(field.getName())) {
field.set(obj, properties.getProperty("gender").charAt(0));
}
}
System.out.println(obj);
}
}