反射概念:
Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes。
换言之,Java可以加载一个运行时才得知名称的class,获得其完整结构。
反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
JAVA反射机制提供了什么功能
提供了如下功能:
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判段任意一个类所具有的成员变量和方法
- 在运行时调用任一个对象的方法
- 在运行时创建新类对象
- 在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。
反射机制的作用:
- 反编译:.class–>.java
- 通过反射机制访问java对象的属性,方法,构造方法等;
Java中JDK提供的Reflection API
Java反射相关的API在包java.lang.reflect中。
Member接口 该接口可以获取有关类成员(域或者方法)后者构造函数的信息。
AccessibleObject类 该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认
Java 语言访问控制检查的能力。 Array类 该类提供动态地生成和访问JAVA数组的方法。
Constructor类 提供一个类的构造函数的信息以及访问类的构造函数的接口。 Field类 提供一个类的域的信息以及访问类的域的接口。
Method类 提供一个类的方法的信息以及访问类的方法的接口。
Modifier类 提供了 static方法和常量,对类和成员访问修饰符进行解码。
Proxy类 提供动态地生成代理类和类实例的静态方法。
动态创建代理类
代理模式:代理模式的作用=为其他对象提供一种代理以控制对这个对象的访问。
代理模式的角色:
- 抽象角色:声明真实对象和代理对象的共同接口
- 代理角色:代理角色内部包含有真实对象的引用,从而可以操作真实对象。
- 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
动态代理:
- java.lang.reflect.Proxy
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类 - InvocationHandler
是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
动态Proxy是这样的一种类:
它是在运行生成的类,在生成时你必须提供一组Interface给它,然后该class就宣称它实现了这些interface。你可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
在使用动态代理类时,我们必须实现InvocationHandler接口
实例练习:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
public class InvokeTest {
/**
* 利用反射机制实现调用方法
* @param obj
* @param methodName
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
public static void test(String methodName) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
InvokeTest test=new InvokeTest();
//对象类型
Class<?> cls=test.getClass();
//利用反射机制获取该类型下的方法
Method method=cls.getMethod(methodName, int.class,String.class);
//执行该方法
method.invoke(test, 10,"20");
// test.method(10,20)
}
/**
* ...代表:一组相同类型的数据(不约束个数)
* 一个方法里最多只能有一个...类型
* ...类型必须出现在参数列表的最后位置
* @param a
*/
public static void e(int... a) {
for(int i=0;i<a.length;i++) {
System.out.println(a[i]);
}
}
//反射机制
//调用方法
//不知道方法名或属性名
//通过传递参数来实现调用
public static void main(String[] args) {
//...省略参数类型
e(1,2,3,4,5);
//反射机制
try {
test("d");
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
//没有该方法
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void a() {
System.out.println("aaaaaaaaaa");
}
public void b(int b) {
System.out.println("b="+b);
}
public void c(int a,int b) {
System.out.println("sum="+(a+b));
}
public void d(int a,String b) {
System.out.println(a+b);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
具体功能的实现
反射机制获取类有三种方法,我们来获取Employee类型。
//第一种方式:
Classc1 = Class.forName("Employee");
//第二种方式:
//java中每个类型都有class 属性.
Classc2 = Employee.class;
//第三种方式:
//java语言中任何一个java对象都有getClass 方法
Employeee = new Employee();
Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
创建对象:获取类以后我们来创建它的对象,利用newInstance:
Class c =Class.forName("Employee");
//创建此Class 对象所表示的类的一个新实例
Objecto = c.newInstance(); //调用了Employee的无参数构造方法.
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
获取属性:分为所有的属性和指定的属性:
a,先看获取所有的属性的写法:
//获取整个类
Class c = Class.forName("java.lang.Integer");
//获取所有的属性?
Field[] fs = c.getDeclaredFields();
//定义可变长的字符串,用来存储属性
StringBuffer sb = new StringBuffer();
//通过追加的方法,将每个属性拼接到此字符串中
//最外边的public定义
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");
//里边的每一个属性
for(Field field:fs){
sb.append("\t");//空格
sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字
sb.append(field.getName()+";\n");//属性的名字+回车
}
sb.append("}");
System.out.println(sb);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
b,获取特定的属性,对比着传统的方法来学习:
public static void main(String[] args) throws Exception{
<span style="white-space:pre"> </span>//以前的方式:
/*
User u = new User();
u.age = 12; //set
System.out.println(u.age); //get
*/
//获取类
Class c = Class.forName("User");
//获取id属性
Field idF = c.getDeclaredField("id");
//实例化这个类赋给o
Object o = c.newInstance();
//打破封装
idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
//给o对象的id属性赋值"110"
idF.set(o, "110"); //set
//get
System.out.println(idF.get(o));
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
参考博客:
博客1:
http://blog.csdn.net/liujiahan629629/article/details/18013523
博客2: