Java允许从配置文件中读取类文件,从类文件(*.class)中反射类的成员变量,成员方法,构造方法,然后直接调用。
反射一般用来开发框架,比如写好xml配置文件,然后封装好一些反射用的程序就可以做出框架。
以下是几种常见的反射用法。
1,反射类的构造方法
package test;
import java.lang.reflect.Constructor;
public class ReflectTest1 {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("test.ForTest");//关键就是可以弄字符串这里可以从xml中获取,具体怎么做,可以用一些大公司做的现成的jar包来实现对xml的查询和修改操作,相关技术可以百度 xml解析技术。一个例子: ForTest tst = (ForTest)cls.newInstance();//这样也可以调用无参构造函数 tst.showPrivField(); Constructor<?> c0 = cls.getConstructor();//获取公有无参构造函数, 括号里面加个null效果一样 ForTest tst0 = (ForTest)c0.newInstance();//括号里面加个null效果一样 tst0.showPrivField(); Constructor<?> c = cls.getDeclaredConstructor(String.class);//可获取私有构造函数 c.setAccessible(true);//使可以访问私有 ForTest tst1 = (ForTest)c.newInstance("ami"); tst1.showPrivField(); }}
package test;
public class ForTest {
private String str = "wowowo"; private static ForTest privField = new ForTest("me"); public ForTest() {} private ForTest(String str) { this(); } public void setPrivField(String str1) { this.privField.str = str1; } public void showPrivField() { System.out.println(privField.privField.privField.privField==privField.privField); }}
2,反射类的其他方法
Class cls = Class.forName("**.**.**");
Method method = cls.getMethod("方法名",...方法参数类型);//第二个为可变参数,数组类型的用 类似int[].class这种方式
int[] i = (int[])method.invoke(指定方法所属对象,...方法参数); //直接跑方法 invoke:援引的意思,返回值的类型需要强转再接收。
获取私有方法要用cls.getDeclaredMethod(……)而非cls.getMethod,并且加上method.setAccessible(true);
获取的静态方法invoke时是可以传null给对象参数的。
获取的main方法,invoke的第二个参数位置由于main方法的参数是String[],而invoke第二个参数是可变参数,所以如果传一个String[]给invoke会被解析成多个字符串对象,因此会报main方法参数过多。
解决方法一 利用其只解析一次的特点传递new Object[]{new String[]{"",""}},只解析一次就会解析出来一个String[]对象。
解决方法二 是传一个 (Object)new String[]{""}
3,反射类的字段(成员变量)
Person p = new Person();
Class cls = Class.forName("**.**.**");
Field f = cls.getField("name");
Object obj = f.get(p);//获取对象p中该字段的值
Class type = f.getType();//可以获得对象的类型
if(type.equals(String.class)){
String svalue = (String)value;//
}
f.set(p,"xxxxxxxx");//可以设置字段的值
Field pw= cls.getDeclaredField("password");//获取私有成员变量
pw.setAccessible(true);//打开私有的权限
和静态方法不同,静态成员变量get的时候get后边的参数也要传对象。这个有待验证