也浅谈下Java反射

Java代码 复制代码
  1. importjava.lang.reflect.Array;
  2. importjava.lang.reflect.Constructor;
  3. importjava.lang.reflect.Field;
  4. importjava.lang.reflect.Method;
  5. importjava.util.Arrays;
  6. /**
  7. *浅谈Java反射
  8. *
  9. *@authorleejon
  10. *
  11. */
  12. publicclassReflectTest{
  13. @SuppressWarnings("unchecked")
  14. publicstaticvoidmain(String[]args)throwsException{
  15. /**
  16. *反射的概念:反射就是把Java类中的各种成分映射成相应的Java类。
  17. *例如:一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等信息
  18. *也用一个个的Java类来表示。就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。
  19. *表示Java类的Class类显然要提供一系列的方法来获取其中的变量,方法,构造方法,修饰符,包等信息。这些信息用相应类的实例对象来表示。
  20. *他们就是Field,Method,Constructor,Package等。
  21. *一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象。
  22. */
  23. System.out.println("==========Class类Demo========");
  24. Class<?extendsObject>cla1=String.class;
  25. Class<?extendsObject>cla2=Class.forName("java.lang.String");
  26. /**
  27. *之所以相等。是因为在jvm中已经装载了String类对象的字节码
  28. */
  29. System.out.println("两对象是否相等:"+(cla1==cla2));
  30. /**
  31. *String类不属于原始类型
  32. */
  33. System.out.println("是否是原始类型:"+cla1.isPrimitive());
  34. System.out.println("int是否是原始类型?:"+int.class.isPrimitive());
  35. System.out.println("原始类型及其包装类型字节码:"+(Integer.class==int.class));
  36. /**
  37. *基本类型的字节码==其包装类的TYPE属性的字节码
  38. */
  39. System.out.println(int.class==Integer.TYPE);
  40. /**
  41. *数组不属于原始类型,是为另外一种类型:Array
  42. */
  43. System.out.println("原始类型的数组的字节码不是原始类型:"+(int[].class.isPrimitive()));
  44. System.out.println("数组是否为Array类型:"+int[].class.isArray());
  45. System.out.println("=====================反射中构造方法demo=================");
  46. /**
  47. *获取某个类的所有的构造函数,返回一个Constructor类型的数组
  48. */
  49. Constructor[]constructors=StringBuffer.class.getConstructors();
  50. for(Constructorconstructor:constructors){
  51. System.out.println(constructor.getName());
  52. }
  53. /**
  54. *根据参数的类型获取某个类的构造函数
  55. */
  56. Constructorconstructor=String.class
  57. .getConstructor(StringBuffer.class);
  58. System.out.println(constructor.getName());
  59. /**
  60. *注意:创建对象的时候指定的参数类型要和获取该Constructor对象时的类型相同
  61. *如果类型不同,在IDE中可以通过编译,但是运行期则会抛出异常,----类型不匹配
  62. *假设:constructor.newInstance(newStringBuffer("demo"));
  63. *则运行异常,因为String.class.getConstructor(StringBuffer.class)
  64. *获取Constructor实例时指定的参数类型为StringBuffer
  65. *=============================================================
  66. *××××××要注意的地方:××××××××调用获得的方法时要用相同的类型×××××××××××××
  67. *=============================================================
  68. *
  69. *Class类的newInstance和Constructor对象的newInstance的关系:
  70. *Class类的newInstance方法为创建类的对象提供便利。
  71. *一般情况下,创建对的对象步骤:class-->Constructor-->newIntance(Class<?>...paramType)
  72. *Class.newInstance():该方法内部先得到默认的构造方法,然后用该构造方法创建实例。/
  73. *内部代码用到了缓存机制来保存默认构造方法的实例对象
  74. */
  75. Stringstr=(String)constructor.newInstance(newStringBuffer("demo"));
  76. System.out.println("根据Constructor的newInstance方法所创建的实例:"+str);
  77. System.out.println("str的第二个字符:"+str.charAt(1));
  78. System.out.println("=============成员变量的反射============");
  79. ReflectPointpp1=newReflectPoint(3,5);
  80. FieldfieldY=pp1.getClass().getField("y");
  81. /**
  82. *fieldY不表示某个对象代表的值,而单纯表示对象本身
  83. */
  84. System.out.println("FieldY:"+fieldY);
  85. /**
  86. *如果要获取fieldY在具体对象上的值(字段的值)则:fieldY.get(OneObj)
  87. */
  88. System.out.println("fieldY的值:"+fieldY.get(pp1));
  89. /**
  90. *对于私有的成员变量,不能使用getField获得,所以,以下代码运行时出错
  91. */
  92. //FieldfieldX=pp1.getClass().getField("x");
  93. //System.out.println("FieldX:"+fieldX);
  94. //System.out.println("fieldX的值:"+fieldX.get(pp1));
  95. /**
  96. *对于私有的成员属性,可以采用getDeclaredField("属性名")的方式获取该成员(Filed)的引用
  97. *并且要设置其为可访问:如:fieldX.setAccessible(true);该访问成员的方式可称之为暴力反射^_^
  98. *========================================================
  99. *对于这里的fieldX和上面的fieldY,仅仅代表字节码的对象,而不是表示某个对象中的一个成员属性的值
  100. *如果要将其和某个对象相关联起来,则可以使用:fieldX.get(pp1),表示在pp1这个对象中x这个属性的值
  101. *========================================================
  102. */
  103. FieldfieldX=pp1.getClass().getDeclaredField("x");
  104. fieldX.setAccessible(true);
  105. System.out.println("FieldX:"+fieldX);
  106. System.out.println("fieldX的值:"+fieldX.get(pp1));
  107. System.out.println("===========Medthod类===============");
  108. MethodmethodCharAt=String.class.getMethod("charAt",int.class);
  109. System.out.println(methodCharAt);
  110. /**
  111. *以反射的方式调用某个对象的方法用:invoke(要调用那个对象,参数数组):后面的参数方法原型为可变长度参数,其内部以数组形式实现。
  112. */
  113. StringmethodStr="HelloWorld!";
  114. System.out.println(methodCharAt.invoke(methodStr,1));
  115. System.out.println("============数组的反射==============");
  116. int[]arr1=newint[]{45,5,6,666,778};
  117. System.out.println(arr1.getClass().getSuperclass());
  118. int[]arr11=newint[]{1,2,3};
  119. /**
  120. *这里比较的是两个对象,所以不相等。而下面的getClass则比较的是字节码。因为两个数组都是int型的,所以,他们的字节码是相等的。
  121. */
  122. System.out.println("arr1==arr11:"+(arr1==arr11));
  123. System.out.println("arr1.getClass()==arr11.getClass():"
  124. +(arr1.getClass()==arr11.getClass()));
  125. int[][]arr2=newint[][]{newint[]{1,2,3,4,5},
  126. newint[]{6,7,8,9,10}};
  127. System.out.println("arr2:"+arr2);
  128. String[]arr3=newString[]{"hello","world"};
  129. System.out.println("arr3:"+arr3);
  130. /**
  131. *基本类型的一维数组只可以被当作Object使用而不能被当作Object[]来使用。
  132. *非基本类型的一维数组,既可以作为Oject类型来使用,也可以作为Object[]类型来使用
  133. */
  134. System.out.println(arr2.getClass().getSuperclass());
  135. System.out.println("StringsuperClass:"
  136. +arr3.getClass().getSuperclass().getName());
  137. //Object[]obj1=arr1;(编译器报错)
  138. Object[]obj2=arr2;
  139. Object[]obj3=arr3;
  140. /**
  141. *以下两行显示[[I@14318bb<br>
  142. *[Ljava.lang.String;@ca0b6
  143. */
  144. System.out.println(obj2);
  145. System.out.println(obj3);
  146. System.out.println("=============java.util.Arrays类==========");
  147. /**
  148. *对于字符串类型的数组。用Arrays的静态方法asList(Object...a)能够将obj2作为一个List集合将其值输出,
  149. *但是,对于int类型的数组,虽然转换成为了List,却还是输出其每个元素的地址,这是为什么呢?
  150. *因为arr1数组是int型,属于基本类型。arr1
  151. *.getClass().getName()=[I,所以JDK编译器将整个数组作为一个Object(一个整型数组)进行处理.
  152. *这也是Arrays.asList(Object...a)处理int[]和String[]时的差异
  153. */
  154. System.out.println(Arrays.asList(arr1));
  155. System.out.println(arr1.getClass().getName());
  156. System.out.println(Arrays.asList(obj3));
  157. /**对数组进行反射操作*/
  158. ObjectprintObj=arr3;
  159. Classclazz=printObj.getClass();
  160. if(clazz.isArray()){
  161. /**如果是数组*/
  162. /**得到长度*/
  163. System.out.println("传入的参数是数组");
  164. intlength=Array.getLength(printObj);
  165. for(inti=0;i<length;i++){
  166. System.out.println(Array.get(printObj,i));
  167. }
  168. }else{
  169. System.out.println("传入的参数不是数组");
  170. System.out.println(printObj);
  171. }
  172. }
  173. }
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 浅谈Java反射
 * 
 * @author leejon
 * 
 */
public class ReflectTest {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
		/**
		 * 反射的概念: 反射就是把Java类中的各种成分映射成相应的Java类 。
		 * 例如:一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包 等信息
		 * 也用一个个的Java类来表示。就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。
		 * 表示Java类的Class类显然要提供一系列的方法来获取其中的变量,方法,构造方法,修饰符,包等信息。 这些信息用相应类的实例对象来表示。
		 * 他们就是Field,Method,Constructor,Package等。
		 * 一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示, 通过调用Class类的方法可以得到这些实例对象。
		 */
		System.out.println("==========Class类Demo========");
		Class<? extends Object> cla1 = String.class;
		Class<? extends Object> cla2 = Class.forName("java.lang.String");
		/**
		 * 之所以相等。是因为在jvm中已经装载了String类对象的字节码
		 */
		System.out.println("两对象是否相等:" + (cla1 == cla2));
		/**
		 * String类不属于原始类型
		 */
		System.out.println("是否是原始类型:" + cla1.isPrimitive());
		System.out.println("int 是否是原始类型?:" + int.class.isPrimitive());
		System.out.println("原始类型及其包装类型字节码:" + (Integer.class == int.class));
		/**
		 * 基本类型的字节码==其包装类的TYPE属性的字节码
		 */
		System.out.println(int.class == Integer.TYPE);
		/**
		 * 数组不属于原始类型,是为另外一种类型:Array
		 */
		System.out.println("原始类型的数组的字节码不是原始类型:" + (int[].class.isPrimitive()));
		System.out.println("数组是否为Array类型:" + int[].class.isArray());

		System.out.println("=====================反射中构造方法demo=================");
		/**
		 * 获取某个类的所有的构造函数,返回一个Constructor类型的数组
		 */
		Constructor[] constructors = StringBuffer.class.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor.getName());
		}
		/**
		 * 根据参数的类型获取某个类的构造函数
		 */
		Constructor constructor = String.class
				.getConstructor(StringBuffer.class);
		System.out.println(constructor.getName());
		/**
		 * 注意:创建对象的时候指定的参数类型要和获取该Constructor对象时的类型相同
		 * 如果类型不同,在IDE中可以通过编译,但是运行期则会抛出异常,----类型不匹配
		 * 假设:constructor.newInstance(new StringBuffer("demo"));
		 * 则运行异常,因为String.class.getConstructor(StringBuffer.class)
		 * 获取Constructor实例时指定的参数类型为StringBuffer
		 * =============================================================
		 * ××××××要注意的地方:××××××××调用获得的方法时要用相同的类型×××××××××××××
		 * =============================================================
		 * 
		 * Class类的newInstance和Constructor对象的newInstance的关系:
		 * Class类的newInstance方法为创建类的对象提供便利。
		 * 一般情况下,创建对的对象步骤:class-->Constructor-->newIntance(Class<?>...paramType)
		 * Class.newInstance():该方法内部先得到默认的构造方法,然后用该构造方法创建实例。/
		 * 内部代码用到了缓存机制来保存默认构造方法的实例对象
		 */
		String str = (String) constructor.newInstance(new StringBuffer("demo"));
		System.out.println("根据Constructor的newInstance方法所创建的实例:" + str);
		System.out.println("str的第二个字符:" + str.charAt(1));

		System.out.println("=============成员变量的反射============");
		ReflectPoint pp1 = new ReflectPoint(3, 5);
		Field fieldY = pp1.getClass().getField("y");
		/**
		 * fieldY不表示某个对象代表的值,而单纯表示对象本身
		 */
		System.out.println("FieldY:" + fieldY);
		/**
		 * 如果要获取fieldY在具体对象上的值(字段的值)则:fieldY.get(OneObj)
		 */
		System.out.println("fieldY的值:" + fieldY.get(pp1));

		/**
		 * 对于私有的成员变量,不能使用getField获得, 所以,以下代码运行时出错
		 */
		// Field fieldX = pp1.getClass().getField("x");
		// System.out.println("FieldX:" + fieldX);
		// System.out.println("fieldX的值:"+fieldX.get(pp1));

		/**
		 * 对于私有的成员属性,可以采用getDeclaredField("属性名")的方式获取该成员(Filed)的引用
		 * 并且要设置其为可访问:如:fieldX.setAccessible(true); 该访问成员的方式可称之为暴力反射^_^
		 * ========================================================
		 * 对于这里的fieldX和上面的fieldY,仅仅代表字节码的对象, 而不是表示某个对象中的一个成员属性的值
		 * 如果要将其和某个对象相关联起来,则可以使用:fieldX.get(pp1),表示在pp1这个对象中x这个属性的值
		 * ========================================================
		 */
		Field fieldX = pp1.getClass().getDeclaredField("x");
		fieldX.setAccessible(true);
		System.out.println("FieldX:" + fieldX);
		System.out.println("fieldX的值:" + fieldX.get(pp1));

		System.out.println("===========Medthod类===============");
		Method methodCharAt = String.class.getMethod("charAt", int.class);
		System.out.println(methodCharAt);
		/**
		 * 以反射的方式调用某个对象的方法 用:invoke(要调用那个对象,参数数组): 后面的参数方法原型为可变长度参数,其内部以数组形式实现。
		 */
		String methodStr = "HelloWorld!";
		System.out.println(methodCharAt.invoke(methodStr, 1));

		System.out.println("============数组的反射==============");
		int[] arr1 = new int[] { 45, 5, 6, 666, 778 };
		System.out.println(arr1.getClass().getSuperclass());
		int[] arr11 = new int[] { 1, 2, 3 };
		/**
		 * 这里比较的是两个对象,所以不相等。而下面的getClass则比较的是字节码。 因为两个数组都是int型的, 所以,他们的字节码是相等的。
		 */
		System.out.println("arr1==arr11:" + (arr1 == arr11));
		System.out.println("arr1.getClass()==arr11.getClass():"
				+ (arr1.getClass() == arr11.getClass()));
		int[][] arr2 = new int[][] { new int[] { 1, 2, 3, 4, 5 },
				new int[] { 6, 7, 8, 9, 10 } };
		System.out.println("arr2:" + arr2);
		String[] arr3 = new String[] { "hello", "world" };
		System.out.println("arr3:" + arr3);
		/**
		 * 基本类型的一维数组只可以被当作Object使用而不能被当作Object[]来使用。
		 * 非基本类型的一维数组,既可以作为Oject类型来使用,也可以作为Object[]类型来使用
		 */
		System.out.println(arr2.getClass().getSuperclass());
		System.out.println("String superClass:"
				+ arr3.getClass().getSuperclass().getName());
		// Object[] obj1=arr1;(编译器报错)
		Object[] obj2 = arr2;
		Object[] obj3 = arr3;
		/**
		 * 以下两行显示[[I@14318bb<br>
		 * [Ljava.lang.String;@ca0b6
		 */
		System.out.println(obj2);
		System.out.println(obj3);
		System.out.println("=============java.util.Arrays类==========");
		/**
		 * 对于字符串类型的数组。用Arrays的静态方法asList(Object...a)能够将obj2作为一个List集合将其值输出,
		 * 但是,对于int类型的数组,虽然转换成为了List,却还是输出其每个元素的地址,这是为什么呢?
		 * 因为arr1数组是int型,属于基本类型。arr1
		 * .getClass().getName()=[I,所以JDK编译器将整个数组作为一个Object(一个整型数组)进行处理.
		 * 这也是Arrays.asList(Object...a)处理int[]和String[]时的差异
		 */
		System.out.println(Arrays.asList(arr1));
		System.out.println(arr1.getClass().getName());
		System.out.println(Arrays.asList(obj3));
		/** 对数组进行反射操作 */
		Object printObj = arr3;
		Class clazz = printObj.getClass();
		if (clazz.isArray()) {
			/** 如果是数组 */
			/** 得到长度 */
			System.out.println("传入的参数是数组");
			int length = Array.getLength(printObj);
			for (int i = 0; i < length; i++) {
				System.out.println(Array.get(printObj, i));
			}
		} else {
			System.out.println("传入的参数不是数组");
			System.out.println(printObj);
		}
	}
}


Java代码 复制代码
  1. publicclassReflectPoint{
  2. privateintx;
  3. publicinty;
  4. publicReflectPoint(intx,inty){
  5. this.x=x;
  6. this.y=y;
  7. System.out.println("X:"+this.x+",Y:"+this.y);
  8. }
  9. @Override
  10. publicStringtoString(){
  11. return"X:"+this.x+",Y:"+this.y;
  12. }
  13. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值