共有方法 获取成员变量 获取构造方法 获取成员方法 获取全类名 配置文件案列
1.java代码在计算机中经历的阶段:
1.源码 xxx.java文件 2.javac编译为字节码文件 ,包含一些成员方法,属性,构造方法,类名信息等
3.使用类加载器往内存中加载,包含成员变量,构造方法,成员方法 都存在一个数组中 4.new的时候 运行阶段
2.将类的各个组成部分封装为其他对象,这就是反射机制
1. 可以在程序运行过程中,操作这些对象。 2. 可以解耦,提高程序的可扩展性。
3.反射的三种方式
1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
* 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
2. 类名.class:通过类名的属性class获取
* 多用于参数的传递
3. 对象.getClass():getClass()方法在Object类中定义着。
* 多用于对象的获取字节码的方式
注意:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
共有方法
1.getName() 获得str类型名字 2. setAccessible(true):暴力反射 设置private成员 或调用时需要设置
public class Person {
public int age;
public String name;
String name2;
private int cm;
@Override
public String toString() {
}
public void eat(){
System.out.println("eat..");
}
public void eat(String str){
System.out.println("eat: "+str);
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public Person() {
}
}
获取成员变量
* Field[] getFields() : 获取所有public修饰的成员变量 返回一个数组
* Field getField(String name) 获取指定名称的 public修饰的成员变量
* Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符包括private的
* Field getDeclaredField(String name)
1. 设置值 * void set(对象名), Object value) 2. 获取值* get(对象名)
Person person = new Person();
Class personClass = Person.class;
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field); public int 反射.day01.Person.age public java.lang.String 反射.day01.Person.name
}
Field names = personClass.getField("name");
names.set(person,"wyc");
Field cm = personClass.getDeclaredField("cm"); 可以获取私有的
cm.setAccessible(true); 获取或者设置私有成员变量 需要为true
Object o = cm.get(person);
System.out.println(o); 0
cm.set(person,15);
System.out.println(person); Person{age=0, name='wyc', cm=15}
获取构造方法
* Constructor<?>[ ] getConstructors() 获取所有public修饰的构造方法返回一个数组
* Constructor<T> getConstructor(类<?>... parameterTypes) 获取指定名称的 public修饰的构造方法
* Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 获取所有的构造方法,不考虑修饰符包括private的
* Constructor<?>[] getDeclaredConstructors() newInstance(构造参数) 用来创建对象
public static void main(String[] args) throws Exception {
Person person = new Person();
Class personClass = Person.class;
Constructor[] constructors = personClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor); } 打印所有构造方法
获取有参的构造方法
Constructor constructor = personClass.getConstructor(int.class, String.class);
System.out.println(constructor); public 反射.day01.Person(int,java.lang.String)
Object wyc = constructor.newInstance(15, "wyc"); 用来创建对象
System.out.println(wyc); Person{age=15, name='wyc', cm=0}}
获取成员方法
* Method[] getMethods()
* Method getMethod(String name, 类<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类<?>... parameterTypes) invoke(对象名),方法参数) 常用的 用来调用方法
public static void main(String[] args) throws Exception {
Person person = new Person();
Class personClass = Person.class;
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method); 也会打印父类的,
}
Method eat = personClass.getMethod("eat"); 无参数eat
eat.invoke(person);
Method eat1 = personClass.getMethod("eat", String.class); 参数是String.class
eat1.invoke(person, "屎"); 有参数
} 如果调用私有 set
获取全类名
* String getName()
Person person = new Person();
Class personClass = Person.class;
System.out.println(personClass.getName()); 打印全称 :反射.day01.Person
}
配置文件案列
1.通过反射获取配置文件中的配置 达到不改变该类的任何代码前提下创建任意类的对象,可以执行任意方法
1..创建一个配置文件promy.Properties 写入要创建的 类 名 , 该类中要执行的方法
className=reflect.day01.Person 必须写全 不然报错
methodName=eat
public static void main(String[] args) throws Exception {
创建与IO流有关的 集合用来 加载配置文件
Properties properties = new Properties();
获取类加载器
ClassLoader classLoader = ReflectTestmy.class.getClassLoader();
使用类加器获取配置文件输入流
InputStream is = classLoader.getResourceAsStream("promy.Properties");
使用properties集合 传入配置文件输入流 加载该配置文件
properties.load(is);
通过properties集合 用键获取值
String className=properties.getProperty("className");
String methodName=properties.getProperty("methodName");
使用反射 加载该类进入内存
Class cls = Class.forName(className);
创建该类的对象
Object obj = cls.newInstance();
获取该类的方法
Method eat = cls.getMethod("eat", String.class);
eat.invoke(obj,"屎"); 调用方法
}