反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射机制主要提供了以下功能: 

  • 在运行时判断任意一个对象所属的类;

  • 在运行时构造任意一个类的对象;

  • 在运行时判断任意一个类所具有的成员变量和方法;

  • 在运行时调用任意一个对象的方法;

  • 生成动态代理。

package com.elex.test;

import org.junit.Test;

import java.io.Serializable;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

/**
* ========================================================================
* - Class: ReflectTest
* - Description: demo
* - Author: quliangliang
* - Email: quliangliang@elex-tech.com
* - Created: 2017/6/9 16:28
* - (C) Copyright 2008 - 2017, www.elex-tech.com All Rights Reserved.
* ========================================================================
*/
public class ReflectTest implements Serializable{
private String paramStr ="str";
private Integer paramInteger = 0;
private Long paramLong = 0l;
private int paramInt = 0;

@Override
public String toString() {
return paramStr+paramInteger+paramLong+paramInt;
}

public static void main(String[] args) throws Exception{
//获取所有构造方法及参数
Class<?> clazz = Class.forName("com.elex.test.ReflectTest");
Constructor<?> constructors[] = clazz.getConstructors();
for(int i=0;i<constructors.length;i++){
System.out.println("构造方法"+i+constructors[i].getName());
Class<?> typeParameters[] = constructors[i].getParameterTypes();
for(int j=0;j<typeParameters.length;j++){
System.out.println("参数"+j+"类型为"+typeParameters[j].getName());
}
}
ReflectTest rt = (ReflectTest)constructors[0].newInstance("str",0l,new Object());
System.out.println(rt);
}

public ReflectTest() {
}

//通过一个对象获得完整的包名和类名
@org.junit.Test
public void test1(){
ReflectTest reflectTest = new ReflectTest();
System.out.println(reflectTest.getClass().getName());
}
//实例化Class类对象
@Test
public void test2() throws ClassNotFoundException {
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;
class1 = Class.forName("com.elex.test.ReflectTest");
class2 = new ReflectTest().getClass();
class3 = ReflectTest.class;
System.out.println("类名"+class1.getName());
System.out.println("类名"+class2.getName());
System.out.println("类名"+class3.getName());

}
//获取一个类父类和所有接口
@Test
public void test3() throws ClassNotFoundException {
Class<?> clazz = Class.forName("com.elex.test.ReflectTest");
String superClass =clazz.getSuperclass().getName();
System.out.println("父类为"+superClass);

Class<?>[] interfices = clazz.getInterfaces();
for (Class c : interfices){
System.out.println("实现的接口有"+c.getName());
}
}


//获取某个类的全部属性
@Test
public void test4() throws Exception {
Class<?> clazz = Class.forName("com.elex.test.ReflectTest");
Field[] declaredFields = clazz.getDeclaredFields();//返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
// clazz.getFields();//返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
for(int i=0;i<declaredFields.length;i++){
int modifiers = declaredFields[i].getModifiers();//得到访问修饰符
Class<?> type = declaredFields[i].getType();//得到字段类型
String name = declaredFields[i].getName();//字段名称
System.out.println(modifiers +" " + type +" " + name );
}
}

//获取某个类的全部方法
@Test
public void test5() throws Exception{
Class<?> clazz = Class.forName("com.elex.test.ReflectTest");
Method[] methods = clazz.getMethods();//得到所有方法
for(int i=0;i<methods.length;i++){
int modifiers = methods[i].getModifiers();//方法修饰符
Class<?> returnType = methods[i].getReturnType();//返回值类型
String name = methods[i].getName();//方法名
System.out.print(modifiers +" " + returnType.toString() +" " + name +"(");
Class<?>[] parameterTypes = methods[i].getParameterTypes();
for(int j = 0;j<parameterTypes.length;j++){
System.out.print(parameterTypes[j].getName()+" arg"+j);
if (j < parameterTypes.length - 1) {
System.out.print(",");
}
}
Class<?>[] exceptionTypes = methods[i].getExceptionTypes();//得到异常
for(int n = 0;n<exceptionTypes.length;n++){
System.out.print(" " + exceptionTypes[n].getName() + " ");
if (n < exceptionTypes.length - 1) {
System.out.print(",");
}
}
System.out.print(")");
}

}

//通过反射机制调用某个类的方法
@Test
public void test6() throws Exception{
Class<?> clazz = Class.forName("com.elex.test.ReflectTest");
Method sout1 = clazz.getMethod("sout1",String.class,String.class);
sout1.invoke(clazz.newInstance(),"key","value");
}

//通过反射机制操作某个类的属性
@Test
public void test7() throws Exception{
Class<?> clazz = Class.forName("com.elex.test.ReflectTest");
Object obj = clazz.newInstance();
Field param = clazz.getDeclaredField("paramStr");
param.set(obj,"str参数");
System.out.println(obj);

}






//动态代理
@Test
public void test8(){
// MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
// RealSubject realSubject = (RealSubject)myInvocationHandler.bind(new RealSubject());
// realSubject.say("haha");

MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject) demo.bind(new RealSubject());
String info = sub.say("Rollen", 20);
System.out.println(info);
}

//向arraylist<Integer>中加入String
@Test
public void test9() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List<Integer> list = new ArrayList<Integer>();
Method method = list.getClass().getMethod("add", Object.class);
method.invoke(list,"Java反射机制");
System.out.println(list.get(0));
}
//通过反射取得并修改数组的信息
@Test
public void test10(){
int[] temp = { 1, 2, 3, 4, 5 };
Class<?> demo = temp.getClass().getComponentType();
System.out.println("数组类型: " + demo.getName());
System.out.println("数组长度 " + Array.getLength(temp));
System.out.println("数组的第一个元素: " + Array.get(temp, 0));
Array.set(temp, 0, 100);
System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
}

//将反射机制应用于工厂模式
@Test
public void test11() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
Subject subject = Factory.getInstance("com.elex.test.RealSubject");
System.out.println(subject.say("haha",21));
}


public void sout1(String str1,String str2){
System.out.println(str1+":"+str2);
}

class User {
private int age;
private String name;
public User() {
super();
}
public User(String name) {
super();
this.name = name;
}
public User(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
}
}

//Java反射动态代理
/*interface Subject{
void say(String str);
}
class RealSubject implements Subject{
public void say(String str) {
System.out.println("输出"+str);
}
}
class MyInvocationHandler implements InvocationHandler{
private Object object;
public Object bind(Object object){
this.object = object;
//返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
//newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
return Proxy.newProxyInstance(object.getClass().getClassLoader(),this.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.object = object;
return method.invoke(object,args);
}
}*/


//定义项目接口
interface Subject {
public String say(String name, int age);
}
// 定义真实项目
class RealSubject implements Subject {
public String say(String name, int age) {
return name + " " + age;
}
}
class MyInvocationHandler implements InvocationHandler {
private Object obj = null;
public Object bind(Object obj) {
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//当执行真正要调用的方法时会走这个方法
Object temp = method.invoke(this.obj, args);
return temp;
}
}


//反射工厂类
class Factory{
public static Subject getInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Subject subject = (Subject)Class.forName(className).newInstance();
return subject;
}
}