栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA反射机制

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA反射机制

类对象概念: 所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。

类对象,就是用于描述这种类,都有什么属性,什么方法的

获取类对象

获取类对象有3种方式
1. Class.forName(实例化对象)
2. 类.class
3. new 类().getClass()
在一个JVM中,一种类,只会有一个类对象存在。所以以上三种方式取出来的类对象,都是一样的。

package com.relect;

public class Test {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		String className = "charactor.Test";
try {
	Class  p1=Class.forName(className);
	Class p2=Test.class;
	Class p3=new Test().getClass();
}catch(Exception e) {
	e.printStackTrace();
}
	}

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

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

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

//构造器
Constructor c= pClass.getConstructor();
//通过构造器实例化
Hero h2= (Hero) c.newInstance();

通过反射修改属性的值
//使用传统方式修改name的值为garen
        h.name = "garen"
            //获取类Hero的名字叫做name的字段
            Field f1= h.getClass().getDeclaredField("name");
            //修改这个字段的值
            f1.set(h, "teemo");

getField和getDeclaredField的区别
这两个方法都是用于获取字段
getField 只能获取public的,包括从父类继承来的字段。
getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。

通过配置文件创建对象并设置字段值
public class end {
 
    public static void main(String[] args) {
 
        File file = new File("C:/Users/Administrator/Desktop/hero.config");
 
        try (FileReader fr = new FileReader(file)) {
            String classname = null;
            char[] all = new char[(int) file.length()];
            fr.read(all);
            String cs = null;
            cs = new String(all);
            String[] sc = cs.split("rn");
 
            String classname1 = sc[0];
            String classname2 = sc[1];
            String name1 = sc[2];
            String name2 = sc[3];
            int HP1 = Integer.parseInt(sc[4]);
            int HP2 = Integer.parseInt(sc[5]);
            int damage1 = Integer.parseInt(sc[6]);
            int damage2 = Integer.parseInt(sc[7]);
//
 
            Class c = Class.forName(classname1);
            Constructor con = c.getConstructor();
            Object h = con.newInstance();
            Field H = h.getClass().getField("HP");
            H.set(h, HP1);
            Field n = h.getClass().getField("name");
            n.set(h, name1);
            Field d = h.getClass().getField("damage");
            d.set(h, damage1);
 
            Class c1 = Class.forName(classname2);
            Constructor con1 = c1.getConstructor();
            Object h1 = con1.newInstance();
            Field H1 = h1.getClass().getField("HP");
            H1.set(h1, HP2);
            Field n1 = h1.getClass().getField("name");
            n1.set(h1, name2);
            Field d1 = h1.getClass().getField("damage");
            d1.set(h1, damage2);
 
            Method attackHeroMethod = c.getMethod("attackHero", Hero.class);
            attackHeroMethod.invoke(h, h1);
            }catch (Exception e){
            e.printStackTrace();
 
        }
    }
 
 }
反射有什么用

首先准备两个业务类,这两个业务类很简单,就是各自都有一个业务方法,分别打印不同的字符串

public class Service1 {
 
    public void doService1(){
        System.out.println("业务方法1");
    }
}
 
public class Service2 {
 
    public void doService2(){
        System.out.println("业务方法2");
    }
}

当需要从第一个业务方法切换到第二个业务方法的时候,使用非反射方式,必须修改代码,并且重新编译运行,才可以达到效果

public class Test {
 
    public static void main(String[] args) {
//      new Service1().doService1();
        new Service2().doService2();
    }
}
反射可以简化这个过程

使用反射方式,首先准备一个配置文件,就叫做spring.txt吧, 放在src目录下。 里面存放的是类的名称,和要调用的方法名。
在测试类Test中,首先取出类名称和方法名,然后通过反射去调用这个方法。
当需要从调用第一个业务方法,切换到调用第二个业务方法的时候,不需要修改一行代码,也不需要重新编译,只需要修改配置文件spring.txt,再运行即可。
这也是Spring框架的最基本的原理,只是它做的更丰富,安全,健壮。
基本原理:取出配置文件的类名称和方法名,通过反射调用这个方法,这样就不需要修改代码

package com.relect;

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

public class Test {

	public static void main(String[] args) throws Exception, IOException {
		// TODO 自动生成的方法存根
		File SpringConfig=new File("D:\eclipse\eclipse-workspace\反射\src\com\relect\spring.txt");
		Properties spring=new Properties();
		spring.load(new FileInputStream(SpringConfig));
		String className = (String) spring.get("class");
        String methodName = (String)spring.get("method");
        //根据类名称获取类对象
        Class clazz = Class.forName(className);
        //根据方法名称,获取方法对象
        Method m = clazz.getMethod(methodName);
      //获取构造器
        Constructor c = clazz.getConstructor();
        //根据构造器,实例化出对象
        Object service = c.newInstance();
        //调用对象的指定方法
        m.invoke(service);
		
	}

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/358102.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号