Java 反射机制

课程  Java面向对象程序设计

一、实验目的

掌握反射机制的使用

二、实验环境

1微型计算机一台 

2WINDOWS操作系统,Java SDK,Eclipse开发环境

三、实验内容 

1、设计一个Student类,包含姓名、年龄属性和说话方法。

2、编写一个程序,通过反射机制,创建Student类的对象,并且对它的姓名和年龄属性进行读写,最后调用它的说话方法。

3、设计一个生产类,包含一个加工方法,生产鞋子;

4、为生产类设计一个代理类,要求收取中介费1000元。

5、编写测试程序。

6、采用动态代理的方式创建代理类,同样收取1000元。

四、实验步骤和结果

  1、设计一个Student类,包含姓名、年龄属性和说话方法。

package com.student;
public class Student {
      private String name;
      private int age;
      
      public String getName() {
        return name;
    }
    public void setName(String name) {
        System.out.println("调用setName方法");
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Student() {
        super();
        System.out.println("默认的构造方法");

      }
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
          public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }
    private void StuSpeak() {
        System.out.println(getClass().getName()+"say 'Hi! Java Reflection __by shenxiaolin!'");
    }
}

  2、编写一个程序,通过反射机制,创建Student类的对象,并且对它的姓名和年龄属性进行读写,最后调用它的说话方法。

测试代码如下所示:

package com.student;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class StuReflectionTest {
    public static void main(String[] args) {
             try {
            //1、获取对应的Student类
             Class c=Class.forName("com.student.Student");
             //2、使用无参构造方法创建对象
             Student stu=(Student)c.newInstance();
             System.out.println("成功创建一个Student对象!");
             //3、调用私有属性
             Field nameField=c.getDeclaredField("name");
             nameField.setAccessible(true);//取消对“姓名”字段的访问检查
             nameField.set(stu, "沈晓");//设置stu对象的nameField的成员变量的值为沈晓
             System.out.println(">>>姓名是:"+nameField.get(stu));//获取stu对象的nameField的成员变量的值
             
             Field ageField=c.getDeclaredField("age");
             ageField.setAccessible(true);
             ageField.setInt(stu, 20);
             System.out.println(">>>年龄是:"+ageField.getInt(stu));
             
             System.out.println("成功对姓名和年龄属性进行读写!");
    
             Method method2=c.getDeclaredMethod("StuSpeak",(Class[])null);
             method2.setAccessible(true);
             method2.invoke(stu,null);
             
             System.out.println("成功调用对象的说话方法!");
             
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException 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();
        }
    }
}

运行结果如下所示:

 

  3、设计一个生产类,包含一个加工方法,生产鞋子。

(1)首先设计一个能完成生产一批鞋子功能的接口(ShoesFactory.java)

package com.produce;
//首先,定义一个能完成生产鞋子功能的接口
public interface ShoesFactory {
     //有生产鞋子的功能
    void productShoes();
}

(2)设计一个生产类(Producer.java)继承上述接口,包含一个加工方法,生产鞋子。

package com.produce;
//Producer是一个生产类,包含一个加工方法,生产鞋子
public class Producer implements ShoesFactory {
     public void productShoes() {
        System.out.println("生产鞋子公司成功生产出一批鞋子");
    }}

  4、为生产类设计一个代理类(Agency.java),要求收取中介费1000元。

package com.produce;
//为生产类Producer设计一个代理类Agency,收取中介费1000元。
public class Agency implements ShoesFactory{
    private ShoesFactory sf;
    //代理公司不会自己生产鞋子,需要找一家真正能做服务的公司
       public Agency(ShoesFactory sf) {
        super();
        this.sf = sf;
    }
       public void  productShoes() {
        System.out.println("代理公司收取中介费1000元");
        sf.productShoes();//委托真正的服务公司生产鞋子
    }
}

  5、编写测试程序(CustomerTest.java),客户通过代理公司生产了一批鞋子。

package com.produce;
//客户通过代理公司生产了一批鞋子
public class CustomerTest {
    public static void main(String[] args) {
        ShoesFactory sf=new Agency(new Producer());
        sf.productShoes();
    }
}

  该测试程序的运行结果如下所示:

 

  6、采用动态代理的方式创建代理类,同样收取1000元。

(1)首先定义一个InvocationHandler 接口:代理类的处理类都需要实现这个接口,这个接口中只有一个方法。

package com.produce;
import java.lang.reflect.Method;
//InvocationHandler 接口:代理类的处理类都需要实现这个接口,这个接口中只有一个方法。
public interface InvocationHandler {
   public Object  invoke(Object proxy,Method method, Object[] args)  throws Throwable;
}

(2)利用JDK对动态代理的支持来创建一个动态代理类,代码如下所示:

package com.produce;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.*;
//动态代理类
public class DynamicAgency implements InvocationHandler, java.lang.reflect.InvocationHandler{
//    目标对象
    private Object target;
    public Object newProxyInstance(Object target ) {
        this.target=target;
        //第一个参数是:定义代理类的类加载器
        //第二个参数是:代理类要实现的接口列表
        //第三个参数是:指派方法调用的调用处理程序
        return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),
                                      this.target.getClass().getInterfaces(),this);
    }
    public Object invoke(Object agency, Method method, Object[] args)
            throws Throwable {
        Object result=null;
          System.out.println("动态代理收取1000元中介费");
        try {
            //目标对象上的方法调用之前可以添加其他代码...
            result=method.invoke(this.target, args);
            //通过反射来调用目标对象上对应的方法
            //目标对象上的方法调用之后可以添加其他代码...
        } catch (Exception e) {
            throw e;
        }
        return result;
    }
}

(3)在客户端的调用测试代码改为如下的方式:

package com.produce;
//客户通过代理公司生产了一批鞋子
public class CustomerTest {
    public static void main(String[] args) {
        
        //静态代理
//        ShoesFactory sf=new Agency(new Producer());
//        sf.productShoes();
        
        //动态代理
        DynamicAgency dyAgency=new DynamicAgency();
        ShoesFactory sf2=(ShoesFactory) dyAgency.newProxyInstance(new Producer());
        sf2.productShoes();
    }
}

(4)测试结果为:

 

五、实验总结

  1.本次实验按时按量完成。

  2.通过本次实验,加深了我对反射相关知识的掌握,反射是指一类能够自描述和自控制的应用。即这类应用通过采用某种机制来实现对自己行为的描述(Self-representation)和监测(Examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

  3.使用带参构造方法创建对象的步骤:

   第1步  获取指定类对应的Class对象。

   第2步  通过Class对象获取满足指定参数类型要求的构造方法类对象。

   第3步  调用指定Constructor对象的newInstance方法,传入对应的参数值,创建出对象。

  4.静态代理是指在客户端和目标对象之间起到中介的作用。动态代理的原理是在程序运行时根据需要动态创建目标类的代理对象。Java SE API在java.lang.reflect包中提供了对动态代理支持的类和接口。

 

 

原文地址:https://www.cnblogs.com/shenxiaolin/p/5040311.html