黑马程序员---反射机制浅析

本文详细介绍了Java反射机制的基本概念,包括如何获取类的构造方法、成员变量和方法,以及如何使用反射进行动态调用和修改。通过实例演示了反射在实际编程中的应用,强调了在使用反射时需权衡性能与可读性的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  ------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------


           其实听课的内容中暂时未涉及到反射内容,但是张孝祥老师讲课的速度比较快,我没跟上,就吸收了不到30%,不是老师不好,是我底子比较差,javabean、内省、反射、然后一大堆代码,我就犯蒙了。然后在网上搜这方面的资料学习,看来看去,内省机制是反射原理在javabean上的一种缺省的处理方法。javabean似乎比内省简单的,而内省只是反射的一种不算很全面的一种应用,所以,我就暂时停止听课了,因为我有点听不懂了,得先把javabean,内省,反射搞懂,再继续前行。嗯!就啃反射了,上网查资料。从最基本的概念开始。以下是我对网上检索到的关于“反射”资料的整理笔记,通过多方的摘录,参考,整合。希望大家参阅时能批评指正我的错误,我虚心接受。大家共同探讨,沟通,学习,共同进步,嘿嘿。

        在Java运行时环境中 反射机制允许程序透过ReflectionAPIs取得任何一个已知名称class的内部信息,包括其modifiers(诸如public,static 等等)、superclass(例如Object)、实现之interfaces(例如Serializable),也包括fieldsmethods的所有信息,并可于运行时改变fields内容或调用methods ,这种动态获取类的信息以及动态调用对象的方法的功能便是对Java 语言的“反射”基本概念的概述。简单点说:就是让你可以通过名称来得到或修改对象(类,属性,方法,构造函数等)的各种信息的技术。

        在JDK中,主要借助于 4 个类: class , Constructor , Field , Method 来实现Java反射机制,这些类都位于java.lang.reflect包中,它们是:
Class类:代表一个类。
Field 类:代表类的成员变量(成员变量也称为类的属性)。
Method类:代表类的方法。

–Constructor 类:代表类的构造方法。

一、获取类的构造方法的Constructor对象(数组)

1、Constructer[] getDeclaredConstructors();返回已加载类声明的所有的构造方法的Constructor对象数组。

2、Constructer getDeclaredConstructor(Class[] param Types);返回已加载类声明的指定的构造方法的Constructor对象,param Types指定了类型参数。

3、Constructer[] getConstructors();返回已加载类声明的所有的public类型的构造方法的Constructor对象数组。

4、Constructer getConstructor(Class[] param Types);返回已加载类声明的指定的public类型的构造方法Constructor对象,param Types指定了类型参数。

如果某个类中没有定义构造方法 ,第一个和第三个方法返回的数组中只有一个元素 ,就是缺省的构造方法 ;如果某个类中只定义了有参数的构造函数 ,而没有定义缺省构造函数 ,第一个和第三个方法返回的数组中不包含缺省的构造方法 。

例子:

import java.lang.reflect.*;
public class DumpMethods
 {
	public static void main(String[ ] args) 
	{
		try
		{
			if(args.length<1)
			{
				System.out.println(" 请输入完整的类名: ");
				return;
			}
			Class strClass=Class.forName(args[0]);
			// 检索带有指定参数的构造方法
			Class[] strArgsClass=new Class[]{ byte[].class,String.class};
			Constructor constructor=strClass.getConstructor(strArgsClass);
			System.out.println("Constructor:"+constructor.toString());
			// 调用带有参数的构造方法创建实例对象 object
			byte[] bytes="java 就业培训 ".getBytes();
			Object[] strArgs=new Object[]{bytes,"gb2312"};
			Object object=constructor.newInstance(strArgs);
			System.out.println("Object"+object.toString());
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}

二、获取类成员变量的Field对象(数组)

1、Field [] getDclaredFields();返回已加载声明的所有成员变量的Field对象数组,不包括从父类继承的成员变量。

2、Field getDeclaredFields(String name);返回已加载声明的指定的成员变量的Field对象,不包括从父类继承的成员变量,参数name指定成员变量的名称。

3、Field [] getFields();返回已加载声明的所有pblic型的成员变量的Field对象数组,包括从父类继承的成员变量。

4、Field getField(String name);返回已声明加载的指定的public型的成员变量的Fied对象,包括从父类继承的成员变量,name指定成员变量的名称。

例子:

import java.lang.reflect.*;
public class ReflectTest 
{
	private String name;
	private String age;
	public ReflectTest(String name,String age)
	{
	this.name=name;
	this.age=age;
	}
	public static void main(String[ ] args) 
	{
		// TODO 自动生成方法存根
		try
		{
			ReflectTest rt=new ReflectTest("zhanghandong","shiba");
			fun(rt);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	public static void fun(Object obj) throws Exception
	{
		Field[] fields=obj.getClass().getDeclaredFields();
		System.out.println(" 替换之前的 :");
		for(Field field:fields)
		{
			System.out.println(field.getName()+"="+field.get(obj));
			if(field.getType().equals(java.lang.String.class))
			{
				field.setAccessible(true);
				// 必须设置为 true 才可以修改成员变量
				String org=(String)field.get(obj);
				field.set(obj,org.replaceAll("a","b"));
			}
		}
		System.out.println(" 替换之后的: ");
		for(Field field:fields)
		{
			System.out.println(field.getName()+"="+field.get(obj));
		}
	}
}

三、获取类的方法的Method对象(数组)

1、Method[] getDeclaredMethods();返回已加载声明的所有方法的Method对象数组,不包括从父类继承的方法。

2、Method getDeclaredMethd(String name,Class[] param Types);返回已加载声明的所有方法的Method对象,不包括从父类继承的方法,参数name指定方法的名称,参数paraTypes指定方法的参数类型。

3、Method [] getMethods();返回已加载声明的所有public型的方法的Method对象,包括从父类继承的方法。

4、Method getMethos(String name,Class[] paraTypes);返回已加载声明的public型的方法的Method对象,包括从父类继承的Method对象,名称name指定方法名,paraTypes指定方法的参数类型。

四、获取类的构造函数的Constructor对象(数组)


1、Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数。
2、Constructor[] getConstructors() -- 获得类的所有公共构造函数。
3、Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数 ( 与接入级别无关 )。
4、Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数 ( 与接入级别无关 ) 。

 

 

检索类的其他信息:

 int getModifiers(): 返回已加载类的修饰符的整形标识值 。
 Package getPackage(): 返回已加载类的包名。
 Class getSuperclass(): 返回已加载类的父类的 Class 实例 。
Class [] getInter faces(): 返回已加载类实现的接口的 Class 对象数组 。
boolean isInterface(): 返回已加载类是否是接口 。

 

总结:

        Java 语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的 对象 ( 根据安全性限制 ) ,无需提前硬编码目标类。这些特性使得反射 特别适用于创建以非常普通的方式与对象协作的库。例如,反射经常在持续存储对象为数据库、 XML 或其它外部格式的框架中使用。 Java reflection 非常有用,它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息。 Java 的这一特性非常强大,并且是其它一些常用语言,如 C 、 C++ 、 Fortran 或者 Pascal 等都不具备的。但反射有两个缺点。第一个是性能问题。用于字段和方法接入时反射要远慢于直接代码。 性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相 对很少涉及的部分,缓慢的性能将不会是一个问题。即使测试中最坏情况下的计时图显示的反射操作只耗 用几微秒。仅反射在性能关键的应用的核心逻辑中使用时性 能问题才变得至关重要。许多应用中更严重的一个缺点是使用反射会模糊程序内部实际要发生的事情。程序人员希 望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问 题。反射代码比相应的直接代码更复杂,正如性能比较的代码实例中看到的一样。解决这些问题的最佳方案 是保守地使用反射 —— 仅在它可以真正增加灵活性的地方 —— 记录其在目标类中的使用。


import java.lang.reflect.*;
public class ReflectTest {
private String name;
private String age;
public ReflectTest(String name,String age){
this.name=name;
this.age=age;
}
public static void main(String[ ] args) {
// TODO 自动生成方法存根
try{
ReflectTest rt=new ReflectTest("zhanghandong","shiba");
fun(rt);
}catch(Exception e){
e.printStackTrace();
}
}
public static void fun(Object obj) throws Exception{
Field[] fields=obj.getClass().getDeclaredFields();
System.out.println(" 替换之前的 :");
for(Field field:fields){
System.out.println(field.getName()+"="+field.get(obj));
if(field.getType().equals(java.lang.String.class)){
field.setAccessible(true);
// 必须设置为 true 才可以修改成员变量
String org=(String)field.get(obj);
field.set(obj,org.replaceAll("a","b"));
}
}
System.out.println(" 替换之后的: ");
for(Field field:fields){
System.out.println(field.getName()+"="+field.get(obj));
}
}
}


● Field[] getDeclaredFields(): 返回已加载类声明的所有成员变量的 Field 对象 数
组 , 不包括从父类继承的成员变量 .
● Field getDeclaredField(String name): 返回已加载类声明的所有成员变量的
Field 对象 , 不包括从父类继承的成员变量 , 参数 name 指定成员变量的名称 .
● Field[] getFields(): 返回已加载类声明的所有 public 型的成员变量的 Field 对 象
数组 , 包括从父类继承的成员变量● Field[] getDeclaredFields(): 返回已加载类声明的所有成员变量的 Field 对象 数
组 , 不包括从父类继承的成员变量 .
● Field getDeclaredField(String name): 返回已加载类声明的所有成员变量的
Field 对象 , 不包括从父类继承的成员变量 , 参数 name 指定成员变量的名称 .
● Field[] getFields(): 返回已加载类声明的所有 public 型的成员变量的 Field 对 象
数组 , 包括从父类继承的成员变量● Field[] getDeclaredFields(): 返回已加载类声明的所有成员变量的 Field 对象 数
组 , 不包括从父类继承的成员变量 .
● Field getDeclaredField(String name): 返回已加载类声明的所有成员变量的
Field 对象 , 不包括从父类继承的成员变量 , 参数 name 指定成员变量的名称 .
● Field[] getFields(): 返回已加载类声明的所有 public 型的成员变量的 Field 对 象
数组 , 包括从父类继承的成员变量● Field[] getDeclaredFields(): 返回已加载类声明的所有成员变量的 Field 对象 数
组 , 不包括从父类继承的成员变量 .
● Field getDeclaredField(String name): 返回已加载类声明的所有成员变量的
Field 对象 , 不包括从父类继承的成员变量 , 参数 name 指定成员变量的名称 .
● Field[] getFields(): 返回已加载类声明的所有 public 型的成员变量的 Field 对 象
数组 , 包括从父类继承的成员变量二 二 二 二 . . . . 获取类成员变量的 获取类成员变量的 获取类成员变量的 获取类成员变量的 Field Field Field Field 对象对象对象对象 ( ( ( ( 数组数组数组数组 ) ) ) )二 二 二 二 . . . . 获取类成员变量的 获取类成员变量的 获取类成员变量的 获取类成员变量的 Field Field Field Field 对象对象对象对象 ( ( ( ( 数组数组数组数组 ) ) ) )


一 . 获取类的构造方法的 Constructor 对象 ( 数组 )
● Constructor[ ] getDeclaredConstructors(); 返回已加载类声明的所有的构造方
法的 Constructor 对象数组 .
● Constructor getDeclaredConstructor(Class[] paramTypes); 返回已加载类声
明的指定构造方法的 Constructor 对象 ,paramTypes 指定了参数类型 .
● Constructor[ ] getConstructors(); 返回已加载类声明的所有的 public 类型的构
造方法的 Constructor 对象数组 .一 . 获取类的构造方法的 Constructor 对象 ( 数组 )
● Constructor[ ] getDeclaredConstructors(); 返回已加载类声明的所有的构造方
法的 Constructor 对象数组 .
● Constructor getDeclaredConstructor(Class[] paramTypes); 返回已加载类声
明的指定构造方法的 Constructor 对象 ,paramTypes 指定了参数类型 .
● Constructor[ ] getConstructors(); 返回已加载类声明的所有的 public 类型的构
造方法的 Constructor 对象数组 .一 . 获取类的构造方法的 Constructor 对象 ( 数组 )
● Constructor[ ] getDeclaredConstructors(); 返回已加载类声明的所有的构造方
法的 Constructor 对象数组 .
● Constructor getDeclaredConstructor(Class[] paramTypes); 返回已加载类声
明的指定构造方法的 Constructor 对象 ,paramTypes 指定了参数类型 .
● Constructor[ ] getConstructors(); 返回已加载类声明的所有的 public 类型的构
造方法的 Constructor 对象数组 .一 . 获取类的构造方法的 Constructor 对象 ( 数组 )
● Constructor[ ] getDeclaredConstructors(); 返回已加载类声明的所有的构造方
法的 Constructor 对象数组 .
● Constructor getDeclaredConstructor(Class[] paramTypes); 返回已加载类声
明的指定构造方法的 Constructor 对象 ,paramTypes 指定了参数类型 .
● Constructor[ ] getConstructors(); 返回已加载类声明的所有的 public 类型的构
造方法的 Constructor 对象数组 .一 . 获取类的构造方法的 Constructor 对象 ( 数组 )
● Constructor[ ] getDeclaredConstructors(); 返回已加载类声明的所有的构造方
法的 Constructor 对象数组 .
● Constructor getDeclaredConstructor(Class[] paramTypes); 返回已加载类声
明的指定构造方法的 Constructor 对象 ,paramTypes 指定了参数类型 .
● Constructor[ ] getConstructors(); 返回已加载类声明的所有的 public 类型的构
造方法的 Constructor 对象数组 .一 . 获取类的构造方法的 Constructor 对象 ( 数组 )
● Constructor[ ] getDeclaredConstructors(); 返回已加载类声明的所有的构造方
法的 Constructor 对象数组 .
● Constructor getDeclaredConstructor(Class[] paramTypes); 返回已加载类声
明的指定构造方法的 Constructor 对象 ,paramTypes 指定了参数类型 .
● Constructor[ ] getConstructors(); 返回已加载类声明的所有的 public 类型的构
造方法的 Constructor 对象数组 .一 . 获取类的构造方法的 Constructor 对象 ( 数组 )
● Constructor[ ] getDeclaredConstructors(); 返回已加载类声明的所有的构造方
法的 Constructor 对象数组 .
● Constructor getDeclaredConstructor(Class[] paramTypes); 返回已加载类声
明的指定构造方法的 Constructor 对象 ,paramTypes 指定了参数类型 .
● Constructor[ ] getConstructors(); 返回已加载类声明的所有的 public 类型的构
造方法的 Constructor 对象数组 .

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值