创建型工厂设计模式之前置黑魔法(反射)

红烧土豆泥
• 阅读 1629

什么是反射? 为什么说反射是黑魔法? 为什么要在工厂设计模式前扯反射这东西? 首先,既然在工厂设计模式前整它,肯定是在处理工厂设计模式时会用到它;既然都用黑魔法来形容它了,肯定是它异常强大; 那什么是反射嘞?既然能被称为"反",那就肯定会有"正",那,正。。。是啥子嘞?想当然,既然平时我们都不怎么搞反射,那我们平日整的就是正了呗!平时我们实例化一个对象都是是使用new关键字,例如:

  Person per = new Person();

那反的自然就是不使用new关键字了嘛~ 在正式了解不使用new来实例化一个类前,我们需要先了解反射手下的几名大将(类)及它们的一些技能特效(方法使用)。


军师 -> Class类(java.lang.Class) 是不是突然眼前一亮,我好像在哪见过,好像还用过它,他不是关键字吗?怎么突然变成一个类了???是不是突然又突然发现经常用的那个class和这个Class还是有点区别的,没错,这个首字母大写了。那这个Class是干啥子的嘞? 首先让我们先看一个小demo

  public class Person {
    public Person() {}

    @Test
    public void fun() {
        Class<Person> clazz = Person.class;
        System.out.println(clazz);
        System.out.println(clazz.getName());
    }

}

输出的是:class test.reflect.Bean.Person test.reflect.Bean.Person 首先我们写了一个Person类,里面我们什么都没写,然后写了一个测试方法,通过Person.class获取了Class对象,输出后发现,就是此类的各级包路径+本类名。如果是clazz.getName则是没有了class这个头,也就是说它的Name值实际上就是test.reflect.Bean.Person。但是这个东东它有什么作用嘞?还不怎么清楚。继续再看,

  public class Person {
    public Person() {}

    @Test
    public void fun() {
        Person per = new Person();
        Class<? extends Person> clazz = per.getClass();
        System.out.println(clazz);
        System.out.println(clazz.getName());
    }
}

输出的是:class test.reflect.Bean.Person test.reflect.Bean.Person 我们在测试中,首先是将Person实例化了,然后通过getClass获取到了Class对象,输出的结果是不是发现他们竟然是一样子的,是不是突然感觉他们之间有着啥不可告人的秘密~ 再看下面的一个

  @Test
    public void fun() {
        try {
            Class<?> clazz = Class.forName("test.reflect.Bean.Person");
            System.out.println(clazz);
            System.out.println(clazz.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

输出的是:class test.reflect.Bean.Person test.reflect.Bean.Person 是不是想,噫 ~ 这东西有啥用哇?看出来了,看出来了,他们都是一样的,但是他们有啥子用嘛! 别急,别急,有没有注意到这边开始有异常抛出了,还是ClassNotFoundException异常,所以听我继续跟你们扯

  public class Person {
    private String name;

    public Person() {
    }

    public Person(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("test.reflect.Bean.Person");
            Person per = (Person) clazz.getDeclaredConstructor().newInstance();
            per.setName("老王");
            System.out.println(per.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出:老王 在这个例子中,有没有注意到,没有new关键字的出现,感觉我没有对Person对象进行实例化,但是我却调用了它的getter和setter方法,还成功输出了"老王"。但是,既然输出了老王,那也就证明了Person这个对象被实例化了。怎么实例化的?没看到,偷麽麽的,那就是反的了呗!即通过反射对这个对象进行了实例化。 首先我们先看Class类的两个方法, 方法一:getDeclaredConstructor(类<?>... parameterTypes) -> 返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。 方法二:newInstance() -> 创建由此 类对象表示的类的新实例。 看到这,你可能会想直接用newInstance()不就好了,为啥还要用上面的那个,如果你去翻看jdk的API的话你就会注意到这个方法在1.9版本就已经被废弃了,但是还可以使用,原文如下图 创建型工厂设计模式之前置黑魔法(反射) 文档上明确表述了它的作用Creates a new instance of the class represented by this Class object以及它的用法clazz.getDeclaredConstructor().newInstance(),到此,是不是可以联想到我们之前写的三个获取类的class对象的作用了。


来再看反射手下的第二名大将 大元帅 -> Method类(java.lang.reflect.Method) 我们先来看一段代码

  public class Person {
    private String name;

    public Person() {
    }

    public Person(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("test.reflect.Bean.Person");
            Method[] method = clazz.getDeclaredMethods();

            for(Method str:method) {
                System.out.println("方法名:"+str.getName()+"\t方法类型:"+Modifier.toString(str.getModifiers())+"\t返回值类型:"+str.getReturnType());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出: 方法名:getName 方法类型:public 返回值类型:class java.lang.String 方法名:main 方法类型:public static 返回值类型:void 方法名:setName 方法类型:public 返回值类型:void

是不是感觉输出这些东西很熟悉啊!但是你可能回想,这有啥用嘛! 别急,继续看下面的一个例子:

  public class Person {
    private String name;

    public Person() {
    }

    public Person(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("test.reflect.Bean.Person");
            Person per = (Person) clazz.getDeclaredConstructor().newInstance();
            Method[] method = clazz.getDeclaredMethods();

            for(Method str:method) {
                if("setName".equals(str.getName())) {
                    str.invoke(per, "老王");
                }
            }
            System.out.println(per.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

看它的输出:老王 是不是感觉很神奇!到这可能还没搞清楚反射究竟是一个啥东西啊?扯了这么多,还没说明白!按照JAVA核心技术卷一的解释就是一个能分析类的能力的程序。 欲知后事如何,请看下篇黑魔法工厂的爱恨情仇 ~

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
happlyfox happlyfox
3年前
笑说设计模式-小白逃课被点名
关于我简介工厂模式(FactoryPattern)是最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来指向新创建的对象。分类工厂模式可以分为三种,其中简单工厂一般不被认为是一种设计模式,可以将其看成是工厂方法的一种特殊
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java 成神之路 (二)
前一篇博客介绍了如何通过注解反射来实例化一个对象。前面提出的一个优化建议。上一版本,每个含有@DAL(http://my.oschina.net/daL)注解的变量都会通过反射去得到实例化对象。要是同一个工程里面每次都对同一个类通过反射实例化一个对象出来,这样太浪费资源了。现在我们就模拟spring的bean工厂,
桃浪十七丶 桃浪十七丶
3年前
工厂模式实例(顺便回忆反射机制的应用)
一、原理反射机制的原理JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。工厂模式自述所谓工厂模式,是说由某个产品类接口、产品实现类、工厂类、客户端(单元测试主类)构成的一个模式,大程度的降低了代码的
Wesley13 Wesley13
3年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Wesley13 Wesley13
3年前
C#设计模式 —— 工厂模式
。  工厂模式同样是项目中最常用的设计模式,工厂模式中又分为简单工厂,工厂方法,抽象工厂。下面我们由简单的开始逐一介绍。1.简单工厂模式  简单工厂又被称为静态工厂,在设计模式中属于创建型模式。主要解决的问题是封装了实例化的过程,通过传入参数来获不同实例。下面我们举一个项目中可能会用到的例子。  假设我们程序的数据保存在几个不同
Wesley13 Wesley13
3年前
Java重点基础:反射机制
一、什么是反射?Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。二、反射的三种方式
Wesley13 Wesley13
3年前
C++ 常用设计模式(学习笔记)
设计模式1、工厂模式在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。工厂模式作为一种创建模式,一般在创建复杂对象时,考虑使用;在创建简单对象时,建议直接new完成一个实例对象的创建。1.1、简单工厂模式主要特点是需要在工厂类中做判断,从而创造相应的产品,当