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

Java基础之反射及动态代理,反射实现工厂模式

2017-05-25 14:04 691 查看
一,先看一下反射的概念:
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
看概念很晕的,继续往下看。

二,反射机制的作用:
1,反编译:.class-->.java
2,通过反射机制访问java对象的属性,方法,构造方法等;
这样好像更容易理解一些,下边我们具体看怎么实现这些功能。
三,在这里先看一下sun为我们提供了那些反射机制中的类:
java.lang.Class;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;

四。从例子看常用的用法:
package reflect;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

public class ReflectTest implements Serializable {

/**
*
*/
private static final long serialVersionUID = 6957472993081091730L;

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException {
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;

class1 = Class.forName("reflect.ReflectTest");//实例化Class类对象-1
class2 = new ReflectTest().getClass();//实例化Class类对象-2
class3 = ReflectTest.class;//实例化Class类对象-3

Class<?> parentClass = class1.getSuperclass();//获得父类
Class<?> intes[] = class1.getInterfaces();//获得所有接口

Class<?> class4 = Class.forName("reflect.User");//完整路径的类名,包括package name
User user1 = (User) class4.newInstance();// create a user through reflect
user1.setUsername("lilong");
Constructor<?> cons[] = class4.getConstructors();

ReflectTest reflectTest = new ReflectTest();
System.out.println("通过一个对象获得完整的包名和类名:" + reflectTest.getClass().getName());
System.out.println("___________________________");

System.out.println("类名称   " + class1.getName());
System.out.println("类名称   " + class2.getName());
System.out.println("类名称   " + class3.getName());
System.out.println("___________________________");

System.out.println("class1的父类是:"+ parentClass.getName());
System.out.println("class1实现的接口有:");
for(int i=0; i<intes.length; i++){
System.out.println((i+1) + ":" + intes[i].getName());
}
System.out.println("___________________________");

System.out.println("username : " + user1.getUsername());
for(int i =0; i<cons.length; i++){
Class<?> clazzs[] = cons[i].getParameterTypes(); //取得各个参数类型构成的Class数组
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(")");

}
System.out.println("___________________________");

Class<?> class5 = Class.forName("reflect.Student");
System.out.println("===============本类属性===============");
Field[] fields = class5.getDeclaredFields(); //该类声明的属性
for(int i=0; i<fields.length; i++){
String mo = Modifier.toString(fields[i].getModifiers()); //权限修饰符
Class<?> type = fields[i].getType();// 属性类型
System.out.println(mo + " " + type.getName() + " " + fields[i].getName() + ";");
}
System.out.println("==========实现的接口或者父类的属性==========");
Field[] fields2 = class5.getFields(); //获得实现的接口或者父类的属性
for(int i=0; i<fields2.length; i++){
String mo = Modifier.toString(fields2[i].getModifiers());
Class<?> type = fields2[i].getType();
System.out.println(mo + " " + type.getName() + " " + fields2[i].getName() + ";");
}
System.out.println("___________________________");

System.out.println("获取某个类的全部方法");
Class<?> class6 = Class.forName("reflect.Student");
Method[] method = class6.getMethods();
for(int i=0; i<method.length; i++){
Class<?> returnType = method[i].getReturnType();
Class<?>[] param = method[i].getParameterTypes();
int temp = method[i].getModifiers();
System.out.print(Modifier.toString(temp) + " " + returnType.getName() + " " + method[i].getName()+"(");
for(int j=0; j<param.length; j++){
System.out.print(param[j].getName() + " arg" + j);
if(j < param.length -1){
System.out.print(",");
}
}
Class<?>[] exce = method[i].getExceptionTypes();
if(exce.length > 0){
System.out.print(") throws ");
for(int k=0; k< exce.length; k++){
System.out.print(exce[k].getName() + "");
if(k < exce.length -1){
System.out.print(",");
}
}
}else {
System.out.print(")\n");
}
System.out.println();
}
System.out.println("___________________________");

System.out.println("通过反射机制调用某个类的方法");
Class<?> class7 = Class.forName("reflect.Student");
Method method2 = class7.getMethod("print"); //调用无参方法
Method method3 = class7.getMethod("print2", String.class);//调用有参方法

try {
method2.invoke(class7.newInstance());
method3.invoke(class7.newInstance(), "i am a student too.");
} catch (IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("___________________________");

System.out.println("通过反射机制操作某个类的属性");
Class<?> class8 = Class.forName("reflect.Student");
Object object = class8.newInstance();
Field field;
try {
field = class8.getDeclaredField("password");
field.setAccessible(true);
field.set(object, "lilong123");
System.out.println("password is " + field.get(object));
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("___________________________");

System.out.println("反射机制的动态代理");
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject) demo.bind(new RealSubjec());// 接口变量指向?
String info = sub.say("roolback", 20);
System.out.println(info);
System.out.println("___________________________");

}

}

class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;

private String username;

public User() {
this.username = "lilong";
}

public User(String username) {
this.username = username;
}

public String getUsername() {
return username;

4000
}

public void setUsername(String username) {
this.username = username;
}

}

class Student extends User {
/**
*
*/
private static final long serialVersionUID = 1L;
private String password;

public Student() {
super();
// TODO Auto-generated constructor stub
}

public Student(String password) {
super();
this.password = password;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public void print(){
System.out.println("i am a student.");
}

public void print2(String str) {
System.out.println(str);
}
}

interface Subject{
public String say(String name, int age);
}

class RealSubjec implements Subject{

@Override
public String say(String name, int age) {
return name + " " + age;
}

}

class MyInvocationHandler implements InvocationHandler{

private Object obj = null;
/**
* 在java中有三种类类加载器。
*
* 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
*
* 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
*
* 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
*
* 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
* 动态代理的代理类是实现了一个InvocationHandler的接口,我们通过reflect.Proxy的类的newProxyInstance方法就可以得到这个接口
的实例,然后再来作为参数传递进去,这里每一个在代理类上处理的东西也会被重定向到调用处理器上。
* @author
*
*/
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 {
Object temp = method.invoke(this.obj, args);
return temp;
}
}

用反射实现工厂模式:
package reflect;

public class ReflectTest2 {

public static void main(String[] args) {
Fruit fruit1 = Factory.getInstance("reflect.Apple");
Fruit fruit2 = Factory.getInstance("reflect.Orange");
fruit1.eat();
fruit2.eat();

}

}

interface Fruit{
public void eat();
}

class Apple implements Fruit{

@Override
public void eat() {
System.out.println("Apple");
}

}

class Orange implements Fruit{

@Override
public void eat() {
System.out.println("Orange");
}

}

/**
* 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。
* Java 工厂模式可以参考
* http://baike.xsoftlab.net/view/java-factory-pattern *
* 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
*
* 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
*
* java 读取 properties 配置文件 的方法可以参考
* http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file *
* @author xsoftlab.net
*/
class Factory{
public static Fruit getInstance(String ClassName) {
Fruit fruit = null;
try {
fruit = (reflect.Fruit) Class.forName(ClassName).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return fruit;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 基础