java Reflection




/**
* 反射--Class的基本分析
* @author yaqi
* @date 2012/06/26
*
*/
public class ReflectionTest {

/**
* Class 代表一类事物
*
* Java类用于描述一类事物的共性,该类事物有什么
* 属性,没有什么属性,至于这个属性的值是什么,
* 则是由这个类的实例对象来确定的.
* 不同的实例对象有不同的属性值
*
* eg:
* 人 --> Person
* Java类 --> Class
*
* eg:
*
* Person p1 = new Person();
*
* Class cls1 = new Class();// 不成立
* Class cls2 = 代表一份字节码;每一份的字节码都是一个类的实例对象
*
* 故:
*
* Class cls3 = new Date.class //成立
*
* 延伸:
* 得到类的字节码(三种方式):
* System.class //类名.class
* p1.getClass(); // 对象.getClass()
* Class.forName("java.lang.String"); //类加载器 返回字节码 主要用在反射中
*
* 类加载器的作用:
* 1.这份字节码之前已被加载到JVM中,直接返回
* 2.这份字节码还不存在,用类加载器去加载,把加载进来的类缓存到JVM中,
*
*
* 九个预定义的Class实例对象:
* 八个基本类型+void
* boolean byte char short int long float double <b>void</b>
*
*/

public static void main(String[] args) throws ClassNotFoundException {

String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");

System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);

/**
* result:
* true
* true
*
* 结论:三个实例对象共用一份字节码
*/

System.out.println(cls1.isPrimitive()); //是否为原始类型
/**
* result :
* false
*结论: String 不是基本类型
*/
System.out.println(int.class.isPrimitive());
/**
* result:
* true
* 结论: int 是基本类型
*/
System.out.println(int.class == Integer.class);
/**
* result:
* false
* 结论: Integer 不是基本类型
*/
System.out.println(int.class == Integer.TYPE);
/**
* result:
* true
* 结论:Integer 中的 TYPE常量: 代表包装类型所包装的基本类型的字节码 其它包装类型也是一样
*/

System.out.println(int[].class.isPrimitive());
/**
* result:
* false
* 结论:
* 数组也是一个类型,但它不属于基本类型
* 数组类型的判断方法: Class.isArray()
*/
/***********************************************/
/**
* 总之,只要是在源程序中出现的类型,都有各自的Class实例对象,eg: int[]
*/
}
}


/**
* Reflection:
* 反射就是把Java类中的各种成分映射成相应的Java类.
*
* 一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示.
*
* 反射会导致性能下降:因为它会对某一些构造方法进行缓存.耗内存.
*/

/**
* 构造方法的反射应用
*
* Constructor 类代表某个类中的<b>某一个</b>构造方法
*
*/
class ConstructorTest{

public static void main(String[] args) throws SecurityException, NoSuchMethodException,
IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
// 得到一个带StringBuffer为参数的构造方法的String对象
Constructor con1 = String.class.getConstructor(StringBuffer.class);
String str2 = (String)con1.newInstance(new StringBuffer("abc"));

//用反射实现: new String(new StringBuffer("abc"));
}
}

/**
*
* 成员变量的反射
*
* Field
*/

class ReflectFieldTest{

public static void main(String[] args) throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException {
ReflectPoint pt1 = new ReflectPoint(3, 5);

Field fieldY = pt1.getClass().getField("y"); //getField() 只能得到可见的变量
// fieldY 不是对象身上的变量,而是类上的变量,要用它来读取某个对象所对应的值
//获得fieldY的值
fieldY.get(pt1);

//取x的值
Field fieldX = pt1.getClass().getDeclaredField("x"); //能得到所有的变量,但对于私有变量"可见不可得"
fieldX.setAccessible(true); //对于私有变量使用"暴力反射",使之"可见又可得"
}
}

/**
* 成员变量的反射的综合案例
*
* 扫描一个对象身上所有的String类型的变量,将'b'转换成'a'
*/
class ReflectFieldTest2{

public static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException{
Field[] fields = obj.getClass().getFields();
for(Field f : fields){
if(f.getType() == String.class){ //同一份字节码用'=='来比较,而不用'equels'
String oldVal = (String)f.get(obj);
String newVal = oldVal.replace('b', 'a');
f.set(obj, newVal); // 改变对象身上的值
}
}
}
}

/**
* 成员方法的反射
*
* 模拟String.charAt(int) 的两种调用方法
*/
class ReflectMethodTest{

public static void main(String[] args) throws SecurityException, NoSuchMethodException,
IllegalArgumentException, IllegalAccessException, InvocationTargetException {
String str1 = "abc";
//method 1:
str1.charAt(2);

//method 2:
Method methodCharAt = String.class.getMethod("charAt", int.class);
methodCharAt.invoke(str1, 1); //invoke 方法类的具体方法的调用工具(方法)
//司机把火车刹车了:
// 司机发了一个信号给火车,然后火车自己调用了自己的刹车方法将火车刹住了
// invoke: 是方法的调用,但需要一个对象
methodCharAt.invoke(null, 1); //invoke 使用一个空对象,说明该对象的这个方法的是一个static的;

}
}

/**
* 23_对接收数组参数的成员方法进行反射
*
* 这个程序能够根据用户提供的类名,去执行该类中的main方法
*/
class ReflectMethodTest2{

public static void main(String[] args) throws SecurityException, NoSuchMethodException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

//method 1:
TestArguments.main(new String[]{"1","2","3"});

//method 2:
String className = args[0]; // 假设第一个参数表示要执行的类名
Method mainMethod = Class
.forName(className)
.getMethod("main",String.class);

//main方法是static 故invoke 可以是传一个null对象
mainMethod.invoke(null,new String[]{"111","22","33"});
//会报错 ,原因看jdk源码 ;jdk会将传过来的数组进行拆包,故实际传过去的是三个参数,而不是一个;
//编译器会作特殊处理,编译时不把参数当作数组看待,也就是打散成若干个参数.

mainMethod.invoke(null,new Object[]{new String[]{"111","22","33"}});//将这个数组对象再次打包成一个数组,而jdk只会进行一个拆包操作,故实际传的只是一个参数,只不过是一个数组类型的参数
//Or
mainMethod.invoke(null,(Object)new String[]{"111","22","33"}); // 强制说明这个数组为一个Object类型,即为一个参数,因此编译器会视其为一个参数.
}
}

class TestArguments{
public static void main(String[] args) {
for(String s : args){
System.out.println(s);
}
}
}


/**
* 数组与Object的关系及其反射类型
*
* Every array also belongs to a class that
* with the same element type and number dimensions (维数)
*
* 每一个数组都属于同一个字节码:具有相同类型和维数
*/

class ReflectArrayTest{

public static void main(String[] args) {

int[] a1 = new int[3];
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] a4 = new String[3];

System.out.println(a1.getClass() == a2.getClass()); //true
System.out.println(a1.getClass() == a4.getClass()); //false
System.out.println(a1.getClass() == a3.getClass()); //false

//得到父类的类名
System.out.println(a1.getClass().getSuperclass().getName());
// result : java.lang.Object
// 数组的父类是Object
Object aObj1 = a1; //向上转
Object aObj2 = a4;
Object[] aObj3 = a3; // 数组是Object 数组的数组也就是Objcet数组

Object obj4 = a4; // 可以, a4是引用类型String 父类是Object
Object obj5 = a1; // 不行, a1 是基本类型的数组 不是Object


//********************************************

int[] a = new int[]{1,2,3};
String[] aa = new String[]{"a","b","c"};
System.out.println(a1);
System.out.println(aa);
//result:
// [I@1cfb549
// [Ljava.lang.String;@186d666

//如若希望看到的结果是具体的值 ,而不是这样的Hash码
System.out.println(Arrays.asList(a));;
System.out.println(Arrays.asList(aa));
//Arrays : Array的工具类
//result:
// [I@1cfb549
// [a,b,c]

//why? 为什么会是这样的结果

//Arrays.asList(Objetc[] obj) jdk1.4 当成Object[] 来处理
//Arrays.asList(T ...a) jdk1.5 当成一个对象来处理

}

/**
* 对数组进行反射
* java.lang.reflect.Array
*/

/**
* 对数组进行打印
* 传的参数有可以是数组,也有可以只是一个对象值
* @param obj
*/
public 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.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}

/**
* 怎么得到数组中值的类型?
*
*/
}

class ReflectPoint {

private int x;

public int y;

public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "cccca";

public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}

@Override
public String toString() {
return "ReflectPoint [x=" + x + ", y=" + y + ", str1=" + str1
+ ", str2=" + str2 + ", str3=" + str3 + "]";
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值