一.对反射的理解。
(1)
AVA反射是一个非常重要的概念,很多框架都是通过反射来完成的.!
反射就是把Java类中的各种成分映射成相应的java类。在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?
答案是肯定的。这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。
(2)Java反射机制主要提供了以下功能:
1,在运行时判断任意一个对象所属的类;
2,在运行时构造任意一个类的对象;
3,在运行时判断任意一个类所具有的成员变量和方法;
4,在运行时调用任意一个对象的方法;
5,生成动态代理。
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。
1,Class类:代表一个类。
2,Field类:代表类的成员变量(成员变量也称为类的属性)。
3,Method类:代表类的方法。
4,Constructor类:代表类的构造方法。
5,Array类:提供了动态创建数组,以及访问数组元素的静态方法。
(3)
我们知道每一个类被加载之后,系统就会为该类生成一个对应的Class对象,通过该Class对象我们就可以访问到JVM中的这个类了,
java程序获取Class对象有三种方式:
1>使用Class类的forName()静态方法,该方法传入字符串参数,该字符串是某个类的全限定类名!
2>调用该类的class属性来获取该类对应的Class对象,例如Dog.class
3>调用某个对象的getClass方法,,该方法是Object类的一个方法,所以Java对象都可以调用这个方法.
二.反射操作属性,方法,数组,集合的演示
package com.hu.Reflect;
import java.lang.reflect.*;
import java.util.*;
public class ReflectDemo extends ReflectPoint {
publicReflectDemo(int i, int j) {
super(i,j);
}
// 给我一个对象,就能够改掉一个对象的中的属性。
private static void changeStringValue(Object obj) throws Exception
{
Field[] fields = obj.getClass().getFields();
for(Field field :fields)
//if (field.getType().equals(String.class)) 同一份字节码
if(field.getType()== String.class) //对字节码用等号比较更好。
{
String oldValue = (String) field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
publicstatic void main(String[] args) throws Exception
{
String str = "abc";
*/
Class cls1= str.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
System.out.println("判断字节码文件:");
System.out.println(cls2==cls1);
System.out.println(cls2==cls3);// 结果为 true true 表明三个方法获得的实例都是同一份字节码文件。
System.out.println("通过反射判断基本类型:");
System.out.println(cls1.isPrimitive());//false 判断是否是基本类型
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class==Integer.class);//f
System.out.println(int.class==Integer.TYPE);// t 判断Integer的一个实例是否和int的字节码文件相同
System.out.println(int[].class.isPrimitive()); //f 判断 int[] 是不是一个基本类型
System.out.println(int[].class.isArray());//t 判断int [] 是不是一个数组
ReflectPoint pt = new ReflectPoint(3,5);
//通过反射访问属性:
System.out.println("通过反射访问属性:");
Field fieldY = pt.getClass().getField("y");
System.out.println(fieldY.get(pt));// fieldY 现在是Field类的一个对象, 调用它的get方法获取属性。
Field fieldX = pt.getClass().getDeclaredField("x"); //DeclaredField来取到私有的成员。
fieldX.setAccessible(true); //设置为True 取消访问权限的检查。以便DeclaredField取到的私有成员可以使用。
System.out.println(fieldX.get(pt));
changeStringValue(pt);
System.out.println(pt);
//通过反射访问方法:
System.out.println("通过反射访问方法:");
//new String(newStringBuffer("abc")); 下面用反射的方式 达到相同的目的。
Constructor const1 =String.class.getConstructor(StringBuffer.class);// 获得构造方法时,要用到参数类型的class
String str1 =(String)const1.newInstance(newStringBuffer("abc"));// 需要传递相同类型的对象。
System.out.println(str1.charAt(2));
Method methodCharAt =String.class.getMethod("charAt", int.class);// ()内是方法名和方法的参数类型的 字节码文件
//getMethod(Stringname, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
System.out.println(methodCharAt.invoke(str,1)); // ()内是指定 调用此方法的对象和调用此方法传入的参数。
//invoke(Objectobj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
Class refpt = pt.getClass();
Method m1;
try {
m1 =refpt.getDeclaredMethod("toString",String.class,String.class,String.class);//原函数有三个String类型的参数。
String str2 = (String)m1.invoke(pt,"wo","lai","le");
System.out.println(str2);
} catch (Exception e) {
e.getStackTrace();
}
//通过反射操作数组:
System.out.println("通过反射操作数组:");
int [] a1 = new int[]{1,2,3};
//int [] a1 = new int[3]; 如果数组的元素已经确定,就不需要在指定数组的大小。
int [] a2 = new int[4];
int [][] a3= new int[2][3];
String [] a4= newString[]{"a","b","c"};//如果数组的元素已经确定,就不需要在指定数组的大小。
System.out.println(a1.getClass()==a2.getClass());
// System.out.println(a1.getClass()==a3.getClass());
// System.out.println(a1.getClass()==a4.getClass());
System.out.println(a1.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());
try
{ //创建一个元素类型为String,长度为10的数组
Object arr =Array.newInstance(String.class, 10);
// 给arr 数组中的index为7,8的元素赋值。
Array.set(arr, 7, "你们好!");
Array.set(arr, 8, "wo lai le ");
// 取出arr 数组中index为7,8的元素的值
Object s1 = Array.get(arr , 7);
Object s2 = Array.get(arr , 8);
System.out.println(s1);
System.out.println(s2);
}catch(Exception e){
e.getStackTrace();
}
List<Integer> list = newArrayList<Integer>();
String str3 ="abc"; list.getClass().getMethod("add",Object.class).invoke(list,str3);
//此处只能用Object.class,用Integer.class和String.class 都错误。
System.out.println("...."+list);
}
}