Java反射机制

原文:Java基础之反射
为了简便,就对原文作一个小总结

反射是框架设计的灵魂

使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)

一、反射的概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
反射就是把java类中的各种成分映射成一个个的Java对象,例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。

二、反射机制的作用

1.反编译:.class–>.java
2.通过反射机制访问java对象的属性,方法,构造方法等;

三、Class对象的由来

Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
在这里插入图片描述
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)
Class 没有公共构造方法。 Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

怎么获取Class对象:

1 Object.getClass();
2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性,通过class属性获取
3 通过Class类的静态方法:forName(String className)(常用)
三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。

四、反射中常用到的Class类的方法

1.构造方法

方法说明
Constructor<?>[] getConstructors()返回所有的公有构造方法
Constructor getConstructor(Class<?>… parameterTypes)按(若干)参数类型返回公有具体构造方法
Constructor<?>[] getDeclaredConstructors()返回所有构造方法
Constructor getDeclaredConstructor(Class<?>… parameterTypes)按(若干)参数类型返回所有具体构造方法

通过Constructor对象创建对象

Object obj=Constructor.newInstance(对应构造器若干参数(实参))后强制转换成对应对象类型即可

注意

当用私有构造方法创建对象时,获取到Constructor后需要调用constructor.setAccessible(true)后才能调用newInstance方法

2.方法

方法说明
Method[] getMethods()返回所有公有方法
Method getMethod(String name, Class<?>… parameterTypes)按照方法名和对应若干参数类型返回具体公有方法
Method[] getDeclaredMethods()返回所有方法
Method getDeclaredMethod(String name, Class<?>… parameterTypes)按照方法名和对应若干参数类型返回具体方法

方法的调用

Object result=method.invoke(反射创建的Object对象,若干参数)后强制转化result为对应返回类型即可

注意

当调用私有方法时,获取到Method后需要调用method.setAccessible(true)后才能调用invoke方法

3.属性

方法说明
Field[] getFields()返回所有公有属性
Field getField(String name)按属性名返回对应公有属性
Field[] getDeclaredFields()返回所有属性
Field getDeclaredField(String name)按属性名返回对应属性

属性的设置

field.set(反射创建的Object对象,值)

注意

当设置私用属性时,获取到Field后需要调用field.setAccessible(true)后才能设置属性值

4、通过反射运行配置文件内容

优点:可以动态配置运行类和属性
可以看到加载类和设置实参和设置属性值都是value,我们可以通过Properties类加载配置文件来动态加载类对象信息

方法说明
load(FileReader in)加载配置文件
getProperty(String key)通过key获取属性值
put(String key,Object value)添加属性
store(FileOutputStream out,null)将属性保存到文件中
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
 
/*
 * 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改
 * 我们只需要将新类发送给客户端,并修改配置文件即可
 */
public class Demo {
	public static void main(String[] args) throws Exception {
		//通过反射获取Class对象
		Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"
		//2获取show()方法
		Method m = stuClass.getMethod(getValue("methodName"));//show
		//3.调用show()方法
		m.invoke(stuClass.getConstructor().newInstance());
		
	}
	
	//此方法接收一个key,在配置文件中获取相应的value
	public static String getValue(String key) throws IOException{
		Properties pro = new Properties();//获取配置文件的对象
		FileReader in = new FileReader("pro.txt");//获取输入流
		pro.load(in);//将流加载到配置文件对象中
		in.close();
		return pro.getProperty(key);//返回根据key获取的value值
	}
}

5、通过反射越过泛型检查

泛型用在编译期(泛型的错误全来自编译错误,泛型集合不协变),先检查后编译再泛型擦除(消失掉,回到原始类)。所以是代码运行时可以通过反射越过泛型检查的

import java.lang.reflect.Method;
import java.util.ArrayList; 
/* * 通过反射越过泛型检查 *  
* 例如:有一个String泛型的集合,怎样能向这个集合中加一个Integer类型的值? */
public class Demo {   
    public static void main(String[] args)throws Exception{  
        ArrayList<String> strList = new ArrayList<>();  
        strList.add("aaa");  
        strList.add("bbb");   
        // strList.add(100);  //获取ArrayList的Class对象,反向的调用add()方法,添加数据  
        Class listClass = strList.getClass(); 
        //得到 strList 对象的字节码 对象  
        //获取add()方法  
        Method m = listClass.getMethod("add", Object.class);  
        //调用add()方法  
        m.invoke(strList, 100);    
        //遍历集合  
        for(Object obj : strList){   
        System.out.println(obj);  
        } 
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值