您的位置:首页 > 编程语言 > Java开发

JAVA : 反射机制

2017-01-19 23:10 435 查看

反射机制

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

JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

功能

java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

它有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

动态绑定

要想深入研究java的反射机制,首先要了解什么是动态绑定。动态是相对于静态来说的。二者的区别主要在于创建对象的时间不一同,静态绑定是编译时创建对象,而动态绑定是在运行时创建对象。

public class TestReflect  {

public static void main(String[] args) throws Exception {
String message = null;
ManPerson m1 = new ManPerson();
message = m1.eat("aaa");//静态方式调用
System.out.println(message);

Class<?> clazz = Class.forName("com.kblsoft.reflect.one.ManPerson");
ManPerson m2 = (ManPerson) clazz.newInstance();//动态方式创建对象调用
message = m2.eat("bbbb");
System.out.println(message);
}
}
interface Person{
public abstract String eat(String food);
}

class ManPerson implements Person{
@Override
public String eat(String food) {
return "man eat " + food;
}
}


通过一个对象获得完整的包名和类名

public class TestReflect {
public static void main(String[] args) {
TestReflect testReflect = new TestReflect();
System.out.println(testReflect.getClass().getSimpleName());//类名
System.out.println(testReflect.getClass().getName());//包名+类名
//output:
//TestReflect
// com.kblsoft.reflect.one.TestReflect
}
}


实例化Class类对象

public class TestReflect {
public static void main(String[] args) throws Exception {
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;

class1 = Class.forName("com.kblsoft.reflect.one.TestReflect");   // 一般采用这种形式
class2 = new TestReflect().getClass();//可用下面这种代替
class3 = TestReflect.class;
System.out.println("类名称   " + class1.getName());
System.out.println("类名称   " + class2.getName());
System.out.println("类名称   " + class3.getName());

//output
//类名称   com.kblsoft.reflect.one.TestReflect
//类名称   com.kblsoft.reflect.one.TestReflect
//类名称   com.kblsoft.reflect.one.TestReflect
}
}


获取某个类中的全部构造函数

public class TestReflect {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.kblsoft.reflect.one.Student");
//第一种方法,实例化
Student student = (Student) clazz.newInstance();
student.setAge(24);
student.setName("black");
System.out.println(student.getAge() + "::" + student.getName());

//output     24::black

//第二种   获取所有构造函数,逐个分析
Constructor<?> cons[] = clazz.getConstructors();
for (Constructor<?> con : cons) {
Parameter[] paras = con.getParameters();
System.out.println(con);
for (Parameter para : paras) {
System.out.println(para.getType().getName());
}
}
//output
//  public com.kblsoft.reflect.one.Student(int,java.lang.String)
//  int
//  java.lang.String
//  public com.kblsoft.reflect.one.Student(java.lang.String)
//  java.lang.String
//  public com.kblsoft.reflect.one.Student()

}
}

class Student {
public int age;
public String name;

public Student() {
}

public Student(String name) {
this.name = name;
}

public Student(int age, String name) {
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;
}
}


获取某个类的全部属性

权限修饰符在这里有用

public class TestReflect extends Param {

private int iSelf = 0;

public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz = Class.forName("com.kblsoft.reflect.one.TestReflect");
System.out.println("===============本类属性:getDeclaredFields===============");
// 取得本类的全部属性
Field[] field = clazz.getDeclaredFields();
for (Field f : field) {
// 权限修饰符
int mo = f.getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = f.getType();
System.out.println(priv + " " + type.getName() + " " + f.getName() + ";");
}

System.out.println("==========实现的接口或者父类的属性:getFields==========");
// 取得实现的接口或者父类的属性
Field[] filed1 = clazz.getFields();
for (Field f : filed1) {
// 权限修饰符
int mo = f.getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = f.getType();
System.out.println(priv + " " + type.getName() + " " + f.getName() + ";");
}

}
}


获取某个类的全部方法

public class TestReflect extends Param {

public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.kblsoft.reflect.one.TestReflect");
Method[] methods = clazz.getMethods();//获取全部方法,然后循环信息
for (Method method : methods) {
Class<?> returnType = method.getReturnType();
Class<?> paras[] = method.getParameterTypes();
int temp = method.getModifiers();

//获取方法修饰符和名称
//output public static void  main
System.out.print(Modifier.toString(temp) + " ");
System.out.print(returnType.getName() + "  ");
System.out.print(method.getName() + " ");

//获取方法参数
for (Class<?> para : paras) {
System.out.print(para.getName());
}

//获取方法的异常
Class<?> exces[] = method.getExceptionTypes();
for (Class<?> exce : exces) {
System.out.println(exce.getName());
}

System.out.println();

}
}

public static void testMethod(String param1,int param2) {

}

public String testMethod2(){
return "SUCCESS";
}
}


通过反射机制调用某个类的方法

public class TestReflect extends Param {

public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.kblsoft.reflect.one.TestReflect");
Method method1 = clazz.getMethod("reflect1");
method1.invoke(clazz.newInstance());

Method method2 = clazz.getMethod("reflect2",int.class,String.class);
method2.invoke(clazz.newInstance(),22,"black");//invoke  反射
//output
//Java 反射机制 - 调用某个类的方法1.
//Java 反射机制 - 调用某个类的方法2.
//age -> 22. name -> black
}

public void reflect1() {
System.out.println("Java 反射机制 - 调用某个类的方法1.");
}
public void reflect2(int age, String name) {
System.out.println("Java 反射机制 - 调用某个类的方法2.");
System.out.println("age -> " + age + ". name -> " + name);
}
}


通过反射机制操作某个类的属性

private String proprety = null;

public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.kblsoft.reflect.one.TestReflect");
Object obj = clazz.newInstance();
// 可以直接对 private 的属性赋值
Field field = clazz.getDeclaredField("proprety");//获取指定的属性值
field.setAccessible(true);//设置是否允许访问,而不是修改原来的访问权限修饰词。
field.set(obj, "Java反射机制");//set值
System.out.println(field.get(obj));//get值
}


反射机制的动态代理

代理设计模式 : 定义:为其他对象提供一种代理以控制对这个对象的访问。

一个典型的动态代理创建对象过程可分为以下四个步骤:

1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);

2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类

Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});

3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型

Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});

4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入

Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));

为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。

生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))

public class TestReflect  {

public static void main(String[] args) throws Exception {
MyInvocationHandler demo = new MyInvocationHandler();
Person sub = (Person) demo.bind(new RealPerson());
String info = sub.eat("children");
System.out.println(info);
}
}
interface Person{
public String eat(String food);
}

class RealPerson implements Person{

@Override
public String eat(String food) {
return "eat " + food;
}
}

class MyInvocationHandler implements InvocationHandler{//定义一个InvocationHandler接口的子类

private Object obj = null;

public Object bind(Object obj){//具体的实现
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);//创建动态代理
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(this.obj,args);//对接口的调用重定向为对代理的调用
}
}


通过反射取得并修改数组的信息

Array的使用

public class TestReflect  {

public static void main(String[] args) throws Exception {
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));
//output
//数组类型: int
//数组长度  5
//数组的第一个元素: 1
//修改之后数组第一个元素为: 100
}
}


通过反射机制修改数组的大小

public class TestReflect  {

public static void main(String[] args) throws Exception {
int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] newTemp = (int[]) arrayInc(temp, 15);
print(newTemp);
String[] atr = { "a", "b", "c" };
String[] str1 = (String[]) arrayInc(atr, 8);
print(str1);
//output
//数组长度为: 15
//1 2 3 4 5 6 7 8 9 0 0 0 0 0 0
//数组长度为: 8
//a b c null null null null null
}
// 修改数组大小
public static Object arrayInc(Object obj, int len) {
Class<?> arr = obj.getClass().getComponentType();
Object newArr = Array.newInstance(arr, len);
int co = Array.getLength(obj);
System.arraycopy(obj, 0, newArr, 0, co);
return newArr;
}
// 打印
public static void print(Object obj) {
Class<?> c = obj.getClass();
if (!c.isArray()) {
return;
}
System.out.println("数组长度为: " + Array.getLength(obj));
for (int i = 0; i < Array.getLength(obj); i++) {
System.out.print(Array.get(obj, i) + " ");
}
System.out.println();
}
}


将反射机制应用于工厂模式

//现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
//但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
public class TestReflect  {

public static void main(String[] args) throws Exception {
Person p = Factory.getInstance("com.kblsoft.reflect.one.ManPerson");//接口接收,创建的是子类
if (null != p) {
System.out.println(p.eat("children"));
}
}
}
interface Person{
public abstract String eat(String food);
}

class ManPerson implements Person{
@Override
public String eat(String food) {
return "man eat " + food;
}
}
class WomanPerson implements Person{
@Override
public String eat(String food) {
return "woman eat " + food;
}
}

class Factory {
public static Person getInstance(String className){
Person person = null;
try {
person = (Person) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}

return person;
}
}


参考

1. http://www.cnbl/lzq198754/p/5780331.html

2. java编程思想
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 反射