当前位置: 首页 > news >正文

27、Java 反射机制

15-1 Java 反射机制概述


Reflection(反射)是被视为动态语言的关键

动态语言:在运行时代码可以根据某些条件改变自身结构。如 C#\JavaScript\PHP

静态语言:运行时结构不可变的语言。如 Java\C\C++

问题:通过直接new的方式或反射的方式都可以调用公共的结构,开发中到底用哪个

建议:直接new的方式

反射特征:动态性


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


哪些类可以有Class对象?

1、class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类

2、interface:接口

3、[]:数组

4、enum:枚举

5、annotation:注解@interface

6、primitive type:基本数据类型

7、void


15-3类的加载与ClassLoader的理解

(主要了解即可)

CleanShot 2025-03-03 at 14.04.18


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

package com.java5.kcw;

import org.junit.Test;

/**通过反射创建对应的运行时类的对象
 * @author Jackson_kcw
 * @Time 2025-03-03  PM2:23
 */
public class NewInstanceTest {
    @Test
    public void test() throws InstantiationException, IllegalAccessException {
        Class clazz=Person.class;

        //newInstance():调用此方法,创建对应的运行时类的对象;内部调用了运行时类的空参构造器
        /*
        要想此方法正常的创建运行时类的对象,要求:
        1、运行时类必须提供空参的构造器
        2、空参的构造器的访问权限得够。通常,设置为 public

        在 javabean 中要求去提供一个 public 的空参构造器 原因:
        1、便于通过反射,创建运行时类的对象
        2、便于子类继承此运行时类,默认调用 super()时,保证父类有构造器
         */
        Object ob = clazz.newInstance();
        System.out.println(ob);
    }
}

体会反射的动态性,这是一个很重要的思想


15-5 调用运行时类的指定结构


package com.java5.kcw;

import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author Jackson_kcw
 * @Time 2025-03-03  PM2:51
 */
public class ReflectionTest1 {
    //这个方法现在已经很多不使用了,无需掌握
    @Test
    public void test1() throws Exception {
        Class clazz=Person.class;
        //创建运行时类的对象
        Person p=(Person)clazz.newInstance();

        //获取指定的属性:要求运行时类中属性声明为 public
        //通常不采用此方法
        Field id= clazz.getField("id");

        /*
        设置当前属性的值
        set():参数一:指明设置那个对象的属性    参数二:将此属性值设置为多少
         */
        id.set(p,1001);

        /*
        获取当前属性的值
        get() 参数一:获取哪个对象的当前属性值
         */
        int pId=(int)id.get(p);
        System.out.println(pId);


    }

    /*
    这个方法很重要的
     */
    @Test
    public void test2() throws Exception {
        Class clazz=Person.class;
        //创建运行时类的对象
        Person p=(Person)clazz.newInstance();

        //getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
        Field name=clazz.getDeclaredField("name");

        //setAccessible(true) :保证当前属性是可访问的
        name.setAccessible(true);
        name.set(p,"Jackson");

        System.out.println(name.get(p));
    }

    //如何操作运行类中的指定方法
    @Test
    public void test3() throws Exception {
        Class clazz=Person.class;
        //创建运行时类的对象
        Person p=(Person)clazz.newInstance();

        Method setName = clazz.getDeclaredMethod("setName", String.class);
        setName.setAccessible(true);
        //invoke() 参数 1:方法的调用者  参数二:给方法形参赋值的实参
        //invoke()返回值即为对应类中调用的方法的返回值
        setName.invoke(p,"Kik");
        System.out.println(p.getName());
        System.out.println("****************如何调用静态方法*****************");


        Method showDesc = clazz.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
        showDesc.invoke(p);
    }
}


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


package com.java6.kcw;

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

/**动态代理
 * @author Jackson_kcw
 * @Time 2025-03-03  PM3:25
 */

interface Human{
    String getBelief();

    void eat(String food);

}
//被代理类
class SuperMan implements Human{


    @Override
    public String getBelief() {
        return "I believe I can Fly";
    }

    @Override
    public void eat(String food) {
        System.out.println("I like eat"+food);
    }
}
/*
想要实现动态代理,需要解决的问题?
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象
问题二:当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法

 */

class ProxyFactory{
    //调用此方法,返回一个代理类的对象,解决问题一
    public static Object getProxyInstance(Object obj){//obj:被代理类的对象
        MyInvocationHandler handle= new MyInvocationHandler();
        handle.bind(obj);

       return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),handle);

    }
}
class MyInvocationHandler implements InvocationHandler {
    private Object obj;//需要使用被代理类的对象进行赋值
    public void bind(Object obj){
        this.obj = obj;
    }

    //当我们通过代理类的对象,调用方法 a 时,就会自动的调用如下的方法:invoke()
    //将被代理类要执行的方法 a 的功能就声明在 invoke()中
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method:即为代理类对象调用的方法,此方法也就作为 被代理类对象要调用的方法
        //obj:被代理类的对象
        Object returnValue = method.invoke(obj, args);
        //上述方法的返回值就作为当前类中的 invoke()的返回值
        return returnValue;
    }
}
public class ProxyTest {
    public static void main(String[] args) {
        SuperMan superman = new SuperMan();
        //proxyInstance:代理类的对象
        Human human = (Human) ProxyFactory.getProxyInstance(superman);
        //当通过代理类对象调用方法时,会自动调用被代理类中同名的方法
        human.getBelief();
        human.eat("烧烤");

    }
}



http://www.dtcms.com/a/48744.html

相关文章:

  • LeetCode 225. 用队列实现栈 java题解
  • 《2025软件测试工程师面试》性能测试面试篇
  • C++知识整理day10——多态(多态的定义和实现、虚函数重写/覆盖、override和final关键字、纯虚函数和抽象类、多态的原理)
  • macOS skhd+ yabai
  • 动态扩缩容引发的JVM堆内存震荡:从原理到实践的GC调优指南
  • 标签的ref属性 vue中为什么不用id标记标签
  • RTC、直播、点播技术对比|腾讯云/即构/声网如何选型 — 2025 版
  • centos虚拟机安装
  • 嵌入式学习笔记-卡尔曼滤波,PID,MicroPython
  • 一、图形图像的基本概念
  • 《白帽子讲 Web 安全》之文件操作安全
  • 基于Android平台的SOME/IP测试模块 EPT-ETS
  • 一、计算机网络技术——概述、性能指标
  • React Native从入门到进阶详解
  • 探秘基带算法:从原理到5G时代的通信变革【九】QPSK调制/解调
  • 钉钉宜搭智能车辆管理系统:AIoT技术驱动的全场景解决方案(价值体现版)
  • ps学习一
  • 【JSON与JSONP】JSON与JSONP全面解析:定义、区别与核心技术对比
  • 《OpenCV》——卷积神经网络人脸检测
  • 网络编程相关概念
  • (十二)基于 Vue 3 和 Mapbox GL 实现的坐标拾取器组件示例
  • spark写数据库用连接池找不到driver类
  • 安装 cnpm 出现 Unsupported URL Type “npm:“: npm:string-width@^4.2.0
  • iterm2更新后主题报错
  • SpringBoot篇(自动装配原理)
  • 大模型学习笔记------LLM模型开发流程
  • Python----数据分析(Matplotlib二:绘图一:折线图,条形图,直方图)
  • Python 爬取唐诗宋词三百首
  • C# Unity 唐老狮 No.4 模拟面试题
  • JDBC核心技术解析:从基础连接到ORM演进之路(上)