zoukankan      html  css  js  c++  java
  • 第十五章 反射

    15、反射
    15.1 Java反射机制概述 1课时
    15.2 理解Class类并获取Class类的实例 1课时
    15.3 类的加载与ClassLoader的理解 1课时
    15.4 通过反射创建运行时类的对象 1课时
    15.5 通过反射获取运行时类的完整结构 1课时
    15.6 通过反射调用运行时类的指定属性、指定方法等 1课时
    15.7 反射的应用:动态代理 1课时
    ##15-1 Java反射机制概述


    案例

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.Properties;
    
    import javax.swing.plaf.synth.SynthSliderUI;
    
    import org.junit.Test;
    
    /**
     * 本章要涉及的内容:
     * 
     * 1.反射的概述 
     * 2.Class的理解 和 实例化  (掌握)
     * 3.类的加载和ClassLoader的理解
     * 4.使用反射,创建指定的运行时类的对象  (掌握)
     * 5.使用反射,获取运行时类中的所有的结构:属性、方法、构造器、父类、接口、注解、父类的泛型... 
     * 6.使用反射,调用运行时类中的指定的结构:属性、方法、构造器   (掌握)
     * 7.反射的应用:动态代理,体会反射的动态性。
     * 
     */
    public class ReflectionTest {
    	
    	/**
    	 * Properties:常用来处理属性文件。
    	 * @throws IOException 
    	 * 
    	 * 
    	 */
    	@Test
    	public void test5() throws IOException{
    		//处理工程下的配置信息
    		Properties pros = new Properties();
    		//默认文件的读取位置:当前工程下。
    //		FileInputStream is = new FileInputStream("jdbc.properties");
    		FileInputStream is = new FileInputStream("src\jdbc1.properties");
    		pros.load(is);
    		
    		String name = pros.getProperty("name");
    		String password = pros.getProperty("password");
    		System.out.println("name = " + name + ",password = " + password);
    		
    		
    		System.out.println("**************************************");
    		Properties pros1 = new Properties();
    		ClassLoader loader = ReflectionTest.class.getClassLoader();
    		//默认读取配置文件的位置是:src目录下
    //		InputStream inputStream = loader.getResourceAsStream("jdbc1.properties");
    		InputStream inputStream = loader.getResourceAsStream("com\xxx\java\jdbc2.properties");
    		pros1.load(inputStream);
    		
    		String user = pros1.getProperty("name");
    		String pwd = pros1.getProperty("password");
    		System.out.println("user = " + user + ",pwd = " + pwd);
    	}
    	
    	/**
    	 * 了解类的加载过程 和 类的加载器:ClassLoader
    	 * @throws ClassNotFoundException 
    	 * 
    	 * 
    	 */
    	@Test
    	public void test4() throws ClassNotFoundException{
    		//获取系统类加载器
    		ClassLoader classLoader1 = ClassLoader.getSystemClassLoader();
    		System.out.println(classLoader1);
    		
    		//获取扩展类加载器
    		ClassLoader classLoader2 = classLoader1.getParent();
    		System.out.println(classLoader2);
    		
    		//获取引导类加载器(获取不到)
    		ClassLoader classLoader3 = classLoader2.getParent();
    		System.out.println(classLoader3);
    		
    		//说明:用户自定义类是由系统类加载器加载的
    		ClassLoader loader1 = Person.class.getClassLoader();
    		System.out.println(loader1);
    		//说明:java 核心api是由引导类加载器加载的
    		ClassLoader loader2 = Class.forName("java.lang.String").getClassLoader();
    		System.out.println(loader2);
    		
    	}
    	
    	/**
    	 * java.lang.Class的理解
    	 * 1.Class是反射的源头
    	 * 2.java源程序经过编译(javac.exe)以后,生成一个或多个字节码(.class)文件,我们使用java.exe命令,
    	 * 将指定的字节码文件加载到内存中,解释运行。此过程是使用JVM的类的加载器、解释器等实现的。
    	 * 加载到内存中的字节码文件对应的类,称为运行时类,此运行时类,即为一个Class的实例。
    	 * 
    	 * 3.Class的一个实例,对应着一个加载内存中的运行时类。
    	 * 
    	 * 4.加载到内存中的运行时类,只被类的加载器加载器一次,之后会被缓存下来。
    	 * 
    	 * @throws ClassNotFoundException 
    	 * @throws Exception
    	 */
    	//如何获取Class的实例 (4种)
    	@Test
    	public void test3() throws ClassNotFoundException{
    		//方式一(掌握):调用运行时类的属性:.class
    		Class clazz1 = Person.class;
    		System.out.println(clazz1);
    		
    		//方式二(掌握):可以调用运行时类对象的getClass()
    		Person p = new Person();
    		Class clazz2 = p.getClass();
    		System.out.println(clazz2);
    		
    		//方式三(掌握):调用Class类的静态方法:forName(String className).
    		//注释:className需要提供类的全类名
    		Class clazz3 = Class.forName("com.xxx.java.Person");
    		System.out.println(clazz3);
    		
    		System.out.println(clazz1 == clazz2 && clazz1 == clazz3);
    		
    		//方式四(了解):使用类的加载器(ClassLoader)
    		ClassLoader classLoader = ReflectionTest.class.getClassLoader();
    		Class clazz4 = classLoader.loadClass("com.xxx.java.Person");
    		System.out.println(clazz4);
    		System.out.println(clazz1 == clazz4);
    		
    	}
    	
    	
    	//有了反射以后,类的封装性受到影响了。如何理解这两个技术?
    	//单例模式被打破了?!
    	
    	//通过反射,实现Person类对象的创建,属性、方法的调用
    	@Test
    	public void test2() throws Exception{
    		
    		Class clazz = Person.class;
    		//通过反射,调用指定的构造器,创建运行时类Person类的对象
    		Constructor con = clazz.getConstructor(String.class,int.class);
    		Person p = (Person) con.newInstance("Tom",12);
    		
    		System.out.println(p);
    		
    		//通过反射,调用当前对象的指定的属性
    		Field field1 = clazz.getField("name");
    		field1.set(p, "HanMeimei");
    		
    		//通过反射,调用当前对象的指定的方法
    		Method method1 = clazz.getMethod("show");
    		method1.invoke(p);
    		
    		System.out.println("***********************************");
    		//通过反射,调用运行时类Person类的私有的构造器
    		Constructor con1 = clazz.getDeclaredConstructor(String.class);
    		con1.setAccessible(true);
    		Person p1 = (Person) con1.newInstance("田杰");
    		
    		System.out.println(p1);
    		
    		//通过反射,调用运行时类Person类的私有的属性
    		Field field2 = clazz.getDeclaredField("age");
    		field2.setAccessible(true);
    		field2.set(p1, 23);
    		
    		System.out.println(p1);
    		
    		
    		//通过反射,调用运行时类Person类的私有的方法
    		Method method2 = clazz.getDeclaredMethod("display",String.class);
    		method2.setAccessible(true);
    		String info = (String) method2.invoke(p1, "中国");//此invoke()的返回值,即为对应的display()的返回值
    		
    		System.out.println(info);
    		
    	}
    	
    	//反射之前的体会
    	@Test
    	public void test1(){
    //		Person p = new Person("Tom");//不可直接调用
    		Person p1 = new Person("Tom", 12);
    		
    		p1.name = "HanMeimei";
    //		p1.age = 10;//不可直接调用
    		
    		p1.show();
    //		p1.display("CHN");//不可直接调用
    		
    		Person p2 = new Person("Tim", 12);
    		
    	}
    }
    

    public class Person {
    	public String name;
    	private int age;
    	
    	public Person(){
    		System.out.println("Person()");
    	}
    	private Person(String name){
    		this.name = name;
    	}
    	
    	public Person(String name,int age){
    		this.name = name;
    		this.age = age;
    	}
    
    	public void show(){
    		System.out.println("name = " + name + ",age = " + age);
    	}
    	
    	public String info(){
    		return name + ":" + age;
    	}
    	
    	private String display(String nation){
    		System.out.println("我是" + nation + "国家的人");
    		return nation;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]";
    	}
    	
    	
    }
    

    jdbc.properties

    name=u62c9u54c8u5475

    password=abc123


    反射的应用一案例
    import org.junit.Test;
    /**
     * 反射的应用一:创建运行时类的对象 (掌握)
     * 
     */
    public class NewInstanceTest {
    	//有了Class实例以后,可以做什么呢?
    	//可以创建运行时类的对象。
    	@Test
    	public void test1() throws Exception{
    		
    		Class clazz = Class.forName("com.tzy.java.Person");
    		/*
    		 * 1.newInstance():实际上调用的就是运行时类中的空参的构造器
    		 * 2.可能调用,也要受封装性的影响。
    		 * 
    		 * 说明:建议创建的Bean类,都提供空参的构造器,而且权限一般都为public!
    		 *     应用场景:①默认子类的构造器通过super()的方式,调用父类空参的构造器。
    		 *     		  ②方便通过反射的方式,创建运行时类的对象
    		 * 
    		 */
    		Person p = (Person) clazz.newInstance();
    		
    		System.out.println(p);
    		
    	}
    }
    

    15-2 理解Class类并获取Class的实例

    15-3 类的加载ClassLoader的理解

    15-4 创建运行时类的对象


    15-5 获取运行时类的完整结构

    15-6 调用运行时类的指定属性、指定方法等


    反射总结案例

    import java.io.Serializable;
    
    public class Creature<T> implements Serializable {
    	
    	public boolean gender;
    	double weight;
    	
    	public void play(T t){
    		System.out.println("Creature");
    	}
    
    }
    

    public interface MyInterface {
    	String info();
    	
    }
    

    import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.LOCAL_VARIABLE; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
    	String value();
    }
    

    @MyAnnotation(value="xxxx") public class Person extends Creature implements Comparable,MyInterface{
    	public String name;
    	private int age;
    	
    	private static String nation = "CHN";
    	
    	public Person(){
    		System.out.println("Person()");
    	}
    	private Person(String name){
    		this.name = name;
    	}
    	
    	protected Person(String name,int age){
    		this.name = name;
    		this.age = age;
    	}
    
    	@MyAnnotation(value="hello")
    	public void show() throws RuntimeException{
    		System.out.println("name = " + name + ",age = " + age);
    	}
    	
    	public String info(){
    		return name + ":" + age;
    	}
    	
    	private String display(String nation){
    		System.out.println("我是" + nation + "国家的人");
    		return nation;
    	}
    	@Override
    	@MyAnnotation(value="hi")
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]";
    	}
    	
    	@Override
    	public int compareTo(Person o) {
    		// TODO Auto-generated method stub
    		return 0;
    	}
    	
    	public static void showNation(){
    		System.out.println("我是中国人!");
    	}
    	
    	
    }
    

    /** * 反射的应用二:获取运行时类的所有的结构:属性 * */ public class FieldTest {
    	//如何获取运行时类中所有属性
    	@Test
    	public void test1(){
    		
    		Class clazz = Person.class;
    		//getFields():只能获取当前运行时类,及其所有父类中声明为public的属性
    		Field[] fields = clazz.getFields();
    		for(int i = 0;i < fields.length;i++){
    			System.out.println(fields[i]);
    		}
    		
    		System.out.println("*****************");
    		//getDeclaredFields():能够获取当前运行时类中声明的所有的属性,不论权限的大小。
    		Field[] fields1 = clazz.getDeclaredFields();
    		for(int i = 0;i < fields1.length;i++){
    			System.out.println(fields1[i]);
    		}
    		
    	}
    	
    	//权限修饰符  数据类型 变量名
    	@Test
    	public void test2(){
    		Class clazz = Person.class;
    		Field[] fields = clazz.getDeclaredFields();
    		for (Field f : fields) {
    
    			// 1.权限修饰符
    			int modifier = f.getModifiers();
    //			System.out.println(modifier);
    			System.out.print(Modifier.toString(modifier) + "	");
    //
    //			// 2.类型
    			Class type = f.getType();
    			System.out.print(type.getName() + "	");
    //
    //			// 3.变量名
    			System.out.println(f.getName());
    		}
    	}
    	
    }
    

    /** * 反射的应用二:获取运行时类的所有的结构:方法 */ public class MethodTest {
    	// 获取运行时类中声明的所有的方法
    	@Test
    	public void test1() {
    
    		Class clazz = Person.class;
    
    		// getMethods():获取当前运行时类,及其所有的父类中声明为public的方法
    		Method[] methods = clazz.getMethods();
    		for (Method m : methods) {
    			System.out.println(m);
    		}
    		System.out.println("*********************");
    		// getDeclaredMethods():获取当前运行时类中声明的所有的方法,不论权限的大小
    		Method[] methods1 = clazz.getDeclaredMethods();
    		for (Method m : methods1) {
    			System.out.println(m);
    		}
    
    	}
    
    	// 注解
    	// 权限修饰符 返回值类型 方法名(参数类型1 参数名1,参数类型2 参数名2,...) throws 异常类型1,异常类型2,...{}
    	@Test
    	public void test2() {
    		Class clazz = Person.class;
    
    		Method[] methods = clazz.getDeclaredMethods();
    		for (Method m : methods) {
    			// 1.注解
    			Annotation[] annos = m.getAnnotations();
    			for (Annotation a : annos) {
    				System.out.println(a);
    			}
    			// 2.权限修饰符
    			System.out.print(Modifier.toString(m.getModifiers()) + "	");
    			// 3. 返回值类型
    			Class returnType = m.getReturnType();
    			System.out.print(returnType.getName() + "	");
    
    			// 4.方法名
    			System.out.print(m.getName() + "(");
    
    			// 5.(形参类型 变量名,....)
    			Class[] paras = m.getParameterTypes();
    			for (int i = 0; i < paras.length; i++) {
    				if (i == paras.length - 1) {
    					System.out.print(paras[i].getName() + " args_" + i);
    					break;
    				}
    				System.out.print(paras[i].getName() + " args_" + i + ",");
    			}
    
    			System.out.print(")");
    
    			// 6. 异常类型
    			Class[] exceptionTypes = m.getExceptionTypes();
    			if (exceptionTypes != null && exceptionTypes.length != 0) {
    				System.out.print(" throws ");
    			}
    
    			for (Class c : exceptionTypes) {
    				System.out.print(c.getName() + "	");
    			}
    
    			System.out.println();
    		}
    	}
    }
    

    /** * 反射的应用二:获取运行时类的所有的结构:构造器 */ public class ConstructorTest {
    	@Test
    	public void test1(){
    		Class clazz = Person.class;
    		
    		//getConstructors():获取运行时类中声明为public权限的构造器
    		Constructor[] cons = clazz.getConstructors();
    		for(Constructor c : cons){
    			System.out.println(c);
    		}
    		
    		System.out.println("*********************");
    		//getDeclaredConstructors():获取运行时类中所有的构造器,不论权限大小
    		Constructor[] cons1 = clazz.getDeclaredConstructors();
    		for(Constructor c : cons1){
    			System.out.println(c);
    		}
    		
    		
    	}
    }
    

    /** * 反射的应用二:获取运行时类的所有的结构:其它结构 */ public class OtherTest {
    	//获取运行时类所实现的接口
    	@Test
    	public void test5(){
    		Class clazz = Person.class;
    		
    		Class[] interfaces = clazz.getInterfaces();
    		for(Class c : interfaces){
    			System.out.println(c);
    		}
    	}
    	
    	
    	@Test
    	public void testGetSuperClassGenericParam() throws Exception{
    		String className = "com.xxx.java1.Person";
    		className = "com.xxx.java2.CustomerDAO";
    		className = "com.xxx.java2.OrderDAO";
    		String superClassGenericParam = getSuperClassGenericParam(className);
    		System.out.println(superClassGenericParam);
    	}
    	
    	//体会反射的动态性
    	public String getSuperClassGenericParam(String className) throws Exception{
    		
    		Class clazz = Class.forName(className);
    		Type genericSuperClass = clazz.getGenericSuperclass();
    		ParameterizedType paramsType = (ParameterizedType) genericSuperClass;
    		Type[] arguments = paramsType.getActualTypeArguments();
    		return ((Class)arguments[0]).getName();
    		
    	}
    	
    	//获取运行时类的带泛型的父类的泛型
    	//逻辑性代码     功能性代码
    	@Test
    	public void test4(){
    		Class clazz = Person.class;
    		
    		Type genericSuperClass = clazz.getGenericSuperclass();
    		ParameterizedType paramsType = (ParameterizedType) genericSuperClass;
    		Type[] arguments = paramsType.getActualTypeArguments();
    		System.out.println(((Class)arguments[0]).getName());
    		
    	}
    	
    	//获取运行时类的带泛型的父类
    	@Test
    	public void test3(){
    		Class clazz = Person.class;
    		
    		Type genericSuperClass = clazz.getGenericSuperclass();
    		System.out.println(genericSuperClass);
    	}
    	
    	//获取运行时类的父类
    	@Test
    	public void test2(){
    		Class clazz = Person.class;
    		
    		Class superClass = clazz.getSuperclass();
    		System.out.println(superClass);
    		
    		Class superClass1 = superClass.getSuperclass();
    		System.out.println(superClass1);
    	}	
    	
    	//获取运行时类所属的包
    	@Test
    	public void test1(){
    		Class clazz = Person.class;
    		
    		Package pack = clazz.getPackage();
    		System.out.println(pack);
    	}
    }
    

    /** * 反射的应用三:调用运行时类中的指定的结构:属性、方法、构造器 (掌握) */ public class ReflectionTest { //int i = 10; Integer j = i; //如何调用运行时类的指定的构造器 (模板代码) @Test public void test4() throws Exception{ Class clazz = Person.class; //第一步:getDeclaredConstructor(Class ... params): Constructor con = clazz.getDeclaredConstructor(String.class,int.class); // Constructor con = clazz.getDeclaredConstructor(String.class,Integer.class);//不可以使用Integer替换类声明的int型参数 //第二步:setAccessible(true):保证当前的构造器是可操作的 con.setAccessible(true);
    		//第三步:newInstance(Object paramValue):调用构造器,创建运行时类的对象
    		Person p = (Person) con.newInstance("田杰",23);
    		
    		System.out.println(p);
    		
    	}
    	
    	
    	//如何调用运行时类的指定的方法 (模板代码)
    	@Test
    	public void test3() throws Exception{
    		Class clazz = Person.class;
    		
    		//第一步:getDeclaredMethod(String methodName,Class ... params):获取当前运行时类中指定的方法
    		Method m1 = clazz.getDeclaredMethod("display",String.class);
    		
    		//2.第二步:setAccessible(true):保证当前的方法是可操作的
    		m1.setAccessible(true);
    		//3.第三步:invoke(Object obj,Object ... objs):调用此方法
    		//此invoke()方法的返回值即为对应的要调用的方法的返回值。
    		Person person = (Person) clazz.newInstance();
    		String info = (String) m1.invoke(person,"中国");
    		System.out.println(info);
    		
    		//另例:静态方法如何调用?
    		Method m2 = clazz.getDeclaredMethod("showNation");
    		m2.setAccessible(true);
    //		m2.invoke(Person.class);
    		m2.invoke(null);
    		
    		
    	}
    	
    	
    	//如何调用 运行时类的指定的属性 (模板代码)
    	@Test
    	public void test2() throws Exception{
    		Class clazz = Person.class;
    		//第一步:getDeclaredField(String fieldName):获取当前类中声明的属性,不用考虑权限
    		Field f1 = clazz.getDeclaredField("age");
    		System.out.println(f1);
    		//创建运行时类的对象
    		Person person = (Person) clazz.newInstance();
    		
    		//第二步:setAccessible(true):保证当前的属性是可操作的
    		f1.setAccessible(true);
    		//第三步:对属性进行设置获取
    		//1.如何设置当前属性的值
    		f1.set(person, 12);
    		
    		//2.如何获取当前属性的值
    		int age = (int) f1.get(person);
    		System.out.println(age);
    		
    		//另例:如何调用静态的属性?
    		Field f2 = clazz.getDeclaredField("nation");
    		f2.setAccessible(true);
    		f2.set(null, "CHINA");
    		System.out.println(f2.get(null));
    		
    		
    	}
    	
    	//如何调用 运行时类的指定的属性  (不用练了)
    	@Test
    	public void test1() throws Exception{
    		Class clazz = Person.class;
    		//getField(String fieldName):
    		Field f1 = clazz.getField("name");
    		System.out.println(f1);
    		//创建运行时类的对象
    		Person person = (Person) clazz.newInstance();
    		
    		//如何设置当前属性的值
    		f1.set(person, "Tom");
    		
    		//如何获取当前属性的值
    		String name = (String) f1.get(person);
    		System.out.println(name);
    	}
    	
    }
    

    15-7 反射的应用:动态代理

    静态代理案例

    /**
     * 静态代理的例子1:如下
     * 
     * 静态代理的例子2:实现Runnable接口的方式,就是代理模式
     *
     */
    public class ClothFactoryTest {
    	public static void main(String[] args) {
    		
    		NikeClothFactory nikeFactory = new NikeClothFactory();//创建被代理类对象
    		ProxyClothFactory proxy = new ProxyClothFactory(nikeFactory);//创建代理类对象
    		proxy.produceCloth();
    	}
    }
    
    
    interface ClothFactory{
    	
    	void produceCloth();
    }
    
    //代理类
    class ProxyClothFactory implements ClothFactory{
    
    	ClothFactory clothFactory;
    	
    	public ProxyClothFactory(ClothFactory clothFactory){
    		this.clothFactory = clothFactory;
    	}
    	
    	@Override
    	public void produceCloth() {
    		System.out.println("代理工厂需要进行前期准备操作");
    		
    		clothFactory.produceCloth();
    		
    		System.out.println("代理工厂需要进行后期处理操作");
    	}
    	
    	
    	
    	
    }
    
    //被代理类
    class NikeClothFactory implements ClothFactory{
    
    	@Override
    	public void produceCloth() {
    		System.out.println("Nike工厂生产一批衣服");
    	}
    	
    }
    

    动态代理案例

    /**
     * 动态代理的例子
     */
    
    interface Human{
    	
    	String say();
    	
    	void fly();
    	
    }
    
    //被代理类
    class SuperMan implements Human{
    
    	@Override
    	public String say() {
    		return "我是超人!我怕谁!";
    	}
    
    	@Override
    	public void fly() {
    		System.out.println("I believe I can fly!");
    	}
    	
    }
    
    
    class HumanUtil{
    	
    	public void method1(){
    		System.out.println("==========通用的操作一=================");
    		
    	}
    	
    	public void method2(){
    		System.out.println("==========通用的操作二=================");
    		
    	}
    }
    
    
    /*
     * 要想实现动态代理类对象的功能,需要解决两个问题:
     * ①如何根据加载到内存中的被代理类对象,动态的去创建代理类的对象
     * ②如何通过代理类的对象调用接口中声明的方法时,实现对被代理类对象同名方法的调用
     * 
     */
    class MyInvocationHandler implements InvocationHandler{
    	
    	private Object obj;//被代理类的对象
    	
    	public void bind(Object obj){//实例化被代理类的对象
    		this.obj = obj;
    	}
    	
    	
    	//解决上述说明的问题②
    	//当通过代理类的对象调用接口中的方法a时,就会调用如下的InvocationHandler中的invoke()
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		
    		HumanUtil humanUtil = new HumanUtil();
    		humanUtil.method1();
    		
    		
    		//method:单行注释中的方法a
    		Object returnVal = method.invoke(obj, args);
    		
    		humanUtil.method2();
    		
    		return returnVal;
    	}
    	
    }
    
    class ProxyFactory{
    	
    	//调用此方法,返回一个代理类的对象
    	public static Object getProxyInstance(Object obj){//形参obj:被代理类的对象
    		
    		MyInvocationHandler handler = new MyInvocationHandler();
    		handler.bind(obj);
    		//解决上述说明的问题①
    		return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), handler);
    	}
    	
    }
    
    public class ProxyTest {
    	public static void main(String[] args) {
    		
    		SuperMan man = new SuperMan();//被代理类对象
    		
    		Object proxyObj = ProxyFactory.getProxyInstance(man);//proxyObj:代理类对象
    		
    		Human human = (Human) proxyObj;
    		
    		Object returnValue = human.say();//代理类对象调用接口中声明的方法
    		System.out.println(returnValue);
    		human.fly();
    		
    		System.out.println("****************");
    		
    		NikeClothFactory nike = new NikeClothFactory();
    		ClothFactory proxy = (ClothFactory) ProxyFactory.getProxyInstance(nike);
    		proxy.produceCloth();//代理类对象调用接口中声明的方法
    		
    	}
    }
    

  • 相关阅读:
    WCF基础教程之开篇:创建、测试和调用WCF
    程序员必须知道的几个Git代码托管平台
    2015继续任性——不会Git命令,照样玩转Git
    何必苦等VS2015?来看看VS2013下实现移动端的跨平台开发
    Android Studio 1.0.2项目实战——从一个APP的开发过程认识Android Studio
    (转)创建Graphics的三种方法
    sql自增长列重新从1计算
    IT之人生感悟
    c# 高效率导出多维表头excel
    SQL 之witn as语法
  • 原文地址:https://www.cnblogs.com/ttzzyy/p/9744707.html
Copyright © 2011-2022 走看看