JAVA反射机制
JAVA有着一个非常突出的动态相关机制:Reflection,即反射机制,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
public class Person{
public Person() {
}
public Person(String name){
this.name=name;
}
public Person(int age){
this.age=age;
}
public Person(String name, int age) {
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString(){
return "["+this.name+" "+this.age+"]";
}
public void reflect1() {
System.out.println("Java 反射机制 - 调用某个类的方法.");
}
public void reflect2(int age, String name) {
System.out.print("Java 反射机制 - 调用某个类的方法.");
System.out.println("age -> " + age + ". name -> " + name);
}
private String name;
private int age;
}
public class ReflectTest {
public static void main(String[] args) throws Exception{
//通过Object的getClass方法获取Class对象
Date date1 = new Date();
Date date2 = new Date();
Class<?> class1=date1.getClass();
Class<?> class2=date2.getClass();
System.out.println("类全称: "+class2.getName());//类全称: java.util.Date
System.out.println("类名: "+class2.getSimpleName());//类名: Date
System.out.println(class1==class2);//true
//使用.class的方法,并不需要有该类的对象存在
Class<?> stringClass=String.class;
System.out.println("类全称: "+stringClass.getName());//类全称: java.lang.String
System.out.println("类名: "+stringClass.getSimpleName());//类名: String
//使用Class.forName()方法
Class<?> numClass=Class.forName("Collection.Num");
System.out.println("类全称:"+numClass.getName());//类全称:Collection.Num
System.out.println("类名:"+numClass.getSimpleName());//类名:Num
//通过Class的newInstance实例化对象(需要有无参构造方法)
Date newDate=(Date)class1.newInstance();
System.out.println(newDate);//Sat Feb 11 21:19:06 GMT+08:00 2017
//通过Class的newInstance调用对应的构造函数实例化对象
Person per1=null;
Person per2=null;
Person per3=null;
Person per4=null;
Class<?> per=Class.forName("Reflect.Person");
//获得全部构造函数
Constructor<?>[] constructor=per.getConstructors();
System.out.println("构造方法: "+constructor[0]);//构造方法: public Reflect.Person(java.lang.String,int)
System.out.println("构造方法: "+constructor[1]);//构造方法: public Reflect.Person(int)
System.out.println("构造方法: "+constructor[2]);//构造方法: public Reflect.Person(java.lang.String)
System.out.println("构造方法: "+constructor[3]);构造方法: public Reflect.Person()
per1=(Person)constructor[3].newInstance();
per2=(Person)constructor[2].newInstance("Rollen");
per3=(Person)constructor[1].newInstance(20);
per4=(Person)constructor[0].newInstance("Rollen",20);
System.out.println(per1);[null 0]
System.out.println(per2);[Rollen 0]
System.out.println(per3);[null 20]
System.out.println(per4);[Rollen 20]
//返回一个类实现的接口
Class<?> interfaces[]=stringClass.getInterfaces();
for(int i=0;i<interfaces.length;i++){
System.out.println("实现的接口 "+interfaces[i].getName());
}//实现的接口 java.io.Serializable;实现的接口 java.lang.Comparable;实现的接口 java.lang.CharSequence
//取得父类
Class<?> superClass=stringClass.getSuperclass();
System.out.println("继承的父类为:"+superClass.getName());//继承的父类为:java.lang.Object
// 取得本类的全部属性
Field[] field=stringClass.getDeclaredFields();
for(int i=0;i<field.length;i++){
//获取权限修饰符
int modify=field[i].getModifiers();
String priv = Modifier.toString(modify);
//获取属性类型
Class<?> type=field[i].getType();
System.out.println(priv+"-----"+type.getName()+"-----"+field[i].getName());
}
//取得实现的接口或者父类的属性
System.out.println("---------------------------------");
Field[] field2=stringClass.getFields();
for(int i=0;i<field2.length;i++){
//获取权限修饰符
int modify=field2[i].getModifiers();
String priv = Modifier.toString(modify);
//获取属性类型
Class<?> type=field2[i].getType();
System.out.println(priv+"-----"+type.getName()+"-----"+field2[i].getName());
}
//通过反射访问修改私有属性
System.out.println("修改前:"+per4);
Field privateField=per.getDeclaredField("name");
privateField.setAccessible(true);
privateField.set(per4, "Mankind");
System.out.println("修改后:"+per4);
//获取某个类的全部方法
Method[] method=Object.class.getMethods();
for(int i=0;i<method.length;i++){
Class<?> returnType=method[i].getReturnType();
Class<?> para[]=method[i].getParameterTypes();
int temp=method[i].getModifiers();
System.out.println("第"+i+"个方法:");
System.out.println("访问权限:"+Modifier.toString(temp));
System.out.println("返回类型:"+returnType.getName());
System.out.println("方法名:"+method[i].getName());
if(para.length!=0){
System.out.println("参数列表:");
for(int j=0;j<para.length;j++){
System.out.println("参数1:"+para[j].getName());
}
}
}
//调用某个类的无参/有参方法
Method method1=per.getMethod("reflect1");
method1.invoke(per.newInstance());
Method method2=per.getMethod("reflect2",int.class,String.class);
method2.invoke(per.newInstance(),1000,"老王");
//反射实例:在泛型为Integer的ArrayList中存放一个String类型的对象
ArrayList<Integer> list = new ArrayList<Integer>();
Method method3 = list.getClass().getMethod("add", Object.class);
method3.invoke(list, "Welcome to JAVA");
System.out.println(list.get(0));
//通过反射取得并修改数组的信息
int[] intArray={1,2,3,4,5};
Class<?> demo=intArray.getClass().getComponentType();
System.out.println(demo.getName());
System.out.println(Array.getLength(intArray));
System.out.println("数组的第一个元素: " + Array.get(intArray, 0));
Array.set(intArray, 0, 100);
System.out.println("修改之后数组第一个元素为: " + Array.get(intArray, 0));
}
}
动态代理
对于普通的静态代理,一个代理类需要对应一个事先真实存在的对象,在实际操作中,如果大量使用静态代理必然导致类的膨胀,如果事先并不知道真实角色,该如何使用代理呢?动态代理的存在解决了这样一个问题。可以通过Java的动态代理类来解决。动态代理的步骤
(1).创建一个实现接口InvocationHandler的类,它必须实现invoke方法
(2).创建被代理的类以及接口
(3).通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 创建一个代理
(4).通过代理调用方法
public interface ProxyInterface {
public void say();
}
public class ProxyObject implements InvocationHandler{
private Object proxied = null;//这里我们并不知道要代理的对象是谁,所以用一个Object代替
public ProxyObject(){
}
public ProxyObject(Object proxied){
this.proxied = proxied;
}
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
System.out.println("你好!");
return arg1.invoke(proxied, arg2);
};
}
public class RealObject implements ProxyInterface{
public void say(){
System.out.println("i'm talking");
}
}
public class DynamicProxyTest {
static void customer(ProxyInterface pi){
pi.say();
}
public static void main(String[] args){
RealObject real = new RealObject();
ProxyInterface proxy = (ProxyInterface)Proxy.newProxyInstance(ProxyInterface.class.getClassLoader(),new Class[]{ProxyInterface.class}, new ProxyObject(real));
customer(proxy);
}
}