反射机制是什么
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射机制能做什么
反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法;
在运行时调用任意一个对象的方法;
生成动态代理。
反射机制的相关API
通过一个对象获得完整的包名和类名
package reflect;
/**
* ReflectDemo1
* 1. 通过一个对象获得完整的包名和类名
* 2.实例化Class类对象
* Created by heqianqian on 2017/4/16.
*/
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
//通过一个对象获得完整的包名和类名
ReflectDemo1 reflectDemo1 = new ReflectDemo1();
System.out.println(reflectDemo1.getClass().getName());
//实例化Class类对象
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;
class1 = Class.forName("reflect.ReflectDemo1");// 一般采用这种形式
class2 = new ReflectDemo1().getClass();
class3 = ReflectDemo1.class;
System.out.println("类名称 " + class1.getName());
System.out.println("类名称 " + class2.getName());
System.out.println("类名称 " + class3.getName());
}
}
获取一个对象的父类与实现的接口
package reflect;
import java.io.Serializable;
/**
* ReflectDemo2
* 获取一个对象的父类与实现的接口
* Created by heqianqian on 2017/4/16.
*/
public class ReflectDemo2 implements Serializable,Runnable{
public static void main(String[] args) throws ClassNotFoundException {
Class<?> class1 = Class.forName("reflect.ReflectDemo2");
//获得父类
Class<?> parent = class1.getSuperclass();
System.out.println("Parent:"+parent.getName());
//获得实现的接口
Class<?>[] interfaces = class1.getInterfaces();
System.out.println("Interfaces: ");
for (Class<?> cl:interfaces){
System.out.println(cl.getName());
}
}
@Override
public void run() {
}
}
通过反射机制实例化一个类的对象
package reflect;
import reflect.entity.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* ReflectDemo3
* 通过反射机制实例化一个类的对象
* Created by heqianqian on 2017/4/16.
*/
public class ReflectDemo3 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class<?> class1 = null;
class1 = Class.forName("reflect.entity.User");
// 1.实例化[默认]构造方法,调用set赋值
User user = (User) class1.newInstance();
user.setName("heqianqian");
user.setAge(20);
System.out.println(user);
//2.获取所有构造函数
Constructor<?> cons[] = class1.getConstructors();
for (int i=0;i<cons.length;i++){
Class<?> clazzs[] = cons[i].getParameterTypes();
System.out.print("cons["+i+"](");
for (int j=0;j<clazzs.length;j++){
if (j==clazzs.length-1){
System.out.print(clazzs[j].getName());
}else{
System.out.print(clazzs[j].getName() + ",");
}
}
System.out.println(")");
}
user = (User) cons[0].newInstance(20,"Lucy");
System.out.println(user);
user = (User) cons[1].newInstance("Tom");
System.out.println(user);
}
}
获取某个类的全部属性
package reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* ReflectDemo4
* 获取某个类的全部属性
* Created by heqianqian on 2017/4/16.
*/
public class ReflectDemo4 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz = Class.forName("reflect.entity.User");
System.out.println("===============本类属性===============");
// 取得本类的全部属性
Field[] fields = clazz.getDeclaredFields();
showField(fields);
// 取得实现的接口或者父类的属性
System.out.println("==========实现的接口或者父类的属性==========");
Field[] fields1 = clazz.getFields();
showField(fields1);
}
private static void showField(Field[] fields){
for (int i = 0; i < fields.length; i++) {
// 权限修饰符
int mod = fields[i].getModifiers();
String priv = Modifier.toString(mod);
// 属性类型
Class<?> type = fields[i].getType();
System.out.println(priv + " " + type.getName() + " " + fields[i].getName() + ";");
}
}
}
获取某个类的全部方法
package reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* ReflectDemo5
* 获取某个类的全部方法
* Created by heqianqian on 2017/4/16.
*/
public class ReflectDemo5 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz = Class.forName("reflect.entity.User");
Method[] methods = clazz.getMethods();
for (int i=0;i<methods.length;i++){
String priv = Modifier.toString(methods[i].getModifiers());
String type = methods[i].getReturnType().getName();
String name = methods[i].getName();
System.out.print(priv+" "+type+" " + name+" (");
//获取方法参数
Class<?>[] params = methods[i].getParameterTypes();
for (int j=0;j<params.length;++j){
System.out.print(params[j].getName()+" args"+j);
if (j<params.length-1){
System.out.print(",");
}
}
//获取异常
Class<?>[] exceptionTypes = methods[i].getExceptionTypes();
if (exceptionTypes.length>0){
System.out.print(") throws ");
for (int z=0;z<exceptionTypes.length;++z){
System.out.print(exceptionTypes[z].getName()+" ");
if (z<exceptionTypes.length-1){
System.out.print(",");
}
}
}else{
System.out.print(")");
}
System.out.println();
}
}
}
通过反射机制调用某个类的方法
package reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* ReflectDemo6
* 通过反射机制调用某个类的方法
* Created by heqianqian on 2017/4/16.
*/
public class ReflectDemo6 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class<?> clazz = Class.forName("reflect.ReflectDemo6");
//调用没有参数的方法
Method method = clazz.getMethod("reflect1");
method.invoke(clazz.newInstance());
//调用有参数的方法
method = clazz.getMethod("reflect2",String.class,int.class);//参数顺序不可调换
method.invoke(clazz.newInstance(),"heqianqian",20);
}
public void reflect1(){
System.out.println("Java 反射机制 - 调用某个类的方法1.");
}
public void reflect2(String name,int age){
System.out.println("Java 反射机制 - 调用某个类的方法2.");
System.out.println("age -> " + age + ". name -> " + name);
}
}
通过反射机制操作某个类的属性
package reflect;
import java.lang.reflect.Field;
/**
* ReflectDemo7
* 通过反射机制操作某个类的属性
* Created by heqianqian on 2017/4/16.
*/
public class ReflectDemo7 {
private String property = null;
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class<?> clazz = Class.forName("reflect.ReflectDemo7");
Object o = clazz.newInstance();
Field field = clazz.getDeclaredField("property");
//可以直接对 private 的属性赋值
field.setAccessible(true);
field.set(o,"Java反射机制");
System.out.println(field.get(o));
System.out.println(((ReflectDemo7)o).getProperty());
}
public String getProperty() {
return property;
}
}
反射机制的动态代理
package reflect.handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* MyInvocationHandler
* 完成代理的具体操作
* Created by heqianqian on 2017/4/16.
*/
public class MyInvocationHandler implements InvocationHandler {
private Object object;
public Object bind(Object object) {
this.object = object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj = method.invoke(this.object, args);
return obj;
}
}
package reflect;
/**
* Subject
* Created by heqianqian on 2017/4/16.
*/
public interface Subject {
public String say(String name, int age);
}
package reflect;
/**
* RealSubject
* Created by heqianqian on 2017/4/16.
*/
public class RealSubject implements Subject {
public String say(String name, int age){
return name + " " + age;
}
}
package reflect;
import reflect.handler.MyInvocationHandler;
/**
* ReflectDemo8
* 反射机制的动态代理
* <p>
* 在java中有三种类类加载器。
* <p>
* 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
* <p>
* 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
* <p>
* 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
* <p>
* 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
* <p>
* Created by heqianqian on 2017/4/16.
*/
public class ReflectDemo8 {
public static void main(String[] args) throws Throwable {
// 获取类加载器的方法
//ReflectDemo8 reflectDemo8 = new ReflectDemo8();
//System.out.println("类加载器 " + reflectDemo8.getClass().getClassLoader().getClass().getName());
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject) demo.bind(new RealSubject());
String info = sub.say("heqianqian", 20);
System.out.println(info);
}
}
反射机制的应用实例
在泛型为Integer的ArrayList中存放一个String类型的对象。
package reflect.example;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* ListReflect
* 在泛型为Integer的ArrayList中存放一个String类型的对象。
* Created by heqianqian on 2017/4/16.
*/
public class ListReflect {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List<Integer> list = new ArrayList<Integer>();
Method method = list.getClass().getMethod("add",Object.class);
method.invoke(list,"add string");
System.out.println(list.get(0));
list.add(1);
list.add(2);
System.out.println(list);
}
}
通过反射取得并修改数组的信息
package reflect.example;
import java.lang.reflect.Array;
/**
* ArrayReflect
* 通过反射取得并修改数组的信息
* Created by heqianqian on 2017/4/16.
*/
public class ArrayReflect {
public static void main(String[] args) {
int []arr = {1,2,3,4,5};
Class<?> componentType = arr.getClass().getComponentType();
System.out.println("数组类型:"+componentType.getName());
System.out.println("数组长度:"+ Array.getLength(arr));
System.out.println("数组的第一个元素:"+Array.get(arr,0));
Array.set(arr,0,100);
System.out.println("修改后的一个元素:"+ Array.get(arr,0));
}
}
通过反射机制修改数组的大小
package reflect.example;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* ArrayReflect2
* 通过反射机制修改数组的大小
* Created by heqianqian on 2017/4/16.
*/
public class ArrayReflect2 {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6};
int[] darr = (int[]) arrInc(arr, 10);
printArr(darr);
String[] str = {"he", "qian", "qian"};
printArr(arrInc(str, 20));
}
/**
* 修改数组大小
*
* @param obj 原数组
* @param len 目标大小
* @return 修改后的数组
*/
private static Object arrInc(Object obj, int len) {
Class<?> clazz = obj.getClass().getComponentType();
Object instance = Array.newInstance(clazz, len);
int co = Array.getLength(obj);
System.arraycopy(obj, 0, instance, 0, co);
return instance;
}
private static void printArr(Object obj) {
Class<?> clazz = obj.getClass();
if (!clazz.isArray()) {
return;
}
System.out.println("数组长度:" + Array.getLength(obj));
for (int i = 0; i < Array.getLength(obj); i++) {
System.out.print(Array.get(obj, i) + " ");
}
}
}
将反射机制应用于工厂模式
package reflect.example;
import reflect.entity.Fruit;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* FactoryReflect
* 将反射机制应用于工厂模式
* <p>
* 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。
* Java 工厂模式可以参考
* http://baike.xsoftlab.net/view/java-factory-pattern
* 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
* 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
* java 读取 properties 配置文件 的方法可以参考
* http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file
* <p>
* Created by heqianqian on 2017/4/16.
*/
public class FactoryReflect {
public static void main(String[] args) throws IOException {
Fruit fruit = null;
Properties properties = new Properties();
InputStream inputStream = FactoryReflect.class.getClassLoader().getResourceAsStream("reflect/example/factory.properties");
properties.load(inputStream);
//fruit = FruitFactory.newInstance("reflect.entity.Orange");
//通过读取配置文件而不用写全包名
fruit = FruitFactory.newInstance((String) properties.get("apple"));
fruit.eat();
}
}
package reflect.entity;
/**
* Fruit
* Created by heqianqian on 2017/4/16.
*/
public interface Fruit {
void eat();
}
package reflect.entity;
/**
* Apple
* Created by heqianqian on 2017/4/16.
*/
public class Apple implements Fruit {
@Override
public void eat() {
System.out.println("eat an apple");
}
}
package reflect.entity;
/**
* Orange
* Created by heqianqian on 2017/4/16.
*/
public class Orange implements Fruit {
@Override
public void eat() {
System.out.println("eat an orange");
}
}
package reflect.example;
import annotation.meta.base.target.ClassNum;
import reflect.entity.Fruit;
/**
* FruitFactory
* Created by heqianqian on 2017/4/16.
*/
public class FruitFactory {
public static Fruit newInstance(String name) {
Fruit fruit = null;
try {
fruit = (Fruit) Class.forName(name).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return fruit;
}
}
factory.properties
apple=reflect.entity.Apple
orange=reflect.entity.Orange
参考文章: