Java反射一:反射引入(一个案例,感性认识什么是反射);

2021/4/19 20:25:21

本文主要是介绍Java反射一:反射引入(一个案例,感性认识什么是反射);,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

反射(Reflect)是学习各种框架的基础!!!

目录

1.反射简介

2.反射案例(目的仅用于感受什么是反射)

(1)案例准备:一个接口,三个实现类

(2)案例准备:演示的入口类:ReflectSample类


1.反射简介

(1)以前写代码的时候,要实例化一个对象,需要使用new关键字实例化指定的类,这是把类实例化的工作写死在代码中的;这种固定写死的代码不够灵活,在实际工作中总会不太方便;即原先创建对象的时机是程序编译的时候。

         反射的根本目的:把创建对象的时机从【程序编译的时候】  延迟到  【程序运行时】;

(2)反射JDK1.2才有;其隶属于java.lang.reflect包,所有与反射相关的类都存放在这个包中;

(3)后续的java高级框架,这些框架在应用程序启动的时候,会动态的读取配置文件的信息,同时利用反射技术在运行的时候去创建不同的对象;

反射让java程序变得更加灵活,更加容易被管理。


2.反射案例(目的仅用于感受什么是反射)

(1)案例准备:一个接口,三个实现类

MathOperation接口(四则运算接口);三个实现类:Addition类(加法类);Multiplication类(乘法类);Subtraction(减法类);一个演示的入口类:ReflectSample类;

如下:

MathOperation接口(四则运算接口)

package com.imooc.reflect;

/**
 * 四则运算接口
 */
public interface MathOperation {
    public float operate(int a , int b);
}

三个实现类之: Addition类(加法类)

package com.imooc.reflect;

/**
 * 加法
 */
public class Addition implements MathOperation {
    @Override
    public float operate(int a , int b) {
        System.out.println("执行加法运算");
        return a + b;
    }
}

三个实现类之: Multiplication类(乘法类): 

package com.imooc.reflect;

public class Multiplication implements MathOperation {
    @Override
    public float operate(int a, int b) {
        return a * b;
    }
}

 三个实现类之: Subtraction(减法类): 

package com.imooc.reflect;

/**
 * 减法运算
 */
public class Subtraction implements MathOperation {
    @Override
    public float operate(int a, int b) {
        System.out.println("执行减法运算");
        return a - b;
    }
}

(2)案例准备:演示的入口类:ReflectSample类

package com.imooc.reflect;

import java.util.Scanner;

/**
 * 初识反射的作用
 */
public class ReflectSample {
    /**
     * 传统的创建对象方式
     */
    public static void case1(){
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入计算类名:");
        String op = scanner.next();
        System.out.print("请输入a:");
        int a = scanner.nextInt();
        System.out.print("请输入b:");
        int b = scanner.nextInt();
        MathOperation mathOperation = null;
        if(op.equals("Addition")){
            mathOperation = new Addition();
        }else if(op.equals("Subtraction")) {
            mathOperation = new Subtraction();
        }else{
            System.out.println("无效的计算类");
            return;
        }
        float result = mathOperation.operate(a, b);
        System.out.println(result);
    }

    /**
     * 利用反射创建对象更加灵活
     */
    public static void case2(){
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入计算类名:");
        String op = scanner.next();
        System.out.print("请输入a:");
        int a = scanner.nextInt();
        System.out.print("请输入b:");
        int b = scanner.nextInt();
        MathOperation mathOperation = null;
        try {
            mathOperation = (MathOperation) Class.forName("com.imooc.reflect." + op).newInstance();
        }catch(Exception e){
            System.out.println("无效的计算类");
            return;
        }
        float result = mathOperation.operate(a, b);
        System.out.println(result);
    }



    public static void main(String[] args) {
        ReflectSample.case1();
        //ReflectSample.case2();
    }
}

上面case1()方法是传统的解决办法;其中只做了加法和减法的处理,即只实例化了Addition类(加法类)和Subtraction(减法类);可以设想一下,如果想要增加乘法的话,首先需要有Multiplication类(乘法的实现类),还需要在case1()方法中增加一个else if做个判断,然后再实例化Multiplication类(乘法类);如下:

缺点:为了实现功能的修改,需要修改源代码……

但在真正的企业应用中,修改源代码要慎重。而且,每次修改源代码后,都需要重新测试,重新打包,重新上线,这个过程是非常麻烦的。

在不修改源代码的情况下,动态让程序支持新的功能。就如case2()方法的内容了:

上面case2()方法利用了反射技术,在运行时动态的创建对应的对象;想增加乘法的时候,case2()的代码不需要做任何调整,只需要在“请输入计算类名”的时候输入【Multiplication】就能自动的完成乘法的逻辑。

核心:mathOperation = (MathOperation) Class.forName("com.imooc.reflect." + op).newInstance();

      Class.forName():反射中最常用的方法,作用是加载指定的类;

      newInstance():对Class.forName()方法获取到的类进行实例化;

……………………………………………………

Summary:

即case1()这种传统的方式,把实例化类的工作放在了【程序编译的时候】,即在【ReflectSample类】的class字节码文件产生的时候,在【ReflectSample类】中创建那些类的实例对象就已经确定了;

但是case2()这种利用反射的方式,把实例化类的工作放在了【程序运行时】,当java的编译器看到【 (MathOperation) Class.forName("com.imooc.reflect." + op).newInstance();】的时候,其并不知道要创建哪个对象,因为op的数据是在运行以后才会产生的;

利用反射,可以在程序运行时动态的决定创建哪些对象,并且访问这些对象的哪些方法和属性;

正是因为Java提供了反射这种灵活的特性,才诞生了Spring,Mybatis这些高级框架;这些高级框架都是以反射为基础的。

……………………………………………………

注解:.class,Class.forName()和.getClass()的区别:

Class.class用来返回 Class 对象。

Class.forName()是反射机制的一种,用于获取指定的Class对象。

getClass()方法是获取该对象的class(类),可以通过返回的Class对象获取类的相关信息

区别如下:

1) .getClass()是动态的,其余是静态的;

2) .class和class.forName()只能返回类内field的默认值,getClass可以返回当前对象中field的最新值;

3) Class.forName() 返回的是一个类,.newInstance() 后才创建一个对象,Class.forName()的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的;

 

 

 

 



这篇关于Java反射一:反射引入(一个案例,感性认识什么是反射);的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程