关于java中的反射
理解反射:就是将类的各个组成部分封装为其他对象,这个就是反射机制。我们通过对生成类对象,获取类对象,使用类对象进行操作就是一个操作反射的过程。举个栗子:
先生成一个类对象
package org.example.doMain;/*
*@author wanghongyuan
*@Create 2021/1/24 17:15
*/
public class Person {
//成员变量
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
//构造方法
public Person(){
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
//成员方法
public void eat(){
}
}
三个阶段中对应生成类文件的三个方法
package org.example.Reflect;/*
*@author wanghongyuan
*@Create 2021/1/24 17:05
*/
import org.example.doMain.Person;
/*
关于反射
获取类的三种方式:
类在程序中有三个阶段,这三个阶段获取类的方法各有不同,分别是下面三种:
第一个阶段,这个阶段类还没有加载进内存,我们要获取这个类就需要手动将该类加载进内存
使用的方法是class.forName("类全名");类全名就是:包名.类名
这个阶段多用于配置文件中,将类名定义在配置文件中,读取文件,加载类。因为这个地方传的是一个字符串,在物理文件,配置文件读取的也是字符串。
第二个阶段,这个时候类已经加载进内存了,我们直接类名.class就可以获取到该类对象
使用的方法就是类.class,通过类名的属性class来获取
这个阶段多用于参数的传递。
第三个阶段,这个时候类已经加载进内存,并且生成了类对象,我们就可以通过类对象.getClass的方法来获取类对象
使用的方法就是对象.getClass,getClass()方法在Object类中定义了。
多用于对象的获取字节码方式
*/
public class reflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException {
//1.class.forName("类全名")
Class<?> cls1 = Class.forName("org.example.doMain.Person");
System.out.println(cls1);
//2.类.class
Class cls2 = Person.class;
System.out.println(cls2);
//3.对象.getClass
Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3);
//==比较三个对象
System.out.println(cls1==cls2);//true
System.out.println(cls1==cls3);//true
System.out.println(cls2==cls3);//true
/*
同一个字节码文件(*.class)在一次程序运行中,只会被加载一次
,不管是哪个阶段获取到的类对象,都是指向同一个字节码文件。
*/
}
}
获取成员变量们
package org.example.Reflect;/*
*@author wanghongyuan
*@Create 2021/1/24 19:41
*/
import org.example.doMain.Person;
import java.lang.reflect.Field;
/*
Class对象功能
获取功能:
1.获取成员变量们
Field[] getFields():获取所有public修饰的成员变量
Field getField(String name):获取指定名称的成员变量
Field[] getDeclaredFields()获取所有的成员变量,不考虑修饰符。
Field getDeclaredField(String name)获取指定名称的成员变量
获取这些方法做什么操作,常见的就两个:
1.设置值
set(Object)
2.获取值
get(Object)
3.忽略访问权限修饰符的安全检查
d.setAccessible(true);//暴力反射
2.获取构造方法们
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>...parameterTypes)
Constructor<T> getDeclaredConstructor(类<?>...parameterTypes)
Constructor<?>[] getDeclaredConstructors()
3.获取成员方法们
Method[] getMethods()
Method getMethod(String name,类<?>...parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name,类<?>...parameterTypes)
4.获取类名
String getName()
*/
public class ReflectDemo02 {
public static void main(String[] args) throws Exception {
//0. 获取一个Person的Class对象
Class personClass = Person.class;
System.out.println(personClass);
Field[] fields = personClass.getFields();
/*
1.获取成员变量们
Field[] getFields()
Field getField(String name)
Field[] getDeclaredFields()
Field getDeclaredField(String name)
*/
for (Field field : fields) {
System.out.println(field);
}
//Field getField(String name)
Field a = personClass.getField("a");
System.out.println(a);
//获取成员变量a的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
//设置a的值
a.set(p,"张三");
System.out.println(p);
System.out.println("===================");
/*
Field[] getDeclaredFields()
Field getDeclaredField(String name)
*/
//Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符。
Field[] df = personClass.getDeclaredFields();
for (Field field : df) {
System.out.println("df:"+field);
}
//Field getDeclaredField(String name)
Field d = personClass.getDeclaredField("d");
System.out.println(d);
//忽略访问权限修饰符的安全检查
d.setAccessible(true);//暴力反射
Object value2 = d.get(p);
//d设置值,里面传对象名,和设置的值
d.set(p,"赵四");
System.out.println(p);
}
}
·获取构造方法们
package org.example.Reflect;/*
*@author wanghongyuan
*@Create 2021/1/24 20:55
*/
import org.example.doMain.Person;
import org.mortbay.jetty.security.Constraint;
import java.lang.reflect.Constructor;
/*
2.获取构造方法们
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>...parameterTypes)
Constructor<T> getDeclaredConstructor(类<?>...parameterTypes)
Constructor<?>[] getDeclaredConstructors()
Constructor:构造方法
创建对象:
T newInstance(Object...initargs)
*/
public class ReflectDemo03 {
public static void main(String[] args) throws Exception {
//获取Person的class对象
Class<Person> personClass = Person.class;
Constructor cs = personClass.getConstructor(String.class,int.class);
//创建对象:
Object person = cs.newInstance("张三", 23);
System.out.println(person);
System.out.println("----------------");
//创建一个空参的对象
Constructor cs1 = personClass.getConstructor();
//创建对象:
Object person1 = cs1.newInstance();
System.out.println(person1);
//如果使用空参数构造方法创建对象,操作可以简化:可以使用class对象里面的专门方法newInstance
cs.setAccessible(true);//暴力破解,可以访问私有方法
Person o = personClass.newInstance();
System.out.println(o);
}
}
获取成员方法们
package org.example.Reflect;/*
*@author wanghongyuan
*@Create 2021/1/24 21:57
*/
import org.example.doMain.Person;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/*
3.获取成员方法们
Method[] getMethods()
Method getMethod(String name,类<?>...parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name,类<?>...parameterTypes)
执行方法:
Object invoke(Object obj(真实的对象),Object...args(方法的实际参数列表))
*/
public class ReflectDemo04 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<Person> personClass = Person.class;
//Method getMethod(String name,类<?>...parameterTypes)获取指定名称和指定参数列表的一个方法
Method eat = personClass.getMethod("eat");
Person p = new Person();
//执行方法
eat.invoke(p);//只传一个对象就可以了,因为这个方法没有参数
//p.eat();
//加个参数在方法中
Method eat1 = personClass.getMethod("eat", String.class);
eat1.invoke(p,"汉堡");
System.out.println("----------------------------");
//获取所有public修饰的方法,不止是自己创建的方法,还有Object的方法也在里面
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
//获取方法的名称
String name = method.getName();
System.out.println(name);
//method.setAccessible(true);//暴力反射,可以访问私有方法
}
//获取类名
String className = personClass.getName();
System.out.println(className);//org.example.doMain.Person
}
}
```