Java反射的一点简单理解

最近才开始学Java,这两天接触了框架后对于反射的概念有很大的困惑,在网上检索了很多信息后发现大多都是在说反射怎么使用的。将反射的原理以及为什么需要反射的比较少,即使有讲很多都比较晦涩难懂。

参考: 学习java应该如何理解反射? - 罗大然不写代码的回答 - 知乎)

后来终于找到了一篇知乎回答讲反射的作用的,我觉得讲得很好,加上一些个人的些微见解记录下来。

简单的水果工厂

这位答主用了一个简单的工厂模式举例来说明反射的作用:

// Fruit接口
public interface Fruit {
    public void eat();
}

// Apple类
public class Apple implements Fruit{
    public void eat() {
        System.out.println("eat apple.");
    }
}

// Factory 用于生产Fruit
public class Factory {
    public static Fruit getInstance(String className){
        if(className.equals("Apple")){
            return new Apple();
        }else{
            return null;
        }
    }
}

// demo
Fruit f = Factory.getInstance("Apple");
f.eat();

这是一个简单的工厂模式范例,工厂通过判断传入的参数来决定生产何种水果。下面我画了一张非常简陋的示意图来说明:

代码和示意图相结合来看:demo程序使用字符串传入了需求,工厂使用if条件来判断需求,使用new对象来生产水果。而判断部分和需求存在严重的耦合:需求的任何改动都需要判断做相应变动。我在需求内每增加一种水果,判断内就得多一条条件分支。

反射的使用

这个代码非常简单,所以修改一下单个类中的代码并不麻烦。如果我们生产水果的不同类型的工厂有一百个、一千个,如果还有和水果相关的其他工厂(生产果汁等)也需要传入需求,那就完全无法解决了。而反射就能够解决这一困难:

// 重写Factory的代码
public class Factory {
    public static Fruit getInstance(String className){
//        if(className.equals("Apple")){
//            return new Apple();
//        }else{
//            return null;
//        }
        Fruit f = null;
        try {
            f = (Fruit) Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return f;
    }
}

我们通过反射,利用传入的字符串直接获取对应类的class对象,并利用class对象来创建对应的水果实体,这样就不需要在增加需求时反复修改判断部分的代码了。(这应该是称作解耦吧),同样用一张图来解释:

原本的判断部分替换成了反射,也就是说:

  1. 不再由工厂对需求进行判断
  2. 需求通过反射直接传递给JVM去查找class

通俗解释

未使用反射之前的代码,我们可以想象成一个工厂有一个专门的订单管理员,这个订单管理员每次接到甲方的需求后都会跟自己手上的生产表单(判断代码)去比对,如果表单里有这一项那么这位管理员就会前往生产线(JVM)上要求开工生产。

生产线接到管理员的指令后,便开始着手准备生产(类加载器相关内容),如果增加了新的需求,那么生产表单也需要同步进行更新,非常麻烦。而且工厂很多,每次新需求都更新表单非常的困难。

于是,这位管理员就直接下岗了(取消判断部分),直接由甲方和生产线对接,需求直接提到了生产线上,生产线根据需求来进行生产:

graph LR
id1{有无生产线}--有-->id2[生产];
id1--无-->id3[查找生产资料];
id3--有资料-->id4[开辟生产线];
id4-->id2;
id3--无资料-->放弃;

这张图涉及到了较浅显的类加载器概念,了解一下类加载器就能将这张图和实际的类加载对应起来了。

原文地址:https://www.cnblogs.com/acct-zcw/p/12299273.html

时间: 2024-11-10 03:47:08

Java反射的一点简单理解的相关文章

java反射之Constructor简单应用

Constructor类是java反射中重要的类,它是对类中构造器的描述的类.类似于Method(对类中方法的描述的类),Field(对类中属性的描述的类). 通过创建Constructor的对象实例,我们可以创建源对象. 小测试demo: package com.wtd; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Array

java反射机制的粗略理解

java反射机制: 涉及的对象:Class, Object, 函数:Class类:[forName(String className):static:getClass():public],Object类:[getClass():public]. Class Class也是一个对象,但是你不能通过构造函数得到它,它都是由jvm产生的,它通过上面的两个方法得到实例,加上下面3一共三个方式: 1.通过Object类的getClass()方法.例如: Class c1 = new String("&qu

Java反射机制的简单应用

一直感觉java的反射机制很强大,但是可用的地方不多.在android学习的时候,一直想实现挂断电话的功能,但是系统并没有提供开放的api接口,看了一下网上使用反射机制来实现该功能,确实很强大,很实用. 今天在对应的web开发中,客户端需要提交参数给服务器,自己已经写好了对应的bean文件,但是每一次都需要就其内部的key-value进行拼接,比较麻烦,突然想起了了反射机制,尝试了一下,确实非常的好用.下面看一下代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

java并发:CopyOnWriteArrayList简单理解

Java集合的快速失败机制 "fail-fast" "fail-fast"是java集合的一种错误检测机制,当多个线程对集合进行结构上的改变的操作时,有可能会产生 fail-fast 机制. 例如:假设存在两个线程(线程1.线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而

Spring Ioc容器的一点简单理解

一个简单的例子 Ioc(Inversion of Control),控制反转.名字起得比较高大上,事实上是一种工程思想,不仅适用于编程领域.我用一个简单的例子来说明IoC: 假设我们到一个餐馆里去吃饭,这个餐馆有成百上千个厨师,每位厨师只能做一样菜,这时候客人应该怎样点菜? 直接到厨房去寻找厨师,找到对应的厨师做菜 向服务员下单,由服务员将菜式需求统一报给对应厨师烹饪 正常思维都会选择第二种方法,然而我们之前的编程经常采用第一种方法:定义好类后,在执行的主程序中直接创建对应对象进行使用.假如有成

java中构造方法的简单理解(转)

构造方法就是与类同名的那个方法,它的作用是可以用来初始化class Person //人类{public Person(String n,int a) //构造方法 { name = n; age = a;} private string name; private int age;}static void main(String[] args){Person p = new Person("张三",14);//这就是作用}new一个对象的时候要用到构造函数,例如Hello hello

java内存模型:简单理解

1.Java内存模型(Java Memory Model,JMM) 2.JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory). 本地内存中存储了该线程以读/写共享变量的副本,本地内存是JMM的一个抽象概念,并不真实存在.它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化. 3.指令重排序,一般来说,处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺

Java——关于继承一点个人理解

继承(构造方法的执行顺序——父类无参.子类无参.父类无参(因为执行子类的构造函数一次就要调用父类的构造).子类有参) 1.成员变量的继承 (1).当子类与父类定义了一个同名变量时, 子类与父类的同名变量同时存在, 互不干扰(父类的变量在子类中隐藏了) (2).子类中未定义的变量可以直接从父类中继承 2.方法的继承 (1).在子类中定义了一个同名.同类型.同参数的方法时, 父类的方法将会被覆盖(不可见.即使在父类中也不可见) (2).子类未定义的方法可以从父类中直接继承(也就是说子类可以直接使用父

java中的二进制运算简单理解

package test9; public class StreamTest { public static void main(String[] args) { int a = 15;// 0b1111 int b = 8;// 0b1000 boolean bool1 = true; boolean bool2 = true; System.out.println(a ^ b);// 0b1111 ^ 0b1000 = 0b0111 一边为1则取1,其余取0 结果:7 System.out.