java反射学习

反射:

理解:

通过对反射的学习,得到最初的解释:反射就是把java类中的各个成员映射成相应的java类。

应用反射,可以实现框架,满足更多的程序的需求。反射还可以使用私有方法,可以实现更多的功能。反射允许程序创建和控制任何类的对象,无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常普通的方式与对象协作的库。Java reflection 非常有用,它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息。

上例子:

实体类源代码:

ackage com.hu;public class ReflectPoint {public int x;private int y;public String str1 = "ball";public String str2 = "basketball";public String str3 = "canhua";public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}public int getX() {return x;}private int getY() {return y;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + x;result = prime * result + y;return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;ReflectPoint other = (ReflectPoint) obj;if (x != other.x)return false;if (y != other.y)return false;return true;}@Overridepublic String toString() {return "ReflectPoint [x=" + x + ", y=" + y + ", str1=" + str1+ ", str2=" + str2 + ", str3=" + str3 + "]";}}


测试程序:

package com.hu;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Text1 {public static void main(String[] args) throws Exception {String str1 = "abc";Class cls1 = str1.getClass();Class cls2 = String.class;Class cls3 = Class.forName("java.lang.String");System.out.println("cls1 == cls2:" + (cls1 == cls2));System.out.println("cls1 == cls3:" + (cls1 == cls3));// isPrimitive()方法 表示返回是否为基本数据类型System.out.println("cls1.isPrimitive():" + (cls1.isPrimitive()));System.out.println("int.class.isPrimitive():"+ (int.class.isPrimitive()));// Integer.class 表示Integer对象的Class的实例System.out.println("int.class == Integer.class:"+ (int.class == Integer.class));// Integer.TYPE 表示基本类型int的Class的实例System.out.println("int.class == Integer.TYPE:"+ (int.class == Integer.TYPE));// 在java中数组也是一种对象,所以也有Class类返回System.out.println("int[].class.isPrimitive():"+ (int[].class.isPrimitive()));System.out.println("int[].class.isArray():" + (int[].class.isArray()));int[] a1 = new int[3];int[] a2 = new int[4];int[][] a3 = new int[2][3];String[] a4 = new String[4];int[] a5 = new int[3];// 打印falseSystem.out.println("a1.getClass() == a2.getClass():"+ (a1.getClass() == a2.getClass()));// 打印trueSystem.out.println("a1.getClass() == a5.getClass():"+ (a1.getClass() == a5.getClass()));// new String(new StringBuffer("abc"));与下面两行是相同的。Constructor constructor = String.class.getConstructor(StringBuffer.class);String str2 = (String) constructor.newInstance(new StringBuffer("abc"));System.out.println("str2:" + str2);System.out.println("str2.charAt(2):" + str2.charAt(2));// 应该打印cReflectPoint pt1 = new ReflectPoint(3, 5);System.out.println("pt1.x:" + pt1.x);// 获得ReflectPoint中的变量,跟上面的效果是一样的Field fieldX = pt1.getClass().getField("x");System.out.println("fieldX.getInt(pt1):" + (fieldX.getInt(pt1)));// 获得ReflectPoint的私有变量Field fieldY = pt1.getClass().getDeclaredField("y");// 设置可以访问属性(暴力反射)fieldY.setAccessible(true);System.out.println("fieldY.getInt(pt1):" + (fieldY.getInt(pt1)));// 获得其中的方法,第一个参数是方法名,第二个参数是传入的参数类型Method method = pt1.getClass().getMethod("getX", null);// 调用该方法,第一个参数是哪个对象,第二个参数是传入的参数int temp = (int) method.invoke(pt1, null);System.out.println(method.getName() + "     " + temp);// 获得私有方法Method method2 = pt1.getClass().getDeclaredMethod("getY", null);// 设置可以访问属性(暴力反射)method2.setAccessible(true);// 调用该方法,第一个参数是哪个对象,第二个参数是传入的参数int temp2 = (int) method2.invoke(pt1, null);System.out.println(method2.getName() + "    " + temp2);changeStringValue(pt1);}private static void changeStringValue(Object obj)throws IllegalArgumentException, IllegalAccessException {// 获得所有成员变量Field[] fields = obj.getClass().getFields();for (Field field : fields) {// 这里用equals可以实现同样的效果,但类型为同一个,字节码想通过,如下写更好if (field.getType() == String.class) {// 获得成员变量的值String oldvalue = (String) field.get(obj);// 将所有的ball替换为***String newValue = oldvalue.replace("ball", "***");// 同样的,前一个参数是哪个对象,第二个参数是替换为什么值field.set(obj, newValue);}}System.out.println(obj.toString());}}

打印的结果:

cls1 == cls2:truecls1 == cls3:truecls1.isPrimitive():falseint.class.isPrimitive():trueint.class == Integer.class:falseint.class == Integer.TYPE:trueint[].class.isPrimitive():falseint[].class.isArray():truea1.getClass() == a2.getClass():truea1.getClass() == a5.getClass():truestr2:abcstr2.charAt(2):cpt1.x:3fieldX.getInt(pt1):3fieldY.getInt(pt1):5getX     3getY    5ReflectPoint [x=3, y=5, str1=***, str2=basket***, str3=canhua]

再来一个例子:

配置文件的内容是:

config.properties

className=java.util.ArrayList

测试的类:

package com.hu;import java.io.FileInputStream;import java.util.Collection;import java.util.Properties;/** * 利用反射,可以根据传入的参数动态的调用不同的类,同样的可以调用不同的方法,所谓框架就是如此,因为框架要适应多种情况,应用配置文件进行配置,接着进行调用, * 这样框架更具健壮性 *  * @author hucanhua * */public class hu {public static void main(String[] args) throws Exception {// 这里是用文件输入流读取类的名字FileInputStream ips = new FileInputStream("config.properties");// 这个是java的默认的参数对象,我们可以使用它Properties props = new Properties();// 从字节流读取配置信息props.load(ips);ips.close();// 获得配置信息中className字段的值String className = props.getProperty("className");System.out.println(className);Collection collection = (Collection) Class.forName(className).newInstance();ReflectPoint pt1 = new ReflectPoint(3, 3);ReflectPoint pt2 = new ReflectPoint(5, 5);ReflectPoint pt3 = new ReflectPoint(3, 3);collection.add(pt1);collection.add(pt2);collection.add(pt3);collection.add(pt1);// 因为配置信息是java.util.ArrayList类型,所以是允许重复的,故打印出来的个数是4// 如果配置信息是java.tuil.HashSet类型,同时ReflectPoint实现以上hashCode方法,则会打印3个System.out.println(collection.size());}}

输出的结果:

java.util.ArrayList4

没有朋友的人生是孤独的,不完整的,可是,因为生活的忙碌,

java反射学习

相关文章:

你感兴趣的文章:

标签云: