Java 反射机制 与 工厂设计模式

2023-11-10

Java 反射机制 与 工厂设计模式

什么是反射

Java反射机制是在运行状态中,对于任意类,都能知道这个类的全部属性和方法,对于任意对象,都能够调用它的任何一个方法或属性。这种动态获取的信息以及动态调用对象的方法的功能,称为Java语言的反射机制。

Class类

Class 是JDK提供的一个类,完整路径为 java.lang.Class,Class是反射能够实现的基础。对于每一个类,Java虚拟机都会初始化出一个Class类型的对象,Java 中的所有类型包括基本类型(int, long, float 等),即使是数组也有与之对应的 Class 类的对象。每当我们编写并且编译一个新创建的类就会产生一个对应Class对象,并且这个Class对象会被保存在同名.class文件中。当我们new一个新对象或者引用静态成员变量时,JVM中的类加载器系统会将对应Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象,创建我们需要实例对象或者提供静态变量的引用值。

Class类对象实例化

获取Class对象的三种方式,如下:

  • 利用Object类中提供的getClass方法获取实例化对象,但是需要获取一个类的实例化对象后,才可以获取Class类实例。
  • 使用“类.class” 形式获取指定类 或接口的Class实例化对象,但需要导入包,不导包就抛编译错误。
  • 使用Class类内部提供的forName(className)获取Class类对象,动态加载类,className需要是类的全限定名。

Class类对象实例化

 public class TestDemo {
         public static  void main(String args [])  {
             // new Node() 产生一个Node对象,一个Class对象
             Node node = new Node();
             // Class 类是反射机制的根源,可以通过Object类中所提供的方法获取Class实例
             // 利用Object类中提供的getClass方法获取实例化对象,需要获取一个类的实例化对象后 才可以获取Class类实例,已经有实例化对象了,再反射没啥意思。
             Class <?> cla1 = node.getClass();
             System.out.println(cla1);

             // 使用“类.class” 形式获取指定类 或接口的Class实例化对象,但需要导入包,不导包就抛编译错误。
             Class <?> cla2 = Node.class; //获取Class类实例化对象
             System.out.println(cla2 == cla1);
 
             // 使用Class类内部提供的forName()获取Class类对象,简单,最常用
             try {
                 Class cla3 = Class.forName("Node");
                 System.out.println(cla2 == cla3);
 
             } catch (ClassNotFoundException e) {
                 e.printStackTrace();
             }
 
         }
     }
 
 class Node{}

执行上述代码,输出结果为:

 class Node
 true
 true

反射机制与工厂设计模式

通常一个接口可能不止有一个子类,使用工厂设计模式的主要特点是解决接口与子类之间因直接使用关键字new所造成的耦合问题,但是传统的工厂设计操作中会存在两个严重的问题。

  1. 传统工厂设计属于静态工厂设计,需要根据传入的参数并结合大量的分支语句来判断所需要实例化的子类,当一个接口或抽象类扩充子类时必须修改工厂类结构,否则将无法获取新的子类实例,如下:
 class Node{}
 
 class Fatory{
     /**
      * 因fatory 没有属性 因此定义static方法 。
      * 获取IFood接口实例化对象,利用此方法对外隐藏子类
      */
    private Fatory(){} // 工厂类,没有产生实例化的意义,避免产生实例化对象——构造方法私有化
 ​
     /**
      * 传统工厂设计属于静态工厂设计,需要根据传入的参数并结合大量的分支语句来判
      * 断所需要实例化的子类,当一个接口或抽象类扩充子类时必须修改工厂类结构,
      * 否则将无法获取新的子类实例。
      * 
      */
     public static IFood eFood(String food) {
         if ("面包".equals(food)) {
             return new Break();
 ​
         }else if ("牛奶".equals(food)) {
             return new Milk();
         }
         else {
             System.out.println("不存在该食物");
             return null ;
         }
     }
 ​
 }
  1. 工厂设计只能够满足一个接口或抽象类获取实例化对象的需求,如果有更多的接口或抽象类定义时将需要定义更多的工厂类或扩充工厂类中的satic方法。

利用反射机制解决第一个问题

 package DemoRunable.example;
 import java.io.IOException;
 
 public class FileDemo {
     public static  void main(String args []) throws IOException, ClassNotFoundException {
         System.out.println();
         IFood food = Fatory.eFood("DemoRunable.example.Break");
         food.eat();
 
     }
 }
 
 
 interface IFood{
     public abstract void eat();// 食物核心作用 被食用
 }
 
 class Break implements IFood{
     @Override
     public void eat() {
         System.out.println("手撕面包");
     }
 }
 
 class Milk implements IFood{
     @Override
     public void eat() {
         System.out.println("喝牛奶");
     }
 }

 class Fatory{
     /**
      * 因fatory 没有属性 因此定义static方法 。
      * 获取IFood接口实例化对象,利用此方法对外隐藏子类
      */
     private Fatory(){} // 工厂类,没有产生实例化的意义,避免产生实例化对象——构造方法私有化

     /**
      *
      * @param className 实例化对象名称
      * @return 如果子类存在则返回指定类的接口实例化对象
      */
     public static IFood eFood(String className) {
         IFood food = null;
         try {
             food = (IFood) Class.forName(className).getDeclaredConstructor().newInstance();
         } catch (Exception e) {
             e.printStackTrace();
         }
         return food;
     }

     /*
     public static IFood eFood(String food) {
         if ("面包".equals(food)) {
             return new Break();

         }else if ("牛奶".equals(food)) {
             return new Milk();
         }
         else {
             System.out.println("不存在该食物");
             return null ;
         }
     }
 
 }
  */

 }

使用泛型解决解决第二个问题。

 package DemoRunable.example;
 import java.io.IOException;
 
 public class FileDemo {
     public static  void main(String args []) throws IOException, ClassNotFoundException {
         System.out.println();
         IFood food = Fatory.eFood("DemoRunable.example.Break",IFood.class);
         food.eat();
         IOther other = Fatory.eFood("DemoRunable.example.OtherOne",IOther.class);
         other.send();
     }
 }
 
 interface IFood{
     public abstract void eat();// 食物核心作用 被食用
 }
 
 class Break implements IFood{
     @Override
     public void eat() {
         System.out.println("手撕面包");
     }
 }
 
 class Milk implements IFood{
     @Override
     public void eat() {
         System.out.println("喝牛奶");
     }
 }
 interface IOther{
     public abstract void send();
 }
 class OtherOne implements IOther{
     @Override
     public void send(){
         System.out.println("开心");
 
     }
 }
 
 class OtherTwo implements IOther{
     @Override
     public void send(){
         System.out.println("很开心");
 
     }
 }
 class Fatory{
     /**
      * 因fatory 没有属性 因此定义static方法 。
      * 获取IFood接口实例化对象,利用此方法对外隐藏子类
      */
     private Fatory(){} // 工厂类,没有产生实例化的意义,避免产生实例化对象——构造方法私有化
 
     /**
      *
      * @param className 实例化对象名称
      * @param clazz 返回实例化对象类型
      * @param <T> 泛型,使得工厂类适用所有类型
      * @return 如果子类存在则返回指定类的接口实例化对象
      */
     public static <T> T eFood(String className,Class<T> clazz) {
         T food = null;
         try {
             food = (T) Class.forName(className).getDeclaredConstructor().newInstance();
         } catch (Exception e) {
             e.printStackTrace();
         }
         return food;
     }
 
 }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 反射机制 与 工厂设计模式 的相关文章

随机推荐

  • 基于matlab的多元线性回归分析

    二 多元线性回归原理 2 1 数学模型 在社会生活及生产实践中会经常遇到一种问题 即我们非常关注一个量的变化 而这个量受到另一个或是多个因素的影响 我们想要了解这些因素是如何影响我们最为关注的这个量的以及这些因素对我们最为关注的这个量的影响
  • 【C语言进阶】实现atoi函数

    1 函数介绍 atoi的函数功能 将string所指向数字字符串转化为整数 注意 1 会跳过前面的空白字符 例如空格 tab缩进 等 2 如果不能转换成 int 或者为空字符串 那么将返回 0 特别注意 该函数要求被转换的字符串是按十进制数
  • 数字图像处理-小波变换小白解释基本原则

    内容完全转载 小波理论的基本概念及概述 第二版 欢迎阅读此份关于小波变换的入门教程 小波变换是一个相对较新的概念 其出现大约是在20世纪80年代 但是有关于它的文章和书籍却不少 这其中大部分都是由数学专业人士写给其他同行看的 不过 仍然有大
  • Java解析cron表达式

    概述 Cron表达式是一个字符串 以5或6个空格隔开 分为6或7个域 每一个域代表一个含义 即两种语法格式 Seconds Minutes Hours DayofMonth Month DayofWeek Year 即 秒 分 时 天 月
  • rp学习1---web页面左侧导航栏收缩

    一 首先使用几个矩形框将所有的导航栏按照需要和层级画出来 如下 二 将父菜单和子菜单分别转化为动态面板 具体转化动态面板方式如下 选择要转为面板的部分 如两个子菜单 鼠标画框框住两个菜单即可 会将框内的所有内容作为一个面板 右击 三 选择父
  • 算法训练营第三十二天(8.16)

    目录 Leecode 435 Non overlapping Intervals Leecode 763 Partition Labels Leecode 56 Merge Intervals Leecode 435 Non overlap
  • pycharm问题求解

    为什么我的pycharm下面会弹出在 init 中找不到某个函数 我不知道在哪里设置了这个就都成这个样子了 重新安装一个模组可以暂时解决这个问题 但是切个屏就又变成这样了 正常的好像是这样的 求解
  • graph 图数据结构

    树 和 图 辨析 1 树的父节点和子节点之间是一条路单向可达 2 图的的节点之间存在多条路可达 基本概念 1 顶点 2 边 3 邻居节点 只有一条边连接的顶点 4 度 degree 一个顶点有几条边 就有几度 图的区分 1 无向图 边没有方
  • 【Shell】expect解决脚本中交互时自动输入的问题

    日常和shell相关的工作中 经常遇到要在脚本中连接其他服务器进行文件传输等操作 这些命令通常会要求和用户交互输入验证 信息 那么在脚本中如何实现自动输入口令之类的信息 这里就要用到expect 以ubuntu20为例 首先要安装这个软件
  • Unity Animancer插件(三)运动

    一 根运动 Animancer的根运动系统与原生的工作原理完全相同 但我们可以通过继承Transition类型或实现ITransition接口 来将额外的数据与动画绑定 从而更方便地控制根运动 在下面这个示例中 我们通过自定义的Transi
  • 从N个整数中判断是否有三个整数能组成三角形

    解决这个问题 可以用斐波那契数列 Fibonacci sequence 原因 斐波那契数列中的数是不可能组成三角形的 而我们只要在这些数列里面加一个数就可以有一个三角形可以组成 有了这个原因我们就可以写一个非常快速就可以判断出结果的函数 如
  • C#:递归汉诺塔

    一 运行效果截图 二 实验要求 如果n 1 直接将金片从A针移到C针上 函数输出 Form A to C 如果n gt 1时 移动过程分解为以下几个步骤 1 将A上的n 1片金片借助C针移到B针上 2 把A针上剩下的一片金片由A针移到C针上
  • stomp.min.js(stomp协议的客户端脚本)、sockjs.min.js(SockJS的客户端脚本)以及jQuery

    stomp min js stomp协议的客户端脚本 sockjs min js SockJS的客户端脚本 以及jQuery 点击打开链接
  • [ C++ ] — 智能指针

    一 三种智能指针 auto ptr unique ptr shared ptr auto ptr是C 98提供的方案 C 11已经将其摒弃 以下只是示例 实际不要使用auto ptr 使用new和delete管理动态内存常出现的问题 1 忘
  • STM32MP1开发环境搭建

    STM32MP1 wiki教程 stm32mpu 按照教程的介绍 开发MPU需要在linux环境下 一般选择在VMware虚拟机环境下安装Ubuntu 安装步骤 1 安装VMware 我安装的是VMware 10 0 0 链接 https
  • jQuery使用手册

    官方网站 http jquery com jQuery是一款优秀js开发库类 特别是对css和XPath的支持 使我们写js变得更加方便 如果你不是个js高手又想写出优 秀的js效果 jQuery可以帮你达到目的 下载地址 Starterk
  • C语言数据结构问题:停车场问题(栈和队列)

    试题描述 设停车场只有一个可停放几辆汽车的狭长通道 只有一个大门可供汽车进出 汽车在停车场内按车辆到达的先后顺序依次排列 若车场内已停满几辆汽车 则后来的汽车只能在门外的便道上等候 一旦停车场内有车辆开走 则排在便道上的第一辆汽车即可进入
  • ARP(地址解析协议)协议和RARP协议(逆地址解析协议)

    ARP协议 地址解析协议 及ARP 是根据IP地址获取物理地址的一个TCP IP协议 主机发送信息是将包含将包含目标IP地址的APR请求广播到局域网络上的所有主机 并接收返回消息 以此确定目标的物理地址 受到返回消息的时候将IP地址和物理地
  • 接口自动化之测试数据动态生成并替换

    一 测试数据 1 随机库random 查看内置random方法 该方法自行学习 不再介绍 show 2 Faker库 pip install faker showHttps github com joke2k faker 3 应用到项目中
  • Java 反射机制 与 工厂设计模式

    什么是反射 Java反射机制是在运行状态中 对于任意类 都能知道这个类的全部属性和方法 对于任意对象 都能够调用它的任何一个方法或属性 这种动态获取的信息以及动态调用对象的方法的功能 称为Java语言的反射机制 Class类 Class 是