Java中Reflect反射小结

1:反射(理解)

(1)类的加载及类加载器

(2)反射:

    通过字节码文件对象,去使用成员变量,构造方法,成员方法 
package day27_Reflect;

public class Person {
    private String name;
    private int age;
    public Person() {
        // TODO Auto-generated constructor stub
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    private Person(String name){
        this.name=name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public void show(){
        System.out.println("show");
    }
    public void method(String s){
        System.out.println("method"+s);
    }
    public String getString(String s,int i){
        return s+"---"+i;
    }
    private void function(){
        System.out.println("function");
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

package day27_Reflect;
/*
 * 反射:就是通过Class文件对象,去使用该文件中的成员变量、构造方法、成员方法
 * 
 * Person p=new Person();
 * p.使用
 * 
 * 要想这样使用,首先你必须得到Class文件对象,其实也就是得到Class类的对象
 * Class类:
 *      成员变量    Field
 *      构造方法    Constructor
 *      成员方法    Method
 * 
 * 获取Class文件对象的方式:
 *  A:Object类的getClass()方法
 *  B:数据类型的静态属性class方法
 *  C:Class类中的静态方法
 *      public static Class forName(String className)
 * 
 * 一般我们到底使用谁呢?
 *      A:自己玩   任选一种,第二种方式比较方便
 *      B:开发    第三种
 *              为什么呢?因为第三种是一个字符串,而不是一个具体的类名
 *              这样我们就可以把这样的字符串配置到配置文件中
 * */
public class ReflectDemo {

    public static void main(String[] args) throws ClassNotFoundException {
        // TODO Auto-generated method stub
        //方式1
        Person p = new Person();
        Class c = p.getClass();

        Person p2 = new Person();
        Class c2 = p2.getClass();

        System.out.println(p==p2);//false
        System.out.println(c==c2);//true

        //方式2
        Class c3=Person.class;
        System.out.println(c3==c);//true

        //方式3
        //ClassNotFoundException
        Class c4 = Class.forName("day27_Reflect.Person");
        System.out.println(c==c4);//true

    }

}

(3)反射的使用

    A:通过反射获取构造方法并使用
package day27_Reflect2;

import java.lang.reflect.Constructor;


/*
 * 通过反射获取构造方法并使用
 * */
public class ReflectDemo {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        //获取字节码文件
        Class c = Class.forName("day27_Reflect.Person");

        //获取构造方法
//      public Constructor [] getConstructor():所有公共构造方法
//      public Constructor [] getConstructors():所有构造方法
//      Constructor[] cons = c.getConstructors();
//      for(Constructor con:cons){
//          System.out.println(con);
//      }

        //获取单个构造方法
//      public Constructor<T> getConstructor(Class<T>...parameterTypes)
        //参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
        Constructor con = c.getConstructor();

        //Person person = new Person();
        //public T newInstance(Object...initargs)
        //使用此Constructor对象表示的构造方法来创建该构造方法的声明类的实例,并用指定的初始化参数初始化实例
        Object obj = con.newInstance();

        System.out.println(obj);
    }


package day27_Reflect2;

import java.lang.reflect.Constructor;

/*
 * 需求:通过反射去获取该构造方法并使用
 * public Person(String name,int age)
 * 
 * Person p=new Person("林青霞",27);
 * System.out.println(p);
 * 
 * */
public class ReflectDemo2 {

    public static void main(String[] args)throws Exception {
        // TODO Auto-generated method stub
        //获取字节码文件对象
        Class c = Class.forName("day27_Reflect.Person");

        //获取带参构造方法对象
        Constructor con = c.getConstructor(String.class,int.class);

        //通过带参构造方法对象创建对象
        Object obj = con.newInstance("林青霞",27);

        System.out.println(obj);
    }

}

package day27_Reflect2;

import java.lang.reflect.Constructor;

/*
 * 需求:通过反射获取私有构造方法并使用
 * private Person(String name){}
 * 
 * Person p=new Person("风清扬");
 * System.out.println(p);
 * */
public class ReflectDemo3 {

    public static void main(String[] args)throws Exception {
        // TODO Auto-generated method stub
        //获取字节码对象
        Class c = Class.forName("day27_Reflect.Person");

        //获取私有构造方法对象
        //publie Constructor getDeclaredConstructor(Class...parameterType)
        Constructor con = c.getDeclaredConstructor(String.class);

        //用该私有构造方法创建对象
        //IllegalAccessException:非法的访问异常
        //暴力访问
        con.setAccessible(true);//值为true则指示反射的对象在使用时应该取消Java语言访问检查
        Object obj = con.newInstance("风清扬");
        System.out.println(obj);
    }

}

    B:通过反射获取成员变量并使用
package day27_Reflect3;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/*
 * 需求:通过反射获取成员变量并使用
 * */
public class ReflectDemo {

    public static void main(String[] args)throws Exception {
        // TODO Auto-generated method stub
        //获取字节码文件
        Class c = Class.forName("day27_Reflect.Person");
        //获取所有成员变量
//      Field[] fields = c.getFields();
        //成员变量私有访问方法
//      Field[] fields = c.getDeclaredFields();
//      for(Field field:fields){
//          System.out.println(field);
//      }

        //通过无参构造方法创建对象
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj);

        //获取单个的成员变量
        //获取name的成员变量
//      Field nameField = c.getField("name");
        //获取私有成员变量
        Field nameField = c.getDeclaredField("name");
        //public void set(Object obj,Object value)
        //NoSuchFieldException:匹配异常
        //私有变量访问,需要暴力访问
        nameField.setAccessible(true);
        nameField.set(obj, "风清扬");
        System.out.println(obj);

        //对age私有成员变量赋值
        Field ageField = c.getDeclaredField("age");
        //暴力访问
        ageField.setAccessible(true);
        ageField.set(obj, 27);
        System.out.println(obj);
    }

}
    C:通过反射获取成员方法并使用
package day27_Reflect3;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectDemo2 {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        // 获取字节码文件对象
        Class c = Class.forName("day27_Reflect.Person");

        // 创建实例
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();

        // 获取单个方法并使用
        // public void show()
        // public void getMethod(String name,Class<T>...parameterType)
        // 第一个参数表示方法名,第二个参数表示的是方法的参数的class类型
        Method m1 = c.getMethod("show");
        // public void invoke(Object obj,Object...args)
        // 返回值是Object接收,第一个参数表示对象是谁,第二个参数表示调用该方法的实际参数
        m1.invoke(obj);// 调用obj对象的m1方法
        System.out.println("----------------");

        // public void method(String s)
        Method m2 = c.getMethod("method", String.class);
        m2.invoke(obj, "hello");
        System.out.println("----------------");

        Method m3 = c.getMethod("getString", String.class, int.class);
        Object objectString = m3.invoke(obj, "hello", 100);
        System.out.println(objectString);

        System.out.println("----------------");
        //private void function()
        Method m4 = c.getDeclaredMethod("function");
        m4.setAccessible(true);
        m4.invoke(obj);
    }

}

(4)反射案例

    A:通过反射运行配置文件的内容
package day27_Reflect4;

import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

/*
 * 需求:通过配置文件运行类中的方法
 * 
 * 反射:
 *      A:需要有配置文件配合使用
 *      B:用config.txt替代
 *      C:并且你知道有两个键
 *          className
 *          methodName
 * */
public class ReflectDemo {

    public static void main(String[] args)throws Exception {
        // TODO Auto-generated method stub
        //反射前的做法
//      Student s = new Student();
//      s.love();
//      Teacher t = new Teacher();
//      t.love();
//      Worker w = new Worker();
//      w.love();

        //反射后的做法
        //加载键值对数据
        Properties pro = new Properties();
        FileReader fr = new FileReader("config.txt");
        pro.load(fr);
        fr.close();

        //获取数据
        String className=pro.getProperty("className");
        String methodName=pro.getProperty("methodName");

        //反射
        Class c = Class.forName(className);
        //无参构造
        Constructor con = c.getConstructor();
        //获取实例对象
        Object obj = con.newInstance();

        //加载方法
        Method m = c.getMethod(methodName);
        //调用
        m.invoke(obj);
    }

}
    B:通过反射越过泛型检查
package day27_Reflect4;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

/*
 * 需求:利用反射实现在给定ArrayList<Integer>的一个对象
 *      我想在这个集合中添加一个字符串数据,如何实现呢?
 * */
public class ReflectTest {

    public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        // TODO Auto-generated method stub
        ArrayList<Integer> array = new ArrayList<Integer>();
//      array.add(10);
//      array.add("hello");
        //通过反射

        Class c = array.getClass();//集合ArrayList的class文件对象
        Method m = c.getMethod("add", Object.class);
        //添加数据
        m.invoke(array, "hello");
        m.invoke(array, "world");
        m.invoke(array, "java");

        System.out.println(array);
    }

}
    C:通过反射给任意的一个对象的任意的属性赋值为指定的值
package day27_Reflect4;

import java.lang.reflect.Field;

public class Tool {
    public void setProperty(Object obj,String propertyName,Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
        //此方法可将obj对象中名为propertyName的属性值设为value
        //获取对象字节码文件d对象
        Class c = obj.getClass();
        //获取该对象的propertyName成员变量
        Field field = c.getDeclaredField(propertyName);
        //取消访问检查
        field.setAccessible(true);
        //赋值
        field.set(obj, value);
    }
}

package day27_Reflect4;

public class ToolDemo {

    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        // TODO Auto-generated method stub
        Person p = new Person();
        //p.name="林青霞";//私有成员变量无法访问

        //调用Tool工具类
        Tool tool = new Tool();
        tool.setProperty(p, "name", "林青霞");
        tool.setProperty(p, "age", 27);
        System.out.println(p);

    }

}
class Person{
    private String name;
    public int age;
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return name+"---"+age;
    }
}

(5)动态代理
接口类:
package day27_Reflect_Agent;

public interface StudentDao {
    public abstract void login();
    public abstract void regist();
}
实现类:
package day27_Reflect_Agent;

public class StudentDaoImpl implements StudentDao {

    @Override
    public void login() {
        // TODO Auto-generated method stub
        System.out.println("登录");
    }

    @Override
    public void regist() {
        // TODO Auto-generated method stub
        System.out.println("注册");
    }

}
代理:
package day27_Reflect_Agent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
    private Object target;//目标对象
    public MyInvocationHandler(Object target) {
        // TODO Auto-generated constructor stub
        this.target=target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("权限校验");
        Object result = method.invoke(target, args);
        System.out.println("日志记录");
        return result;
    }

}
测试类:
package day27_Reflect_Agent;

import java.lang.reflect.Proxy;

/*
 * 通过代理实现
 * */
public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
            //未使用代理
            UserDao ud = new UserDaoImpl();
//          ud.add();
//          ud.delete();
//          ud.update();
//          ud.find();
//          System.out.println("-------------------");

            //使用代理做法
            //public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
            MyInvocationHandler handler=new MyInvocationHandler(ud);
            UserDao proxy=(UserDao) Proxy.newProxyInstance(ud.getClass().getClassLoader(),ud.getClass().getInterfaces(), handler);
            proxy.add();
            proxy.delete();
            proxy.update();
            proxy.find();
            System.out.println("---------------");

            StudentDao sd = new StudentDaoImpl();
            MyInvocationHandler handler2 = new MyInvocationHandler(sd);
            StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass().getClassLoader(), sd.getClass().getInterfaces(), handler2);
            proxy2.login();
            proxy2.regist();
    }

}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值