----------------------
android培训、java培训、期待与您交流! -------------------------
Java反射机制
概念:反射就是把java类中的各种成分映射成相应的java类,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。例如,一个java类用一个Class类的对象来表示,一个类中的组成部分:成员变量,成员方法,构造方法,包等等信息也用一个个的java类来表示。就好比汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类,表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应的实例对象来表示,它们是Field,Method,Constructor,Package等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象,学习和应用反射的要点就是研究这些实例对象的作用和用法。
1.构造方法的反射应用Constructor类
Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:
Constructor[] constructors = Class.forName("java.lang.String").getConstructor();
得到某个类某一个构造方法:
Constructor constructor =Class.forName("java.lang.String").getConstructor(StringBuffer.class);
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(newStringBuffer("abc"));
Class.newInstance()方法应用:
例子:String obj =(String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
注:该方法内部代码用到了缓存机制来保存默认构造方法的实例对象。
2.成员变量的反射应用Field类
Field类代表某个类中的一个成员变量
得到的Field对象是对应到类上面的成员变量。原因:类只有一个,而该类的实例对象有多个,如果是与对象关联,那关联的是哪个对象呢?所以字段fieldX代表的是x的定义,而不是具体的x变量。(示例代码见:reflecttest.java)
3.成员方法的反射应用Method类
Method类代表某个类中的一个成员方法
得到类中的某一个方法:
Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:
通常方式:str.charAt(1);
反射方式:charAt.invoke(str,1);
如果传递给Method对象的invoke()方法的第一个参数为null,这没有什么意义,说明该Method对象对应的是一个静态方法。
4.用反射方式执行某个类中的main方法:
目标:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
问题:
启动java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法的,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac到底会按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new
String[]{"xxx"}),javac只把它当作jdk1.4的语法进行理解,而不把空当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
解决办法:
mainMethod.invoke(null,new Object[]{newString[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"});编译器会作特殊处理,编译时不把参数当作数组看待,也就不会将数组打散成若干个参数了。
5.数组的反射:
1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
2.代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class.
3.基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
4.Arrays.asList()方法处理int[]和String[]时的差异。
Arrays工具类用于完成对数组的反射操作。
反射的作用-->实现框架功能:
框架:
通俗易懂的框架解读:我建房子卖给用户住,由用户自己安装门窗和空调,我建的房子就是框架,用户需要用我的框架,把门窗插入进我提供的框架中。框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
框架要解决的核心问题:
我在写框架(房子)时,你这个用户可能还在上小学,还不会写程序,我写的框架程序怎样能调用到你以后写的类(门窗)呢?
因为在写程序时无法知道要被调用的类名,所以,在程序中无法直接new某个类的实例对象,而要用反射方式来做。
综合案例:(代码见:ReflectTest.java,ReflectTest2.java)
示例代码:
ReflectTest.java
package cn.itcast.day1; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; public class ReflectTest { @SuppressWarnings("unchecked") publicstatic void main(String[] args) throws Exception { Stringstr = "abc"; Class<String>cls1 = (Class<String>) str.getClass(); //三种得到字节码的方式 Class<String>cls2 = String.class; Class<String>cls3 = (Class<String>) Class.forName("java.lang.String"); System.out.println(cls1== cls2);//true System.out.println(cls1== cls3);//true System.out.println(cls1.isPrimitive()); System.out.println(int.class.isPrimitive()); System.out.println(int.class== Integer.class); System.out.println(int.class== Integer.TYPE); Constructorconstructor = String.class.getConstructor(StringBuffer.class); Stringstr1 = (String)constructor.newInstance(new StringBuffer("abc")); //Stringstr1 = (String)constructor.newInstance("abc");//argument typemismatch System.out.println(str1.charAt(2)); ReflectPointpt1 = new ReflectPoint(3, 5); FieldfieldY = pt1.getClass().getField("y"); //fieldY的值是多少?是5,错!!fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值。 System.out.println(fieldY.get(pt1)); FieldfieldX = pt1.getClass().getDeclaredField("x"); fieldX.setAccessible(true);//暴力反射 System.out.println(fieldX.get(pt1)); //System.out.println(pt1); changeStringValue(pt1); System.out.println(pt1); //成员方法反射。 MethodmethodCharAt = String.class.getMethod("charAt", int.class); System.out.println(methodCharAt.invoke(str,1)); System.out.println(methodCharAt.invoke(str,new Object[]{2})); //用反射方式执行某个类中的main方法。 StringstartingClassName = args[0]; MethodmainMethod = Class.forName(startingClassName).getMethod("main",String[].class); mainMethod.invoke(startingClassName,new Object[]{newString[]{"adf","fghh","asdth"}});//记得给程序进行运行配置 //mainMethod.invoke(startingClassName,(Object)new String[]{"adf","fghh","asdth"}); //数组与Object的关系及其反射类型 int[]a1 = new int[]{1,2,3}; int[]a2 = new int[4]; int[][]a3 = new int[2][3]; String[]s1 = new String[]{"a","b","c"}; System.out.println(a1.getClass()==a2.getClass()); //System.out.println(a1.getClass()== a3.getClass()); //System.out.println(a1.getClass()== s1.getClass()); System.out.println(a1.getClass().getName()); System.out.println(a1.getClass().getSuperclass().getName()); System.out.println(s1.getClass().getSuperclass().getName()); Objectobj1 = a1;//a1数组的父类就是object,所以赋值成功 Objectobj2 = s1;//String的父类是Object //Object[]obj3 = a1;//不行的,object数组里面装的应该是object,而将a1数组赋给object数组是不行的,因为a1数组里面装的是int类型 Object[]obj4 = a3;//可以,object数组中装的是int[] ,而int[]的父类型就是object Object[]obj5 = s1; System.out.println(a1); System.out.println(s1); System.out.println(Arrays.asList(a1)); System.out.println(Arrays.asList(s1)); printObject(s1); printObject("xyz"); } privatestatic void printObject(Object obj) { Classclazz = obj.getClass(); if(clazz.isArray()){ intlen = Array.getLength(obj); for(inti = 0 ;i<len;i++){ System.out.println(Array.get(obj,i)); } }else{ System.out.println(obj); } } //非常有用的一个代码 privatestatic void changeStringValue(Object obj) throws Exception { Field[]fields = obj.getClass().getFields(); for(Fieldfield : fields) { if(field.getType()== String.class) { StringoldValue = (String) field.get(obj); StringnewValue = oldValue.replace('b', 'a'); field.set(obj,newValue); } } } } class TestArguments{ publicstatic void main(String[] args){ for(Stringarg : args){ System.out.println(arg); } } }
ReflectTest2.java
package cn.itcast.day1; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Collection; import java.util.HashSet; import java.util.Properties; public class ReflectTest2 { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub //InputStream ips = new FileInputStream("config.propertise"); //用类加载器加载文件 //InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.propertise");//不能加斜扛“/”cn/itcast/day1/config.propertise InputStream ips = ReflectTest2.class.getResourceAsStream("config.propertise"); Properties props = new Properties(); props.load(ips); ips.close(); String className = props .getProperty("className"); Collection collections = (Collection) Class.forName(className).newInstance(); //Collection collections = new HashSet(); ReflectPoint pt1 = new ReflectPoint(3,3); ReflectPoint pt2 = new ReflectPoint(5,3); ReflectPoint pt3 = new ReflectPoint(3,3); collections.add(pt1); collections.add(pt2); collections.add(pt3); collections.add(pt3); System.out.println(collections.size()); } }
ReflectPoint.java
package cn.itcast.day1; import java.util.Date; public class ReflectPoint { private int x; public int y; private Date birthday = new Date(); public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } String str1 = "abc"; String str2 = "basketball"; String str3 = "itcast"; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } public String toString() { return str1+":"+str2+":"+str3; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public 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; } }
----------------------
android培训、java培训、期待与您交流! ----------------------