您的位置:首页 > 编程语言 > Java开发

Java反射小总结

2015-02-08 01:20 232 查看
Java反射小总结

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

在反射之下,我们平常对Java的好认知都要改变,比如private进行访问控制,泛型可以限制容器内元素的类型等概念都要有所调整。可以说反射是Java语言中的核心特点之一。现在我们所使用的成熟的框架如Spring,Hibernate等等,都是因为大量使用反射才能很好的实现。

利用java的反射,我们可以在不清楚一个类内部情况下动态地分析这个类,并对这个类或其实例进行操作。下面对反射进行分析。

Java反射反射所用到的类,接口和异常都在java.lang.reflect包中,下面是JDK7u65API中各类的说明。



介绍几个常的接口和类:

1, Constructor: 提供了一个构造函数的信息以及访问类的构造函数的接口。

2, Field: 提供一个类的域的信息以及访问类的域的接口。

3, Method: 提供一个类的方法的信息以及访问类的方法的接口。

4, Array: 该类提供动态地生成和访问JAVA数组的方法。

5, AccessibleObject: 该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。

6, Modifie: 提供了 static 方法和常量,对类和成员访问修饰符进行解码。

7, Proxy: 提供动态地生成代理类和类实例的静态方法。(不太明白)。

再讲反射中最重要的一个类Class.

它位于Java.lang包中,其API信息太多,不示切图了,用到哪个说哪个吧!

要想运用反射首先要得到Class对象。老生常谈的问题,得到Class类的三个方法。

1, 调用任何对象的getClass()方法

如Class<?> classType1 = ”HelloWorld!”.getClass();

2, 在类后加.class

如Class<?> classType2 = String.class;

3, 运用Class类的一个静态方法,forName(StringclassName)

如Class<?> classType3 = Class.forName(“java.lang.String”);

在些要说明的一点是,这三种类型,classType1~3是==的,而且是equals的,我们平常使用时,如果要对比两个类型是否是一样的,直接用==,因为相同类型在Java中只有一ww发字节码,用==完全没有问题,且提倡使用==。

4, 还有一种特别的类型,就是基本类型,它们也是有对应的Class的,通过类似于int.class或Integer.TYPE来得到。再有其实void也是有对应的Class的。就是在JAVA中所有的结成部分都有对应的Class。

得到Class后,下面就正式开始运用Class进行一些操作。

获取Fields有两组四个方法:

1, public FieldgetField(String name),返回一个 Field 对象,它反映此 Class对象所表示的类或接口的指定公共成员字段。

2, public Field[] getFields(),返回一个包含某些 Field 对象的数组,这些对象反映此Class 对象所表示的类或接口。

3, public FieldgetDeclaredField(Stringname),返回一个 Field 对象,该对象反映此Class 对象所表示的类或接口的指定已声明字段。

4, public Field[] getDeclaredFields(),返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段

其中的带declaredField的方法可以得到被声明为private的成员,其中Field对象是包装了一个成员的对象。要对私有的成员或方法进行访问的时候要先进行暴力设定为可访问setAccessible(true),之后就可以与public的成员一样进行访问了。

见下面代码:

下面的反射得到Method,得到构造方法都与这个得到成员是类似的,就不去浪费时间叙述,需要的可以去查看API

通过反射建立对象

1, 调用没有参数的构造方法,分两种方法。

a) 在得到所需要的类的Class对象后,通过newInstance()方法来得到新的对象。

b) 得到Class对象后,调用其getConstructor()方法,得到空参数的构造方法对应的对象。再调用构造方法的对象的newInstance()方法来得到所需的对象。

2, 调用有参数的构造方法的newInstance()方法,如:

Constructor<?> constructor = classType.getDeclaredConstructor(int.class,String.class);

Object abc = constructor. newInstance(1, ”123”);

下面代码有说明:

对得到的成员设置值

Field中有setXXX()和getXXX()方法,其中的XXX是指类型,比较简单,看代码;

调用得到的方法

通过Method对象的invoke方法来调用对应的方法:

说明性代码:

<span style="font-size:14px;">package cn.com.taiji.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestReflect {

public static void main(String[] args) throws Exception {
//得到了Class
Class<Arm> clazz = Arm.class;
//得到Field
Field f0 = clazz.getField("i");
Field f1 = clazz.getField("str1");
//		Field f2 = clazz.getField("str2");//运行时抛异常,这个方法不能访问到私有成员
System.out.println(f1);	//public java.lang.String cn.com.taiji.test.Arm.str1
Field f3 = clazz.getDeclaredField("str1");
System.out.println(f3);//public java.lang.String cn.com.taiji.test.Arm.str1
Field f4 = clazz.getDeclaredField("str2");
System.out.println(f4);//public java.lang.String cn.com.taiji.test.Arm.str2
//getFields方法可以得到所有能正常访问到的方法,将其组成一个数组,getDeclaredFields类似
//得到构造方法,
Constructor<Arm> constructor1 = clazz.getConstructor();
Constructor<Arm> constructor2 = clazz.getConstructor(String.class, String.class);
//得到实例
Arm a1 = clazz.newInstance();
Arm a2 = constructor1.newInstance();
Arm a3 = constructor2.newInstance("def", "456");
System.out.println(a1);//str1:abc====str2:123
System.out.println(a2);//str1:abc====str2:123
System.out.println(a3);//str1:def====str2:456

//访问Field,引用类型
System.out.println(f1.get(a1));
f1.set(a1, "cba");
System.out.println(a1.getStr1());
//		System.out.println(f4.get(a1));//报异常,现在不能访问
f4.setAccessible(true);
System.out.println(f4.get(a1));//可以访问
//访问基本类型,两个都可以
System.out.println(f0.get(a1));//返回的是Object类型
System.out.println(f0.getInt(a1));//返回的是int类型

//得到Method,执行方法,不带参数
Method method1 = clazz.getMethod("m1");
System.out.println(method1);//public void cn.com.taiji.test.Arm.m1()
method1.invoke(a1);//m1 run
//带参数的
Method method2 = clazz.getDeclaredMethod("m2", int.class);
System.out.println(method2);//private void cn.com.taiji.test.Arm.m2(int)
//设定访问权限
method2.setAccessible(true);
System.out.println(method2);//private void cn.com.taiji.test.Arm.m2(int)
method2.invoke(a1, 3);//m2 run:3
}
}
class Arm {
public String  str1;
public int i;
private String str2;

public Arm() {
str1 = "abc";
str2 = "123";
i = 11;
}
@Override
public String toString() {
return "str1:" + str1 + "====" + "str2:" + str2;
}

public Arm(String str1, String str2) {
super();
this.str1 = str1;
this.str2 = str2;
}
public void m1() {
System.out.println("m1 run");
}
private void m2(int ss) {
System.out.println("m2 run:" + ss);
}
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: