反射

反射概念

由下图可知,java的类经过javac编译成.class文件再通过类加载器进行加载成类对象,最后再创建对象。
···反射:将类的各个组成部分封装为其他对象,这就是反射机制。
···好处:1、可以在程序运行过程中,操作这些对象。
2、可以解耦,提高程序可扩展性。

在这里插入图片描述

Class对象功能

一个类无非就是由成员变量、构造方法、成员方法组成,故class的获取功能由下图所示:
在这里插入图片描述

获取类对象

获取类对象有3种方式

  1. Class c= Class.forName
  2. Class c = Hero.class 【即类名.Class】
  3. Class c = new.Hero().getClass() 【即对象.getClass】

获取类对象的时候,会导致类属性被初始化
无论什么途径获取类对象,都会导致静态属性被初始化,而且只会执行一次。(除了直接使用 Class c = Hero.class 这种方式,这种方式不会导致静态属性被初始化)。

static String copyright;
static {
    System.out.println("初始化 copyright");
    copyright = "版权由Riot Games公司所有";
}

创建对象

通过反射机制创建一个对象

import java.lang.reflect.Constructor;
import charactor.Hero;
public class TestReflection {
  
    public static void main(String[] args) {
        //传统的使用new的方式创建对象
        Hero h1 =new Hero();
        h1.name = "teemo";
        System.out.println(h1);
          
        try {
            //使用反射的方式创建对象
            String className = "charactor.Hero";
            //类对象
            Class pClass=Class.forName(className);
            //构造器
            Constructor c= pClass.getConstructor();
            //通过构造器实例化
            Hero h2= (Hero) c.newInstance();
            h2.name="gareen";
            System.out.println(h2);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

访问属性

**对于private修饰的成员,需要使用setAccessible(true)才能访问和修改。**也成为暴力反射,忽略权限修饰符的安全检查。

getField和getDeclaredField的区别

这两个方法都是用于获取字段。
getField 只能获取public的,包括从父类继承来的字段。
getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))

下面是反射的例子:
spring.txt

class=reflection.Service1
method=doService1

text.java

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
 public class Test {
     @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {
 
        //从spring.txt中获取类名称和方法名称
        File springConfigFile = new File("e:\\project\\j2se\\src\\spring.txt");
        Properties springConfig= new Properties();
        springConfig.load(new FileInputStream(springConfigFile));
        String className = (String) springConfig.get("class");
        String methodName = (String) springConfig.get("method");
         
        //根据类名称获取类对象
        Class clazz = Class.forName(className);
        //根据方法名称,获取方法对象
        Method m = clazz.getMethod(methodName);
        //获取构造器
        Constructor c = clazz.getConstructor();
        //根据构造器,实例化出对象
        Object service = c.newInstance();
        //调用对象的指定方法
        m.invoke(service);    
    }
}
创建对象:

创建对象使用的方法:
newInstance(): 用来实例化对象的,与new()的主要区别是,newInstance()的使用有局限,因为它生成对象只能调用无参的构造函数,而使用new关键字生成对象没有这个限制。

调用对象:

invoke(): 用来调用对象指定的方法。

反射的妙用

使用前提:
已经创建了一个Person类和一个student类,并且创建了一个pro.properties配置文件。
使用步骤:
1.加载配置文件
1.1创建Properties对象

Properties pro = new Properties;

1.2加载配置文件,转换为一个集合
1.2.1获取class目录下的配置文件

ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream(name:"pro.properties");

Classloader是类加载器。

2.获取配置文件中定义的数据

String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");

3.加载该类进内存

Class cls = Class.forName(className);

4.创建对象

Object obj = cls.newInstance();

5.获取方法对象

Method method = cls.getMethod(methodName);

这时候如果你想要的该代码只需要更改配置文件,pro.properties进行修改,就可以在不改动源码的情况下,对其进行修改,大大的增加了程序的可扩展性,并且在日后程序系统增大的时候,更为方便修改!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值