今天学习java反射机制:
常见方法
关于反射,常用的有如下一些方法:
clazz.getDeclaredField(name);//获取指定的私有属性
clazz.getField(name);//获取指定的公有属性
clazz.getSimpleName();//获得类名
clazz.getConstructor(parameterTypes);//获取构造函数
clazz.getClassLoader();//获取类加载器
clazz.getComponentType();
clazz.getConstructors();//获取所有的共有的构造方法
clazz.getDeclaredConstructor(parameterTypes);//获取私有的指定参数的构造方法
clazz.getDeclaredFields();//获取所有的属性
clazz.getMethod(name, parameterTypes);//获取指定方法名的方法
clazz.getDeclaredMethods();//获取所有的方法
clazz.getDeclaredMethod(name, parameterTypes);//获取指定方法名的私有方法
运行私有方法
首先新建一个用于反射操作的类People
People.java
public class People {
private void say() {
System.out.println("=====saysay=======");
}
}
利用反射来运行该方法:
Class clazz = Class.forName("com.test.refelect.People");
// Class clazz = new People().getClass();
// Class clazz = People.class;
People people = (People) clazz.newInstance();
Method method = clazz.getDeclaredMethod("say",null);//得到私有的方法
//需要设置accessible为true否则会抛出
//can not access a member of class com.test.refelect.People with modifiers "private"
method.setAccessible(true);
method.invoke(people, null);//这句代码表示运行people对象的method方法
使用反射操作类属性
进一步,我们给People.java文件中添加如下属性和方法private String testChangeString = "aaabbbccaaddaa";
private String fruit;
private String name;
private int age;
private String[]address = new String[3];
public String getFruit() {
return fruit;
}
public void setFruit(String fruit) {
this.fruit = fruit;
}
public People(String name, int age, String[] address) {
this.name = name;
this.age = age;
this.address = address;
}
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;
}
public String[] getAddress() {
return address;
}
public void setAddress(String[] address) {
this.address = address;
}
public People() {
}
利用反射运行setName方法:
Method method = clazz.getMethod("setName",String.class)//由于setName是公有的方法,所以这里调用getMethod方法
method.invoke(people,(Object)(new String("小明")));
System.out.println(people.getName());
利用反射运行构造函数来new一个实例对象:
Constructor constructor = clazz.getConstructor(String.class,int.class,String[].class);//这里需要传入参数的类型
//这里需要将所有的参数转换成Object类型
People people2 = (People) constructor.newInstance(new Object[]{"xiaoming",22,new String[]{"china","shanxi","xi'an"}});
System.out.println(people2.getName()+people2.getAge()+people2.getAddress()[0]+people2.getAddress()[1]+people2.getAddress()[2]);
利用反射将testChangeString属性中的所有a改为b
Field field = clazz.getDeclaredField("testChangeString");
field.setAccessible(true);
field.set(people,field.get(people).toString().replace('a','b'));
System.out.println(field.get(people).toString());
利用反射更改属性的值:
Field fruitField = clazz.getDeclaredField("fruit");
fruitField.setAccessible(true);
fruitField.set(people,"apple");
System.out.println(fruitField.get(people));
method = clazz.getMethod("setFruit",String.class);
method.invoke(people,"banbanba");
System.out.println(clazz.getMethod("getFruit",null).invoke(people, null));
反射和可变参数
反射和可变参数结合使用,首先在People.java文件中添加如下方法:
private List<String> getStrings(String a,String b,String ... c) {
List<String>returnStr = new ArrayList<String>();
returnStr.add(a);
returnStr.add(b);
for (int i = 0; i < c.length; i++) {
returnStr.add(c[i]);
}
return returnStr;
}
利用反射运行发方法如下:
Class clazz = Class.forName("com.test.refelect.People");
People people = (People) clazz.newInstance();
@SuppressWarnings("unchecked")
Method method = clazz.getDeclaredMethod("getStrings",String.class,String.class,String[].class);
method.setAccessible(true);
@SuppressWarnings("unchecked")
List<String>list = (List<String>) method.invoke(people,new Object[]{"aaaa","bbbb",new String[]{"cccc","dddd","eee","fff"}});
// System.out.println(list.size());
for (String string : list) {
System.out.println(string);
}
内部类使用反射
下面我创建一个测试类,来演示如何正常或者通过反射实例化内部类,并且运行其中的方法。
People.java
package com.reflect.study;
public class People {
public void sayHello() {
System.out.println("hello world");
}
class InnerOne {
public void walk() {
System.out.println("i am walk");
}
}
// 公有内部类
public static class InnerTwo {
public void run() {
System.out.println("i am running");
}
}
// 私有内部类
private class InnerThree {
private String name;
public InnerThree(String name) {
super();
this.name = name;
}
private void stop(String address) {
System.out.println(name+"is stoping at "+address);
}
}
}
创建内部类实例
这里需要注意的是<font color='red'> 获取内部类构造方法时,需要将其外部类的类对象作为参数传进去,同样实例化内部类时,也需要将外部类对象作为参数传进</ftont>
// 实例化非静态内部类
InnerOne innerOne = new People().new InnerOne();
innerOne.walk();
// 实例化公有静态内部类
People.InnerTwo innerTwo = new People.InnerTwo();
innerTwo.run();
===================================================================================================
使用反射方式实例化内部类,并调用其方法
try {
Class innerOne = Class.forName("com.reflect.study.People$InnerOne");
Constructor innerOneConstructor = innerOne.getDeclaredConstructor(People.class);
System.out.println(innerOneConstructor);
Method walkMethod = innerOne.getDeclaredMethod("walk",null);
walkMethod.invoke(innerOneConstructor.newInstance(new People()),null);
// public static内部类
Class innerTwo = Class.forName("com.reflect.study.People$InnerTwo");
Method runMethod = innerTwo.getDeclaredMethod("run",null);
runMethod.invoke(innerTwo.newInstance(), null);
Class innerThree = Class.forName("com.reflect.study.People$InnerThree");
Constructor innerThreeConstructor = innerThree.getDeclaredConstructor(new Class[]{People.class,String.class});
Method stopMethod = innerThree.getDeclaredMethod("stop",String.class);
stopMethod.setAccessible(true);
stopMethod.invoke(innerThreeConstructor.newInstance(new Object[]{new People(),"小明"}),"大马路");
} catch (Exception e) {
e.printStackTrace();
}