`
yaqi0628
  • 浏览: 6749 次
  • 性别: Icon_minigender_1
  • 来自: 株洲
最近访客 更多访客>>
社区版块
存档分类
最新评论

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 + "]";
	}
}



分享到:
评论

相关推荐

    java reflection in action

    在《Java Reflection in Action》这本书中,作者深入探讨了这一主题,帮助开发者理解并有效地利用Java反射机制。这本书是2005年出版的英文版,对于想要提升Java编程技能,特别是对动态类型和元编程感兴趣的开发者来...

    Java Reflection in Action

    Java Reflection in Action这本书作为Java反射机制的经典之作,详细介绍了反射技术的应用和相关的概念基础,是Java开发者的必备书籍。 首先,反射允许开发者在不知道对象具体类型的情况下,通过类名获取类类型,...

    Java Reflection In Action

    本书《Java Reflection in Action》深入浅出地讲解了Java反射技术的各种应用场景和技术细节。书中通过一系列生动的例子展示了如何安全有效地使用反射技术解决实际问题。例如: 1. **使用反射进行动态代理**:介绍了...

    Java Reflection in Action_PDF+sample source

    《Java Reflection in Action》这本书深入探讨了这一主题,为开发者提供了理解和运用反射的强大工具。这本书包含了PDF版的全文以及示例源代码,帮助读者通过实践来学习。 1. **反射基础**: - 反射API:`java.lang...

    Java Reflection In Action(英文版)

    《Java Reflection In Action》这本书深入探讨了这个主题,对于理解和掌握Java动态性有着极大的帮助。以下是关于Java反射的一些关键知识点: 1. **反射基础**:反射API主要包括`java.lang.Class`、`java.lang....

    基于Java Reflection自动逆向生成类间方法关系图的解析器.pdf

    Java Reflection是Java提供的用于在运行时获取类、接口、方法、字段等信息的机制。在本论文中,作者利用反射机制开发了一个能够自动逆向分析Java源代码或编译后的.class文件的解析器。反射在动态语言编程中有着广泛...

    Manning Java Reflection In Action

    Java Reflection in Action Java Reflection in Action is unique in presenting a clear account of all the cool things you can do with reflection, and at the same time providing the sound conceptual basis...

    Java Reflection (JAVA反射)详解

    Java 反射(Reflection)是Java编程语言的一个重要特性,它允许程序在运行时动态地获取类的信息(如类名、方法、字段等)并直接操作对象的内部属性。这为开发者提供了强大的灵活性,能够在不预先知道具体类的情况下...

    JAVA REFLECTION IN ACTION

    《JAVA反射在行动》这本书由Ira R. Forman和Nate Forman撰写,由MANNING出版社出版,是一本深入探讨Java反射机制及其应用的权威指南。反射是Java语言的一项强大特性,允许运行时检查类的信息并操作类的对象,这在很...

    Java Reflection (JAVA反射)

    ### Java反射机制详解 #### 一、Java反射机制概述 反射是Java编程语言的一个关键特性,它赋予了Java程序在运行时自我检查的能力,并能够直接操纵程序内部的属性。通过反射,开发者可以在运行时获取类的信息(如...

    基于Java Reflection的数据库访问通用模型设计与实现.pdf

    "基于Java Reflection的数据库访问通用模型设计与实现" 本文提出了基于Java Reflection机制和面向接口的编程思想,设计并实现了一款Java数据库访问通用模型,该模型具有适用范围广、轻量级、可扩展性好等特点,可以...

    Manning - Java Reflection in Action

    《Java Reflection in Action》一书由Ira R. Forman和Nate Forman共同撰写,旨在帮助读者深入理解Java反射机制的核心概念和技术细节,并通过一系列实用案例展示如何有效地利用反射技术来解决实际问题。 #### 二、...

    Java反射经典实例 Java Reflection Cookbook[1].pdf

    ### Java反射经典实例详解 #### 一、引言 反射是Java编程语言中的一个重要特性,它允许程序在运行时检查自身结构(如类、字段、方法等),并且可以在运行时调用任意一个类的成员(包括私有成员)。这一特性为Java...

    Java Reflection (JAVA反射.mht

    Java Reflection (JAVA反射.mht

Global site tag (gtag.js) - Google Analytics