java--反射机制

反射

反射库提供了一个丰富且精巧的工具集,可以用来编写能动态操纵java代码的程序。
能够分析类能力的程序称为反射

Class类

在程序运行期间,java运行时系统始终为所有对象维护一个运行时类型标识。
这个信息会跟踪每个对象所属的类。
虚拟机利用运行时类型信息选择要执行的正确的方法。

Class对象会描述一个特定类的属性。
虚拟机为每个类型管理一个唯一的Class对象。

异常

如果一个方法包含一条可能抛出检查型异常的语句,则在方法名上增加一个throws子句。
public static void doSomethingWithClass(String name)
	throws ReflectiveOperationException
{
	Class c1 = Class.forName(name);
	do something with c1
}
只需要为检查型异常提供一个throws子句,很容器找出哪些方法会抛出检查型异常。
只要你调用了一个可能抛出检查型异常的方法而没有提供相应的异常处理器,编译器就会报错。

资源

类通常有一些关联的数据文件,如:
图像和声音文件
包含消息字符串和按钮标签的文本文件
java中,这些关联的文件被称为资源。

Class类提供了一个很有用的服务可以查找资源文件。下面给出必要步骤:
1.获得拥有资源的类的Class对象。
如ResourceTest.class
2.有些方法,如ImageIcon类的getImage方法,接受描述资源位置的URL。则要调用
URL url = c1.getResource("about.gif");
3.否则,使用getResourceAsStream方法得到一个输入流来读取文件中的数据。

java虚拟机知道如何查找一个类,所以它能搜索相同位置上的关联资源。
如,假设类ResourceTest在一个resources包中。ResourceTest.class文件就位于resources目录中,
可以把一个图标文件放在同一目录下。
除了可以将资源文件与类文件放在同一目录中,还可提供一个相对或绝对路径。
如:data/about.txt或/corejava/title.txt。
文件的自动装载是利用资源加载特性完成的。没有标准的方法来解释资源文件的内容。
每个程序必须有自己的方法来解释它的资源文件。
另一个经常使用资源的地方是程序的国际化
// 编译,构建一个JAR文件并执行
javac resource/ResourceTest.java
jar cvfe ResourceTest.jar resource.ResourceTest \
	resources/*.class resource/*.gif resources/data/*.txt corejava/*.txt
java -jar ResourceTest.jar

利用反射分析类的能力

在java.lang.reflect包中有三个类Field,Method和Constructor分别用于描述类的字段,方法和构造器。
java.lang.reflect包中Modifier用于分析修饰符。

利用反射编写泛型数组代码

package arrays;
import java.lang.reflect.*;
import java.util.*;
public class CopyOfTest
{
	public static void main(String[] args)
	{
		int[] a = {1, 2, 3};
		a = (int[])goodCopyOf(a, 10);
		System.out.println(Arrays.toString(a));
	
		String[] b = {"Tom", "Dick", "Harry"};
		b = (String[])goodCopyOf(b, 10);
		System.out.println(Arrays.toString(b));
		
		System.out.println("The following call with generate an exception.");
		b = (String[])badCopyOf(b, 10);
	}
	
	public static Object[] badCopyOf(Object[] a, int newLength)
	{
		var newArray = new Object[newLength];
		System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
		return newArray;
	}

	public static Object goodCopyOf(Object a, int newLength)
	{
		Class c1 = a.getClass();
		if(!c1.isArray()) return null;
		Class componentType = c1.getComponentType();
		int length = Array.getLength(a);
		Object newArray = Array.newInstance(componentType, newLength);
		System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
		return newArray;
	}
}

调用任意方法和构造器

Method类的invoke允许触发一次方法调用。
如方法返回类型是基本类型,invoke方法会返回其包装器类型。
Method m1 = Employee.class.getMethod("getName");
Mathod m2 = Employee.class.getMethod("raiseSalary", double.class);
Class c1 = Random.class;
Constructor cons = c1.getConstructor(long.class);
Object obj = cons.newInstance(42L);
如在调用方法的时候提供了错误的参数,invoke方法会抛出一个异常。
invoke的参数和返回值必须是Object类型,这意味着必须来回进行多次强制类型转换。
使用反射获得方法指针的代码比直接调用方法的代码慢的多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值