Java反射机制

本文详细介绍了Java反射机制,通过实际场景解释如何在运行时动态创建对象和调用方法。通过反射,可以避免大量if-else语句,提高代码灵活性,降低耦合度。示例代码展示了如何根据配置文件内容动态调用类的方法,体现了反射在实际开发中的应用。
摘要由CSDN通过智能技术生成

Java反射机制

  关于反射,我也是听过很多遍,我也去学习了一段时间,但是一直模模糊糊的,平时像我是做前端的,更没有机会遇见。现在有空闲时间了,就找了很多的文章看了,梳理了下,好歹是弄清楚了点。

介绍:

  我看了很多的介绍,第一句话就是告诉你:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;这句话虽然简单,但是像我这种实践少的,理解起来就特别费劲,没有具体的场景,感觉只能算是对自己猜测的一种认可。
  为了更好理解反射机制,我又回头来补充了一下。想一下这样一个场景:

场景一:
  有时候你获得了一个类的名字,想创建这个类,但是这时候你发现它是一个String字符,那么怎么用这个String字符去创建这个类呢?通常情况下我们会这样写:

	...
	String className = "Cat";
	...
	if("Cat".equals(className)){
		Cat cat = new Cat("xxx");
		return cat;
	}

  这样写没错,但是我们假设有很多不同的类要生成(Dog类、Fish类…),这时候我们得不断加else if,每次都得来代码中添加几行代码。
  但是,java反射机制给了我们很好的一个解决方法,那就是反射,我们就可以直接通过String生成对应的类。

	...
	String className = "xxx.xxx.Cat"; // 要求是类的全路径(放在哪个包下)
	...
	Object obj = Class.forName(className).newInstance(); // 运行类型为className值的类型,这里为Cat
	// 上面的Class.forName(xxx)就是加载xxx类,返回一个Class类(也是一个类)
	// newInstance()就是创建实例
	// 所以上面的就相当于 new className(); -> new Cat();

  这样的话,我们用一句话就解决了上面的问题,无论是哪个对象的生成,都可以通过上面的代码实现,就没必要反复去添加else if了。

场景二:
  这里其实有一个很明显的例子:就是你使用编程软件的时候用到的东西,当你输入一个类的时候,你输入.这个符号的时候,他会把这个类的方法给你显示出来。这样来看,“运行状态”中指的就是你的编程软件运行,然后他通过反射手段,把你类的所有属性和方法拿到,在把相应的部分显示给你。(通过getMethods()返回类所有的方法,getFields()返回所有的字段(也就是属性))。
在这里插入图片描述
  通过反射,加载类(Class clazz = Class.forName(xxx))之后,它会识别出你类中的方法,属性(内部实现我们不用关心,我们只用知道xxx类的所有信息都保存在clazz里边了),我们这时候就可以知道类中的所有方法和属性,我们可以用clazz对象去创建实例,或者是调用其中的方法(就像上面用String实例创建对象一样,我们仍可以用String实例来调用方法)。

简单的例子:

  例子:

项目结构:
在这里插入图片描述

properties文件(只是用于读取className使用的)

className=com.myClass.Cat

Cat类:

package com.myClass;

public class Cat {
    public String name = "小猫";
    private int age = 0;
    public void eat(){
        System.out.println("小猫吃鱼...");
    }
    public void play(){
        System.out.println("小猫玩耍...");
    }
    public void sleep(){
        System.out.println("小猫睡觉...");
    }
}

reflection类

package com.myClass.reflection;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

public class Reflection {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\properties")); // 加载配置文件,就相当于加载文件,然后放到一个配置类中去

        String classFullPath = properties.get("className").toString();// 获取配置类中的信息
        
        // 反射的使用
        Class clazz = Class.forName(classFullPath);

        Field[] fields = clazz.getFields(); //获取所有的属性
        // 打印输出
        System.out.println("属性有:");
        for(Field f : fields){
            System.out.println(f.getName());
        }

        Method[] methods = clazz.getMethods();// 获取所有方法
        // 打印输出
        System.out.println("方法有:");
        for(Method m : methods){
            System.out.println(m.getName());
        }
    }
}

运行截图:
在这里插入图片描述

这里多出来的方法继承自基类而来。

两种方式比较:

  我们一般创建对象都是都是在未运行时new className();然后再去调用相应的方法。而反射可以做到在未运行时不去创建对象,而在运行的时候去完成这个对象的创建,再去使用相应的方法。下面比较下两种情况:

  未使用反射:

	Cat cat = new Cat();
	cat.eat();

  使用反射:

	Properties properties = new Properties();
    properties.load(new FileInputStream("src\\properties")); // 加载配置文件

	// 获取配置文件信息
    String classFullPath = properties.get("className").toString(); // 获取类名->com.myClass.Cat
    String methodName = properties.get("method").toString(); // 获取调用的方法->eat

	// 下面两步相当于new Cat();
    Class clazz = Class.forName(classFullPath);
    Object obj = clazz.newInstance();
    
    // 下面两步相当于cat.eat();
    Method method = clazz.getMethod(methodName);
    method.invoke(obj);

从上面就可以看见反射的好处,假设我需要改变调用的方法,第一种非反射方式只能改源码,而反射方式能通过修改配置文件就能做到。Reflection类中不需要出现依赖的对象,达到了解耦的效果。

其次:
未用反射时,我们只能在未运行时就创建好对象,等待调用,这样代码就写死了,就死死绑定了我们写的几个类,这就是高耦合
使用反射时,我们要使用的对象并没有出现在Reflection类中,单纯这样看,他们之间没有任何关系(无依赖),这样的话,代码的耦合度就很小,那么代码就会更加灵活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值