------- android培训、java培训、期待与您交流! ----------
使java具备了动态性,可以在运行时构造任意一个类的对象,可以在运行时获取任意类的任意成员,并修改其成员变量或者调用其方法。写程序时(比如框架)无法知道将来要被调用的类名,所以,无法new对象。所以,反射机制解决了框架要解决的核心问题。反射就是把java类中的各个成分映射成相应的java类。比如:成员变量映射到Field类。
2.反射机制的主要成员类
Class类: 位于java.lang包中,Class类的实例对象是某个类的字节码。
以下类均位于java.lang.reflect包中:
Field 类:代表类的成员变量。该类提供一系列方法操作成员变量 Method类:代表类的方法。提供invoke方法,用以调用方法。
Constructor 类:Constructor 提供关于类的单个构造方法的信息以及对它的访问权限
Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。
3.反射机制中主要的成员类关系图
4.获取Class对象方式
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该Class
对象。基本的 Java 类型(boolean
、byte
、char
、short
、int
、long
、float
和double
)和关键字 void
也表示为 Class
对象。
三种获取Class对象的方式:
1.通过Object类的getClass()方法。例如:
Class c1 = new String("").getClass();
2.通过Class类的静态方法——forName()来实现:
Class c2 = Class.forName("java.lang.String");
3.类名.class
Class c3 = String.class;
5.使用反射的综合代码示例:
package com.itheima;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 对于反射的演示。获取类的字节码,并获得其中的成员变量,构造方法以及成员函数。
* 此处以String类为例。
* @author wu
*/
public class ReflectTest
{
/**
* @param args
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws SecurityException
* @throws NoSuchMethodException
*/
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException
{
//获取String的字节码的三种方式
Class clazz1 = String.class;
Class clazz2 = Class.forName("java.lang.String");
Class clazz3 = new String("abc").getClass();
//反射方式获取类中的成员变量
Field[] fields = clazz1.getDeclaredFields();
System.out.println("---------成员变量列表---------");
for (Field field : fields)
{
//打印反射获取到的String类中成员变量
System.out.println(field);
}
//反射方式获取类中构造方法
Constructor[] constructors = clazz2.getDeclaredConstructors();
System.out.println("---------构造方法列表---------");
for (Constructor constructor : constructors)
{
//打印反射获取到的构造方法。
System.out.println(constructor);
}
//反射获取类中成员方法
Method[] methods = clazz3.getDeclaredMethods();
System.out.println("---------成员方法列表---------");
for (Method method : methods)
{
//打印通过反射获取的方法列表
System.out.println(method);
}
//通过反射方式构建类的实例对象,首先获取构造方法,再通过指定构造方法构建对象
Constructor constru = clazz1.getConstructor(String.class);
String str = (String) constru.newInstance("Hello java!");
System.out.println(str);
}
}
反射技术与泛型结合练习中遇到的问题:
package com.itheima;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
/**
*
*
* @author Wu
*/
public class Test1
{
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException, SecurityException
{
// TODO Auto-generated method stub
// ------------------打印int[].class中的方法-------------------
int[] arr = new int[3];
Class clazz1 = int[].class;
Method[] methods1 = clazz1.getDeclaredMethods();
System.out.println("-------int[].class中的方法-------");
if (methods1.length == 0)
{
// System.out.println("int[].class---->没有成员方法");
}
Constructor[] constructor = clazz1.getDeclaredConstructors();
if (constructor.length == 0)
{
// System.out.println("int[].class---->没有构造方法");
}
// System.out.println(clazz1.getName());
// 只要参数化泛型类型时,不是String。貌似就可以运行时添加和取出任意类型。
ArrayList<Integer> collection1 = new ArrayList<Integer>();
collection1.getClass().getMethod("add", Object.class).invoke(collection1, new Date());
System.out.println(collection1.get(0));
ArrayList<Date> collection3 = new ArrayList<Date>();
collection3.getClass().getMethod("add", Object.class).invoke(collection3, "hello");
collection3.getClass().getMethod("add", Object.class).invoke(collection3, 17);
System.out.println(collection3.get(0) + ":" + collection3.get(1));
// 当参数化泛型类型为String时,运行时能添加任意类型,但取出时出现类型转换
ArrayList<String> collection2 = new ArrayList<String>();
Object obj = collection2.getClass().getMethod("add", Object.class).invoke(collection2, 12);
// System.out.println(collection2.get(0));
Object obj1 = collection2.getClass().getMethod("add", Object.class)
.invoke(collection2, new Date());
// System.out.println(collection2.get(0));
// 返回两个true,说明都添加成功。
System.out.println(obj + ":" + obj1);
// 是在取出的时候出问题。
Iterator it = collection2.iterator();
while (it.hasNext())
{
Object object = (Object) it.next();
System.out.println(object);
}
// ------------------打印Array.class中的方法-------------------
Class clazz2 = Array.class;
Method[] methods2 = clazz2.getDeclaredMethods();
// System.out.println("-------Array.class中的方法-------");
System.out.println(clazz2.getName());
for (Method method : methods2)
{
// System.out.println(method.getName());
}
}
}