Java-反射

Java-反射

1. 概念
  1. 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接
     
  2. 在程序运行期间,系统始终为所有对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时的类型信息选择相应的方法执行。保存这些信息的类成为 Class
     
  3. java代码运行的阶段
    1. source源代码阶段: .java -> .class字节码文件
    2. Class类对象阶段: .class字节码文件被类加载器加载进内存,并将其封装成class对象(用于在内存中描述字节码文件),class对象将原字节码文件中的成员变量抽取等装成数组Field[],将原字节码文件的构造函数封装成数组Construction[],将成员变量封装成Method[]。当然Class类不止这三个,还封装了很多,常用的是以上这三个。
    3. RunTime运行阶段,创建对象的过程new
      avator
  4. 加载的时候: Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
  5. 如图是类的正常加载过程:反射的原理在于class对象。
    avator
2. 反射作用
  • 反编译 .class -> .java
  • 通过反射机制访问Java对象的属性,方法,构造方法等
  • 实现通用的数组操作代码
  • 利用Method对象,这个对象很像C++的函数指针
3. 反射机制中的类
java.lang.Class;                
java.lang.reflect.Constructor; java.lang.reflect.Field;        
java.lang.reflect.Method;
java.lang.reflect.Modifier;
4. 具体实现
  1. 反射机制获取类有三种方法,我们来获取Employee类型
//第一种方式: 源代码阶段 
Classc1 = Class.forName("Employee");

//第二种方式: class类对象阶段
//java中每个类型都有class 属性.
Classc2 = Employee.class;
 
//第三种方式:RunTime运行阶段
//java语言中任何一个java对象都有getClass 方法
Employeee = new Employee();
Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
  1. 创建对象:获取类以后我们来创建它的对象,利用newInstance
Class c =Class.forName("Employee");
 
//创建此Class 对象所表示的类的一个新实例
Objecto = c.newInstance(); //调用了Employee的无参数构造方法.
  1. 获取属性: 分 所有属性和特定属性

    获取所有属性

//获取整个类
Class c = Class.forName("java.lang.Integer");
//获取所有的属性?
Field[] fs = c.getDeclaredFields();
//定义可变长的字符串,用来存储属性
StringBuffer sb = new StringBuffer();
//通过追加的方法,将每个属性拼接到此字符串中
//最外边的public定义
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");
//里边的每一个属性
for(Field field:fs){
	sb.append("\t");//空格
	sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
	sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字
	sb.append(field.getName()+";\n");//属性的名字+回车
}
	
sb.append("}");
	
System.out.println(sb);

获取特定方法

public static void main(String[] args) throws Exception{
			
	//以前的方式:
	/*
	User u = new User();
	u.age = 12; //set
	System.out.println(u.age); //get
	*/
			
	//获取类
	Class c = Class.forName("User");
	//获取id属性
	Field idF = c.getDeclaredField("id");
	//实例化这个类赋给o
	Object o = c.newInstance();
	//打破封装
	idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
	//给o对象的id属性赋值"110"
	idF.set(o, "110"); //set
	//get
	System.out.println(idF.get(o));
}
5. 好处
  1. 对于封装好的框架来说,直接拿来用就可以,不用修改框架内的代码。但如果我们使用的是传统的new形式来实例化,那么当类名更改的时候,我们就要修改java代码,还有重新测试,编译等。如果仅修改配置文件就简单的多。

  2. 反射还能解耦,假设我们使用的是new这种形式进行对象的实例化,此时如果在项目的某一个小模块中我们的一个实例类丢失了,那么在编译期间就会报错,以导致整个项目无法启动。而对于反射创建对象Class.forName(“全类名”);这种形式,我们在编译期需要的仅仅只是一个字符串(全类名),在编译期不会报错,这样其他的模块就可以正常的运行,而不会因为一个模块的问题导致整个项目崩溃。这就是Spring框架中IOC控制反转的本质。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值