JAVA学习笔记-反射(黑马程序员)

JAVA学习笔记-反射

一、什么是反射

反射允许对封装类的字段、方法和构造函数的信息进行编程访问。

二、获取class对象的三种方式

在这里插入图片描述

Class.forName(“全类名”);
源代码阶段。
类名.class
加载阶段。
对象.getClass();
运行阶段。

//最为常用
Class clazz = Class.forName("com.myreflect.Student");

//一般更多的是当作参数进行传递
Class clazz1 = Student.class;
System.out.println(clazz1);

//当有了一个对象后,才使用
Student stu = new Student();
System.out.println(stu.getClass());

三、反射获取构造方法

在这里插入图片描述

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
   // 获取字节码文件对象
   Class clazz = Class.forName("com.myreflect.Student");
   // 获取构造方法
   Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);
   int modifoers = constructor.getModifiers();

   Parameter[] parameters = constructor.getParameters();
//        for (Parameter parameter : parameters) {
//            System.out.println(parameter);
//        }
   constructor.setAccessible(true); //暴力创建
   Student stu = (Student) constructor.newInstance("张三", 19);
   System.out.println(stu);
}

四、反射获取成员变量

在这里插入图片描述

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
  // 获取字节码文件对象
  Class clazz = Class.forName("com.myreflect.Student");
  // 获取成员变量
  // Field[] declaredFields = clazz.getDeclaredFields();
  // 获取单个变量 获取私有的变量
  Field field = clazz.getDeclaredField("name");
  System.out.println(field);

  // 获取数据类型
  Class<?> type = field.getType();
  System.out.println(type);

  // 获取成员变量记录的值
  field.setAccessible(true); //不进行校验修饰符,因为name是private的
  Student student = new Student("张三", 12);
  System.out.println(field.get(student));

}

五、反射获取成员方法

在这里插入图片描述

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
   // 获取字节码文件对象
   Class clazz = Class.forName("com.myreflect.Student");
   // 获取成员方法
   Method method = clazz.getDeclaredMethod("sleep");

   int modifiers = method.getModifiers();

   // 方法的异常
   Class<?>[] exceptionTypes = method.getExceptionTypes();

   method.setAccessible(true);
   Student stu = new Student("张三", 18);
   method.invoke(stu);
}

六、综合练习

1.对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException {
   Student student = new Student("张三", 29);
   saveObject(student);
}
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
   Class clazz = obj.getClass();
   Field[] declaredFields = clazz.getDeclaredFields();
   BufferedWriter bw = new BufferedWriter(new FileWriter("two/a.txt"));
   for (Field field : declaredFields) {
       field.setAccessible(true);
       String fieldName = field.getName();
       Object o = field.get(obj);
       bw.write(fieldName + ":" + o);
       bw.newLine();
   }
   bw.close();
}

2.反射与配置文件结合,动态创建对象,并调用方法

配置文件

classname=com.myreflect.Student
method=sleep
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException {
    Properties prop = new Properties();
    FileInputStream fis = new FileInputStream("two/prop.properties");
    prop.load(fis);
    fis.close();
    Class clasz = Class.forName(prop.get("classname").toString());
    Constructor declaredConstructor = clasz.getDeclaredConstructor();

    declaredConstructor.setAccessible(true);
    Student stu = (Student) declaredConstructor.newInstance();

    Method method = clasz.getDeclaredMethod(prop.get("method").toString());

    method.setAccessible(true);
    method.invoke(stu);
}

七、动态代理

特点:无侵入式的给代码增加额外的功能

通过接口保证,后面的对象和代理需要实现同一个接口。
在这里插入图片描述

 public interface Star {
     // 所有被代理的方法写到接口中
     public abstract String sing(String name);
     public abstract void dance();
 }
public class BigStar implements Star{
    private  String name;

    public String getName() {
        return name;
    }
    @Override
    public String sing(String name) {
        System.out.println(this.name + "正在唱" + name);
        return "谢谢";
    }
    @Override
    public void dance() {
        System.out.println(this.name + "正在跳舞");
    }
    public void setName(String name) {
        this.name = name;
    }

    public BigStar(String name) {
        this.name = name;
    }

    public BigStar() {
    }
}
// 代理类
public class ProxyUtil {
    /*
    * 创建一个代理
    *
    *
    *
    *  */


    public static Star creatProxy(BigStar bigStar) {
        Star star = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), // 指定哪个加载器去加载生成的代理类
                new Class[]{Star.class}, // 指定接口,代理长什么样
                new InvocationHandler() { // 代理对象干什么
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 代理的对象, 方法, 参数数组
                        if("sing".equals(method.getName())){
                            System.out.println("准备话筒,收钱");

                        } else if ("dance".equals(method.getName())) {
                            System.out.println("准备场地,收钱");
                        }
                        return method.invoke(bigStar, args); //反射
                    }
                });
        return star;
    }
}
//test
public class Test {
    public static void main(String[] args) {
        BigStar  bigStar = new BigStar("鸡哥");
        Star star = ProxyUtil.creatProxy(bigStar);
        System.out.println(star.sing("只因你太美!"));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值