在写java中,我们可以通过new关键字来创建一个对象。但是呢,凡事没有绝对。同样地,我们也可以通过别的方法来构造一个对象。这个方法就是:反射。
这篇文章通过8个Demo()方法来演示反射常用的几种方法:
- class.forName():传入类路径、动态反射生成一个相应类的Class对象
- class.newInstance():顾名思义,通过反射得到一个对象。
- class.getConstructors():获得该类的构造器数组
- class.getDeclaredFields():获得类属性数组
- class.getMethods():获得类方法数组
- class.getClassLoader():获得该类的类加载器
- method.invoke(class.newInstance())调用该对象的一个方法
Person类的定义
class Person {
private int age;
private String name;
public Person() {
}
public Person(int age,String name) {
this.age = age;
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}
接口ActionInterface的声明
interface ActionInterface {
public void walk(int m);
}
SuperMan类,继承自Person,实现ActionInterface接口的walk(int m)方法。
class SuperMan extends Person implements ActionInterface{
private boolean BlueBriefs;
public void fly() {
System.out.println("超人会飞耶~");
}
public void setBlueBriefs(boolean blueBriefs) {
this.BlueBriefs = blueBriefs;
}
public boolean isBlueBriefs() {
return BlueBriefs;
}
@Override
public void walk(int m) {
System.out.println("超人会走耶~~走了" + m + "米就走不动了!");
}
}
测试类:八个Demo()方法
package reflectLearning;
import java.lang.reflect.*;
/**
* Created by Nanguoyu on 2016/4/21.
*/
public class ReflectLearning {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException {
demo1();
System.out.println("==============================================");
demo2();
System.out.println("==============================================");
demo3();
System.out.println("==============================================");
demo4();
System.out.println("==============================================");
demo5();
System.out.println("==============================================");
demo6();
System.out.println("==============================================");
demo7();
System.out.println("==============================================");
demo8();
System.out.println("==============================================");
}
//Demo1.通过java反射机制得到类的包名和类名
public static void demo1() {
Person person = new Person();
System.out.println("Demo1:包名:" + person.getClass().getPackage().getName() + "," + "完整类名:" + person.getClass().getName());
}
//Demo2.通过Class类的静态方法forName()来动态反射生成一个相应类型的Class
public static void demo2() throws ClassNotFoundException {
//定义两个类型都未知的Class,设置初值为null,看看如何给它们赋值成Person类
Class<?> class1 = null;
Class<?> class2 = null;
//写法1,可能抛出ClassNotFoundException
class1 = Class.forName("reflectLearning.Person");
System.out.println("Demo2:(写法1)包名:" + class1.getPackage().getName() + ","
+ "完整类名:" + class1.getName());
//写法2
class2 = Person.class;
System.out.println("Demo2:(写法2)包名:" + class2.getPackage().getName() + ","
+ "完整类名:" + class2.getName());
}
/**
* demo3:通过java反射机制,用class创建类对象【这也就是反射存在的意义所在】
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void demo3() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class<?> class1 = null;
class1 = Class.forName("reflectLearning.Person");
//由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数
Person person = (Person) class1.newInstance();
person.setAge(20);
person.setName("SmileDay");
System.out.println("Demo3:" + person.getName() + ":" + person.getAge());
}
/**
* demo4:通过java反射机制得到一个类的构造函数,并实现创建带参实例对象
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws InstantiationException
*/
public static void demo4() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> class1 = null;
Person person1 = null;
Person person2 = null;
class1 = Class.forName("reflectLearning.Person");
//得到一系列构造函数集合
Constructor<?>[] constructors = class1.getConstructors();
//通过 无参 构造函数来反射生成一个对象
person1 = (Person) constructors[0].newInstance();
person1.setName("I'm the none param Body");
person1.setAge(18);
//通过 有参 构造函数来反射生成一个对象
person2 = (Person) constructors[1].newInstance(20,"I'm the second param Body");
System.out.println("Demo4:" + person1.getName() + ":" + person1.getAge());
System.out.println("Demo4:" + person2.getName() + ":" + person2.getAge());
}
/**
* Demo5: 通过Java反射机制操作成员变量, set 和 get
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchFieldException
*/
public static void demo5() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class<?> class1 = null;
class1 = Class.forName("reflectLearning.Person");
Object obj = class1.newInstance();
Field personNameField = class1.getDeclaredField("name");
//因为name域属性为private,故要设置为true,方可对其进行操作。
personNameField.setAccessible(true);
personNameField.set(obj,"大魔王");
System.out.println("Demo5:修改属性之后得到的属性变量的值:" + personNameField.get(obj));
//通过Class的getDeclaredFields()方法来获得一个属性数组
Field[] fields = class1.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
fields[i].set(obj,"啦啦啦");
System.out.println("利用之后得到的结果为:" + fields[i].get(obj));
}
}
/**
* 通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等
* @throws ClassNotFoundException
*/
public static void demo6() throws ClassNotFoundException {
Class<?> class1 = null;
class1 = Class.forName("reflectLearning.SuperMan");
//取得父类名称
Class<?> superClass = class1.getSuperclass();
System.out.println("Demo6:SuperMan类的父类名:" + superClass.getName());
System.out.println("=========================================");
//通过Class的getDeclaredFields()方法来获得一个属性数组
Field[] fields = class1.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println("类中的成员:" + fields[i]);
}
System.out.println("=========================================");
//通过Class的getMethods()方法来获得一个方法数组
Method[] methods = class1.getMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println("Demo6:取得SuperMan类的方法:");
System.out.println("函数名:" + methods[i].getName());
System.out.println("函数返回类型:" + methods[i].getReturnType());
System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));
}
System.out.println("=========================================");
//取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到
Class<?> interfaces[] = class1.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
System.out.println("实现的接口名:" + interfaces[i].getName());
}
}
/**
* Demo7: 通过Java反射机制调用类方法
* @throws ClassNotFoundException
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
*/
public static void demo7() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class<?> class1 = null;
class1 = Class.forName("reflectLearning.SuperMan");
System.out.println("Demo7:\n调用无参方法fly():");
Method method = class1.getMethod("fly");
method.invoke(class1.newInstance());
/*
*通过调用Class的getMethod(String methodName,Class<?> class)
*来获得一个walk(int m)方法。
*/
System.out.println("调用有参数方法walk(int m):");
method = class1.getMethod("walk",int.class);
method.invoke(class1.newInstance(),100);
}
/**
* 通过Java反射机制得到类加载器信息
* @throws ClassNotFoundException
*
* Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
* Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类
* AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
*/
public static void demo8() throws ClassNotFoundException {
Class<?> class1 = null;
class1 = Class.forName("reflectLearning.SuperMan");
String nameString = class1.getClassLoader().getClass().getName();
System.out.println("Demo8:类加载器名:" + nameString);
}
}
总结:Class.forName()方法,是反射的入口,只有当执行了这个方法,得到了一个class对象,那么接着就可以获取所对应的类、对象的各种数据:构造器数组、方法数组、属性数字、父类数组、接口、类加载器等信息。