----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------
反射
1 Class: Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class.
2 字节码:一个类被类加载到内存中,占用一片存储空间,就个空间就是字节码.
3 得到字节码: 类名.class 对象.getClass() Class.forName("类名")
代码验证
String str = "abc";
Class c1 = str.getClass()//得到字节码;
Class c2 =String.class;//得到字节码
Class c3 =Class.forName("java.lang.String");//得到字节码
c1==c2==c3
System.out.println(c1.isPrimitive());//不是基本类型
System.out.println(int.class.isPrimitive());//基本类型
System.out.println(int.class==Integer.class);//两种不同类型的字节码
System.out.println(int.class==Integer.TYPE);//同类型的字节码
System.out.println(int [].class.isPrimitive());//数组不是原始类型
/*属于基本类型:原始类型的字节码
Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE,
Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE*/
4 反射就是把Java类中的各种成分映射成相应的java类。
5 Constructor类
//得到某个类所有的构造方法
Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
//得到某个类的一个构造方法
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
//由构造方法得到类的对象,必须是相对应的参数:new StringBuffer("sdf")
String Str = (String)constructor.newInstance(new StringBuffer("sdf"));
Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
6 Field类代表某个类中的一个成员变量
public Field getField(String name) 这个name必须是这个类的成员变量(非私有)的名字,如类的 int x=8,x就是name中的一个 getDeclaredField则可以访问所有的成员变量
要想访问 则先用setAccessible(true)方法
filex.setAccessible(true);
System.out.println(filex.get(pt1));
7 成员变量反射的综合应用
//o是一个类的实例对象
private static void changeStringValue(Object o) throws Exception
{
// TODO Auto-generated method stub
//由对象找到字节码
Class c1 = o.getClass();
//由字节码 找出所有的成员类型
Field [] file = c1.getFields();
//判断成员类型
for(int i=0;i<file.length;i++)
{
if(file[i].getType()==String.class)
{
//由对象找到成员类型变量
String ago = (String)file[i].get(o);
//新字符代替旧字符
String now = ago.replace("b", "a");
//装进去
file[i].set(o, now);
}
}
System.out.println(o);//打印的toString()方法已经被重写
}
8 Method类代表某个类中的一个成员方法
String str ="abc";
获得字节码
Class c = str.getClass();
获得 方法
Method charAt = c.getMethod("charAt", int.class);
调用方法
System.out.println(charAt.invoke(str, 2));
new Object[]{1}:表示一个存储 new Object 对象的数组,现在里面有一个元素,1自动装箱为Intger型
System.out.println(charAt.invoke(str, new Object[]{1}));
如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!
9 用反射方式执行某个类中的main方法
问题:
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"}); ,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了
10 数组的反射及应用
a、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
b、代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类
对应的Class.
c、基本类型的一维数组可以被当作Objcet类型使用,不能当作Object[]类型使用。
;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用
d、Arrays.asList()方法处理int[]和String[]时,有差异。
e、Array工具类用于完成对数组的反射操作
f、怎么得到数组元素的类型
无法得到数组的类型,但可以得到数组元素的类型
int [] a = new int [3];
Object[] a = new Object[]{“a”,1};
a[0].getClass().getName(); //这里可以得到某个元素的类型
注意代码注释部为什么不能通过编译:下有无法通过图
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayOfReflect {
public static void main(String[] args) {
int [] a1 = new int[]{1,2,3};
int [] a2 = new int[4];
int[][] a3 = new int [2][3];
String[] a4 = new String[]{"a", "b", "c"};
System.out.println(a1.getClass() == a2.getClass());
/*
* 所有类型相同和维数相同的数组它的的类字节码都是一样的
* a1的类字节码 与a3、a4的类字节码永远都不会一样
* jdk1.5以后,编译器认为这2个类型是不一样的。
* 根本没有比较的需要。对于总是不成立的比较,其实是没有意义的
* 所以编译器会报错!
System.out.println(a1.getClass() == a4.getClass());
System.out.println(a1.getClass() == a3.getClass());
*/
System.out.println(a1.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());
Object aObj1 = a1;
Object aObj2 = a4;
// Object[] aObj3 = a1;
Object[] aObj4 = a3;
Object[] aObj5 = a4;
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));
// 注意这里为什么不能打印出a1里的值,为了兼容jdk1.4,但jdk1.4只能传Object[]
// 但a1是基本数据类型,无法打印出里面的值,那怎样解决呢 下面通过自己编写方法,来打印
System.out.println(Arrays.asList(a4));
printObject(a1);
}
private static void printObject(Object obj) {
Class clazz = obj.getClass();
if (clazz.isArray()) {
int len = Array.getLength(obj);
for (int i = 0; i < len; i++) {
System.out.print(Array.get(obj, i));
}
} else {
System.out.println(obj);
}
}
}
----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------