黑马程序员—JAVA高新技术_反射

反射概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射其实就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员。就是把JAVA类中的各种成分反射成为相应的JAVA类
简单说:反射就是把Java类中的各种成分映射成相应的java类

反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象。
2、实例化对象,获得类的属性、方法或构造函数。
3、访问属性、调用方法、调用构造函数创建对象。

Class类

得到类的字节码文件相同,有三种方式:
类名.class,例如:System.class
对象.getClass(),例如:new Date().getClass()
Class.forName("类名"),例如:Class.forName("java.util.Date");

9个预定义的Class实例对象:8种基本数据类型加上void 

判断:class.isPrimitive();
Integer.class包装类的字节码
Integer.TYPE Integer中基本类型的字节码
int.class==Integer.TYPE
数组:class.isArray();
只要在源程序中出现的类型,都有各自的Class实例对象,例如 int[] void 等等

Constructor类

Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class); //获得方法时要用到类型
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc")); //调用获得的方法时要用到上面相同类型的实例对象
Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

Field类

ReflectPoint类的定义

public class ReflectPoint {
	private int x;
	public int y;	
	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
} 

问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,哪关联的是哪个对象呢?所以字段fieldX 代表的是x的定义,而不是具体的x变量。
对该类进行反射:
ReflectPoint  pt1=new ReflectPoint(3,5);
Filed filedy=pt1.getclsss().getFiled("Y");//只代表哪个对象
Filed filedy=pt1.getclsss().getDeclaredField("x")//获取对象不管是私有还是被保护的
filedy.setAccessible(true);//设置可以访问,暴力反射
filedy.get(pt1)//取出Y的值

示例代码:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"

private static void changeStringValue(Object obj) throws Exception {
		Field[] fields = obj.getClass().getFields();
		for(Field field : fields){
			if(field.getType() == String.class){
				String oldValue = (String)field.get(obj);
				String newValue = oldValue.replace('b', 'a');
				field.set(obj, newValue);
			}
		}		
	}

Method类

Method类代表某个类中的一个成员方法
得到类中的某一个方法:Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
通常方式:System.out.println(str.charAt(1));
反射方式: System.out.println(charAt.invoke(str, 1));
如果传递给Method对象的invoke()方法的第一个参数为null的话说明该Method对象对应的是一个静态方法。

一个同名的方法有多个重载形式,要根据参数的个数和类型得到重载方法中的某一个方法,例如,Class.getMethod(name,Class... args)中的args参数就代表所要获取的那个方法的各个参数的类型的列表。

数组的反射

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
示例代码:利用反射遍历数组

	private static void printObject(Object obj) {
		Class clazz = obj.getClass();
		if(clazz.isArray()){
			int len = Array.getLength(obj);
			for(int i=0;i<len;i++){
				System.out.println(Array.get(obj, i));
			}
		}else{
			System.out.println(obj);
		}		
	}


反射的作用大大的增强了程序的扩展性,实现框架功能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值