反射:就是通过class文件对象,去使用该文件中的成员变量、构造方法、成员方法。
Class类:
获取class文件对象的方式:
A:Object类对象.getClass()方法
B:数据类型的静态属性class。
C:Class类中静态方法
public static Class forName(String className);
一般我们使用第三种方式来获取,因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。安全性。
例子:
//方式一:Object类对象.getClass()方法
Person p = new Person();
Class class_p1 = p.getClass();
String name = class_p1.getName();//类的权限定名
System.out.println(name);
输出结果为:Test.Demo.Person
//方式二:数据类型的静态属性class。
Class class_p3 = Person.class;
System.out.println(class_p3==class_p1);//true 因为字节码文件只有一个,所以是true。
/*方式三:Class类中静态方法
public static Class forName(String className)*/
Class class_p4 = Class.forName("com.hwua.ReflectDemo.Person");
System.out.println(class_p4==class_p3); //结果为true
//获取构造方法
/*
* public Constructor[] getConstructors():获得所有公共的构造方法 只会返回带有public所修饰的
* public Constructor[] getDeclaredConstructors():获得所有的构造方法
* */
例子如下:
首先得有个person类以下是person类
package Test.Demo;
public class Person {
private String name;
int age;
public String address;
public Person() {
}
Person(String name){
this.name = name;
}
private Person(String name, int age, String address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
}
}
下面是例子:
Class cl = Class.forName("Test.Demo.Person");
Constructor[] constructors = cl.getConstructors();//这里只返回public修饰的构造方法
for (Constructor c : constructors) {
System.out.println(c); // 输出为public Test.Demo.Person()(这里只定义了一个public的构造方法)
}
Constructor[] declaredConstructors = cl.getDeclaredConstructors();
for (Constructor cc : declaredConstructors) {
System.out.println(cc);
}
这里输出的结果为:
private Test.Demo.Person(java.lang.String,int,java.lang.String)
Test.Demo.Person(java.lang.String)
public Test.Demo.Person()
获取单个的方法,并调用:
public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有的;
参数表示:你要获取的构造方法的构造参数个数以及数据类型的class字节码文件对象。
例子:
Constructor con = cl.getDeclaredConstructor(String.class,int.class,String.class);//返回的是构造方法的对象
con.setAccessible(true);//暴力破解,设置为true的时候,私有的东西就能访问了
System.out.println(con);
输出结果为:
privateTest.Demo.Person(java.lang.String,int,java.lang.String)
使用此Constructor对象表示的构造方法来创建该构造方法的声明类的实例,并使用指定的初始化参数进行初始化实例。
Object newInstance = con.newInstance("张三",1,"中国");
Person p = (Person) newInstance;
System.out.println(p);
输出结果为:
Person [name=张三, age=1, address=中国]
例子如下:
Class cl = Class.forName("Test.Demo.Person");
//获取所有的成员变量
//getFields()和getDeclaredFields();
Field[] fields = cl.getFields(); //获取所有公共字段
for (Field field : fields) {
System.out.println(field);
}
输出结果为:
public java.lang.String Test.Demo.Person.address
获取所有字段:
Field[] declaredFields = cl.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field);
}
输出结果为:
private java.lang.String Test.Demo.Person.name
int Test.Demo.Person.age
public java.lang.String Test.Demo.Person.address
//比如:我要获取address并赋值
Field field = cl.getField("address");
//只是获得了变量,你要对变量进行赋值,那么你要考虑到给哪个对象的变量进行赋值
field.set(obj, "北京");
System.out.println(obj);
输出结果为:
Person [name=null, age=0, address=北京]
获取所有方法
获取公共:getMethods():获取自己的以及父类的公共方法
获取所有:getDeclaredMethods():获取自己的所有的方法
代码如下:
Method[] methods = cl.getMethods();//这里得到得到的是所有公共的方法,包括自己的和父类的
for (Method method : methods) {
System.out.println(method);
}
输出结果如下:
public java.lang.String Test.Demo.Person.toString()
public java.lang.String Test.Demo.Person.getAddress()
public java.lang.String Test.Demo.Person.getName()
public int Test.Demo.Person.getAge()
public void Test.Demo.Person.setAddress(java.lang.String)
//这是父类object类的方法
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
获取自己的所有方法:
Method[] declaredMethods = cl.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
输出结果为:
public java.lang.String TestDemo.Person.toString()
public java.lang.String Test.Demo.Person.getAddress()
public java.lang.String Test.Demo.Person.getName()
private void Test.Demo.Person.setName(java.lang.String)
public int Test.Demo.Person.getAge()
public void Test.Demo.Person.setAddress(java.lang.String)
void Test.Demo.Person.setAge(int)
获取单一方法并执行
Constructor con = cl.getConstructor();
Object obj = con.newInstance();
Method m = cl.getMethod("setAddress", String.class);
m.invoke(obj, "北海");//第一参数是对象,第二参数是调用方法参数数据
Method method = cl.getMethod("toString");//得到toString()方法
Object invoke = method.invoke(obj);
System.out.println(invoke);
System.out.println("------------------------");
Method declaredMethod = cl.getDeclaredMethod("setName", String.class);//获取私有的方法
declaredMethod.setAccessible(true);//暴力破解反射
declaredMethod.invoke(obj, "阿达");
invoke = method.invoke(obj);
System.out.println(invoke);
这两个代码的输出结果是:
Person [name=null, age=0, address=北海]
Person [name=阿达, age=0, address=北海]
本章内容暂时补充到这。