您的位置:首页 > 其它

构造函数、成员变量、成员方法、静态方法、数组的反射应用

2014-12-14 14:22 417 查看
1、 反射就是通过Class类提供的方法获取所有class类的构造函数(Constructor)、成员变量(Field)、成员方法(Method)、静态方法等;

2、Class类和class类的区别:描述所有人的类是Person类(class类),描述所有java类的的类是Class类Person类的实例是张三、李四; Class类的实例是各个类在内存中的字节码; 每个类在内存中的字节码是不同的,若每个类空间都用一个个对象来表示, 那么这些对象就具有相同的类型,那么这个类型就是Class

3、获取Sting字节码对应的实例对象(Class类型)的三种方法如下:

public class ReflectDemo {

public static void sop(Object obj) {
System.out.println(obj);
}

public static void main(String[] args) throws Exception {
String s = "abcd";
// 三种获取String字节码对应的实例对象(Class类型),
//1、实例对象的getClass()方法获取
Class<? extends String> cla = s.getClass();
// 2、类名.class获取
Class<String> clb = String.class;
// 3、Class.forName("类名")方法获取
Class<?> clc = Class.forName("java.lang.String");
sop(cla == clb);
sop(clb == clc);
sop(cla);
sop(clb);
sop(clc);
}
}
运行结果是:

true
true
class java.lang.String
class java.lang.String
class java.lang.String
通过结果知道三个获取的字节码是一致的,都是【class java.lang.String】

4、通过反射的原理写出构造方法

// 创造String实例的普通方法
sop(new String(new StringBuffer("abc")));
/*
* 创造String实例的反射方法,首先获取到String字节码的构造方法StringBuffer.class,
* 调用获得的构造方法时要用到相同类型的实例对象, 编译时没有使用cons后面的语句, 所以编译时若没有指定(String)则报错
*
* Constructor类代表构造函数的类,通过字节码可以获取到任意一个类的构造函数
*/
// 通过类名.class获得的String字节码
Constructor cons = String.class.getConstructor(StringBuffer.class);
String str = (String) cons.newInstance(new StringBuffer("abc"));
sop(str);
// 通过Class.forName("类名")获得类名String的字节码
Constructor cons1 = Class.forName("java.lang.String").getConstructor(
StringBuffer.class);
String str1 = (String) cons1.newInstance(new StringBuffer("bcd"));
sop(str1);
// 通过实例对象的获得
String s1 = new String();
Constructor cons2 = s1.getClass().getConstructor(StringBuffer.class);
String str2 = (String) cons.newInstance(new StringBuffer("efg"));
sop(str2);

// 该方法获得是获得String类的无参构造函数
String str3 = (String) Class.forName("java.lang.String").newInstance();
结果是:

abc
abc
bcd
efg
通过结果知道通过获取的String字节码调用Constructor类获取String类的构造方法结果是一致的

5、成员常量和成员方法的反射应用如下:

成员常量的类是Field类,成员方法的类是Method类

/*
* Field类代表成员变量的类,通过二阶码可以获取任何类内的成员变量
*/
FieldClass fic = new FieldClass(4, 8);
// public修饰的常量y,通过Field参数获取
Field fa = fic.getClass().getField("y");
sop(fa.get(fic));
// private修饰的常量x,通过Field参数获取
Field fb = fic.getClass().getDeclaredField("x");
fb.setAccessible(true);
sop(fb.get(fic));

/*
* Method类代表成员方法的类,通过二节码可以获取任何类内的成员方法
*/
String st = "5678";
Method mt = Class.forName("java.lang.String").getMethod("charAt",
int.class);
sop(mt.invoke(st, 2));
//静态成员方法用反射的类调用,需要在invoke(null,)的第一个参数为空
Method mta = Class.forName("java.lang.String").getMethod("valueOf",
int.class);
sop("静态成员方法:" + mta.invoke(null, 2));

6、反射调用另外一个类的main函数

import java.lang.reflect.Method;

public class ReflectMain {

public static void main(String[] args) throws Exception {
//调用主函数的参数,设置主函数的参数为newStudy.template(通过F2查看template的路径)
String startClassName = args[0];
Method mainMethod = Class.forName(startClassName).getMethod("main",
String[].class);
/*
* jdk1.5中是可变参数形式Object invoke(Object obj, Object...args).
* jdk1.4中是参数数组形式Object invoke(Object obj, Object[] obj).
* jdk1.5为了兼容jdk1.4,invoke()方法要接收到一个参数数组时,也会将数组进行拆分,当成方法的多个参数
*/
mainMethod.invoke(null, new Object[] { new String[] { "1", "2", "3" } });
mainMethod.invoke(null, (Object) new String[] { "a", "b", "c" });
}
}

class template {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
7、int[]等基本数据类型数组和String[]等引用数据类型数据在反射处理上是有些不同的,int[]等基本数据类型是按照一个整体处理,String[]等引用类型则自动进行拆分

import java.lang.reflect.Array;
import java.util.Arrays;

public class ArrayReflectDemo {

public static void main(String[] args) {
int[] a = new int[] { 1, 3, 5 };
int[] b = new int[2];
int[][] c = new int[2][];
String[] s = new String[] { "sf", "wfw" };
sop(a.getClass() == b.getClass());
// 打印的[I 代表的是int类型的数组
sop(a.getClass().getName());
sop(s.getClass().getName());
/*
* Incompatible operand types Class<capture#4-of ? extends int[]> and
* Class<capture#5-of ? extends int[][]> 下面两个都是互相不兼容的操作数据类型,不允许编译通过
*/
/*
* sop(a.getClass() == c.getClass()); sop(a.getClass() == s.getClass());
*/
sop(a.getClass().getSuperclass().getName());
sop(s.getClass().getSuperclass().getName());

Object aobj = a;
Object bobj = b;
Object cobj = c;
Object sobj = s;
/*
* 下面三个的打印结果是[[I@15db9742]
* [I@15db9742
* [[I@15db9742]
* [I代表是整型的数组,[]代表的是集合
*/
sop("********");
sop(Arrays.asList(a));
//如果sop方法判断是否是数组,则可以逐个打印出来
sop(a);
sop(Arrays.asList(aobj));

/*
* 下面三个打印的结果是:[sf, wfw]
* [Ljava.lang.String;@6d06d69c
* [[Ljava.lang.String;@6d06d69c]
* 基本数据类型的数组转换成集合后不能打印出来集合内的元素,
* String类型的可以转换成集合后且可以打印出集合内的元素
*/
sop("********");
sop(Arrays.asList(s));
//如果sop方法判断是否是数组,则可以逐个打印出来
sop(s);
sop(Arrays.asList(sobj));

}
/*	private static void sop(Object obj){
System.out.println(obj);
}*/

private static void sop(Object obj) {
Class<? extends Object> a = obj.getClass();
if(a.isArray()){
int len = Array.getLength(obj);
for(int i=0; i < len; i++){
System.out.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}

}


总结:

反射原理就是通过Class类型获取字节码内的构造方法、成员常量、成员方法赋予一个类(Constructor、Field、Method),再通过对应的类的方法获取java类的数据
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐