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

红烧土豆泥 等级 758 0 0
标签: beanJava

什么是反射? 为什么说反射是黑魔法? 为什么要在工厂设计模式前扯反射这东西? 首先,既然在工厂设计模式前整它,肯定是在处理工厂设计模式时会用到它;既然都用黑魔法来形容它了,肯定是它异常强大; 那什么是反射嘞?既然能被称为"反",那就肯定会有"正",那,正。。。是啥子嘞?想当然,既然平时我们都不怎么搞反射,那我们平日整的就是正了呗!平时我们实例化一个对象都是是使用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核心技术卷一的解释就是一个能分析类的能力的程序。 欲知后事如何,请看下篇黑魔法工厂的爱恨情仇 ~

收藏
评论区

相关推荐

创建型工厂设计模式之前置黑魔法(反射)
什么是反射? 为什么说反射是黑魔法? 为什么要在工厂设计模式前扯反射这东西? 首先,既然在工厂设计模式前整它,肯定是在处理工厂设计模式时会用到它;既然都用黑魔法来形容它了,肯定是它异常强大; 那什么是反射嘞?既然能被称为"反",那就肯定会有"正",那,正。。。是啥子嘞?想当然,既然平时我们都不怎么搞反射,那我们平日整的就是正了呗!平时我们实例化一个对象都是是
1.1Spring Boot 环境配置和常用注解
**Spring Boot常用注解:** @Service: 注解在类上,表示这是一个业务层bean @Controller:注解在类上,表示这是一个控制层bean @Repository: 注解在类上,表示这是一个数据访问层bean @Component: 注解在类上,表示通用bean ,value不写默认就是类名首字母小写 @Auto
JavaFX学习之道:JavaFX之TableView
TableView表 TableColumn列 构建一个表主要有TableView,TableColumn,ObservableList,Bean。 添加列table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); ObservableList里面是存放的数据
1.利用BeanMap进行对象与Map的相互转换
javabean与map的转换有很多种方式,比如: 1、通过ObjectMapper先将bean转换为json,再将json转换为map,但是这种方法比较绕,且效率很低,经测试,循环转换10000个bean,就需要12秒!!!不推荐使用 2、通过java反射,获取bean类的属性和值,再转换到map对应的键值对中,这种方法次之,但稍微有点麻烦 3、通过
NetBeans配置Spring
<bean id="obstacle1" class="C:\launchCodeFiles\src\main\java\RunMario.java"> 改为 <bean id="obstacle1" class="RunMario"> class路径为(包名+类名) <?xml version="1.0" encoding=
Spring Bean详细讲解
### 什么是Bean? Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象。 Spring [容器会自动完成@bean对象的实例化](https://www.oschina.net/action/GoToLink?url=mailto%3A%25E5%25AE%25B9%25E5%2599%25A8%25E4%25BC%2
Spring IOC 练习
练习题 实验一 | 通过IOC容器创建对象,并为属性赋值 实验二 | 通过Bean的类型从IOC中获取bean的实例 实验三 3.1使用构造器在IOC中创建bean 3.2通过p名称空间为bean赋值 实验四 4.1正确的为各种属性赋值 测试使用nu11值、 引用类型赋值(引用其他bean、引用内部bean) 集合类型赋值(Lis
Spring Ioc之BeanFactory
     IoC(Inversion of Control),即所谓的控制反转,就是应用本身不负责依赖对象的创建及维护, 依赖对象的创建及维护是由外部容器(BeanFactory)负责的。      Spring通过配置文件(或者注解、JavaConfig)描述Bean和Bean之间的依赖关系,利用反射机制实例化Bean并建立Bean之间的依赖关系。Spr
Spring 源码分析之 bean 实例化原理
本次主要想写spring bean的实例化相关的内容。创建spring bean 实例是spring bean 生命周期的第一阶段。bean 的生命周期主要有如下几个步骤: * <font color='red'>创建bean的实例</font> * 给实例化出来的bean填充属性 * 初始化bea * 通过IOC容器使用bean *
Spring4
    方法注入主要是用在Singleton的Object中使用非Singleton的Bean时,通过lookup-method的那个方法来取得非Singleton的Bean。一般用的不多,在用这种定义之前最好想明白你的需求。 1 使用Java代码实现方法注入 ================ 1.1 用法示例 -------- // a cl
SpringMvc中@resource和@autowired区别
在java代码中使用@Autowired或@Resource注解方式进行装配 这两个注解的区别是: **@Autowired** 默认**按类型**装配, **[@Resource](https://my.oschina.net/u/929718)** 默认**按名称**装配,当找不到与名称匹配的bean才会按类型装配。 如果我们想使用按名称装
Spring中的bean是线程安全的吗?
**结论:不是线程安全的** Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。 Spring 的 bean 作用域(scope)类型: * singleton:单例,默认作用域。 * p
Spring中管理Bean依赖注入之后和Bean销毁之前的行为
    对于Singleton作用域的Bean,Spring容器将会跟踪它们的生命周期,容器知道何时实例化结束、何时销毁。Spring可以管理Bean在实例化结束之后和Bean销毁之前的行为。 **Bean依赖关系注入之后的行为:**     Spring提供了两种方式在Bean全部属性设置成功后执行特定的行为: * 在Spring配置文件
Spring实战 难懂的JavaBean
bean中文解释为:豆; 豆形种子; 毫无价值的东西。 按照上面的意思,很难理解Bean是个什么鬼,Java豆? 我们先来看一个典型的JavaBean,直观地理解下: public class Person implements Serializable { private static final long serialVer
Spring容器中Bean的作用域
当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。**Spring支持如下5种作用域:** * **singleton**:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例 * **prototype**:原型模式,每次通过容器