黑马程序员-----反射

来源:互联网 发布:网络淘宝涮单是真的嘛 编辑:程序博客网 时间:2024/05/29 03:46
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

1.Class
Class是一个类的类名,这个类表示所有类的字节码。当类加载时,JVM将类的class文件读入内存,并为之创建一个java.lang.Class对象,也就是说当程序中使用任何类时,系统都会为之建立一个java.lang.Class对象。
Class没有公共的构造器,获得Class对象有三种方法:
1)使用Class类的forName(String className)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类名的全限定类名(必须添加完整的包名)。例如:
Class cls = Class.forName("java.lang.String");
2)调用某个类的class属性来获取该类对应的Class对象。例如:
Class cls = Person.class;
3)调用某个对象的getClass()方法,该方法是java.lang.Object类中的一个方法,所以所有Java对象都可以调用该方法,该方法将会返回该对象所属类对应的Class对象。
Class cls = p.getClass();

Class方法:
每个Class实例代表一个类的字节码,当获取了Class实例后,就可以通过getXxx方法获取该类的Field、Constructor、Method对象。

Field getField(String name):返回一个Field对象,它反映此Class对象所表示的类或接口的指定公共成员字段。
Field[] getFields():返回一个包含所有Field对象的数组。

Constructor<T> getConstructor(Class<?>...parameterTypes):返回一个Constructor对象,它反映此Class对象所表示的类的指定公共构造方法。
Constructor<T>[] getConstructors():返回一个包含所有Constructor对象的数组。

Method getMethod(Class<?>...parameterTypes):返回一个Method象,它反映此Class对象所表示的类或接口的指定公共成员方法。name参数是一个String,用于指定所需方法的简称。parameterTypes参数是按声明顺序标识该方法形参类型的Class对象的一个数组。
Method[] getMethods():返回一个包含所有Method对象的数组。

T newInstance():创建此Class对象所表示的类的一个新实例。如同用一个带有一个空参数列表的new表达式实例化该类。
public class ReflectDemo {public static void main(String[] args) throws ClassNotFoundException {//使用类名.class得到Class实例Class cls1 = ReflectDemo.class;//使用某对象的getClass方法得到Class实例Class cls2 = p.getClass();//使用Class的静态方法forName得到Classs实例Class cls3 = Class.forName("java.lang.String");//输出falseSystem.out.println(int.class == Integer.class);//输出trueSystem.out.println(int.class == Integer.TYPE);//输出falseSystem.out.println(int[].class.isPrimitive());//输出trueSystem.out.println(int[].class.isArray());}}

2.反射
反射,就是将某个类中的一些或所有成员映射成相应的类。
Field类:Field提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
Constructor类:Constructor提供关于类的单个构造方法的信息以及对它的访问权限。 
Method类:Method提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 
通过Class实例的getXxx方法即可得到其成员类的实例。

3.Field
Field提供有关类或接口的单个字段的信息,以及对它的动态访问权限。
当访问公有属性时,步骤如下:
1)得到某类的Class实例。
2)通过Class实例方法getField得到Field实例,参数为字符串形式的属性名。
3)通过Field实例方法get得到指定对象的属性值,将指定对象作为参数传入。

当访问私有属性时,步骤如下:
1)得到某类的Class实例
2)通过Class实例方法getDeclaredField得到Field实例,参数为字符串形式的属性名。此方法忽略属性的访问权限。
3)使用Field方法setAccessible(true)将该属性变为可访问的。
4)通过Field实例方法get得到指定对象的属性值,将指定对象作为参数传入。
public class Point {//私有属性private int x;//公有属性public int y;public Point(){} public Point(int x, int y) {this.x = x;this.y = y;}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;}}


public class FieldDemo {public static void main(String[] args) throws Exception {//创建Point对象Point pt = new Point(3,5);//-----下面使用反射对公有属性y进行访问-----//1.通过对象getClass方法得到Class实例Class cls = pt.getClass();//2.通过Class实例方法getField得到Field实例,参数为字符串形式的属性名Field fieldY = cls.getField("y");//3.通过Field实例方法get得到指定对象的属性值,将指定对象作为参数传入System.out.println(fieldY.get(pt));//-----下面使用反射对私有属性x进行访问-----//1.通过对象getClass方法得到Class实例//2.通过Class实例方法getDeclaredField得到Field实例,参数为字符串形式的属性名。此方法忽略属性的访问权限。Field fieldX = cls.getDeclaredField("x");//3.使用Field方法setAccessible(true)将该属性变为可访问的。fieldX.setAccessible(true);//4.通过Field实例方法get得到指定对象的属性值,将指定对象作为参数传入System.out.println(fieldX.get(pt));}}

4.Constructor
Constructor提供关于类的单个构造方法的信息以及对它的访问权限。
使用反射创建某个类对象步骤:
1)获取该类的Class实例。
2)使用Class实例方法getConstructor(Class<?>...parameterType)得到Constructor实例。因为某个类的构造器有多个,所以这个方法传入的参数是指定构造器的参数。
3)使用Constructor实例方法newInstance创建对象。传入的参数要与上面parameterType严格一致。
public class ConstructorDemo {public static void main(String[] args) throws Exception {//使用反射达到语句new String(new StringBuffer("abc"));的效果//1.得到String字节码文件Class实例Class cls = String.class;//2.通过Class实例方法getConstructor得到Constructor实例Constructor constructor = cls.getConstructor(StringBuffer.class);//3.使用Constructor实例方法newInstance创建对象。String str = (String)constructor.newInstance(new StringBuffer("abc"));System.out.println(str);}}

注:Class本身也有一个newInstance方法,这个方法是直接调用该字节码文件的无参构造器。而Constructor的newInstance方法可以调用多个重载的构造器。

5.Method
Method提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。
使用反射调用某个对象方法的步骤:
1)得到该类的字节码文件对象。
2)使用Class实例方法getMethod(String name, Class<?>...parameterType)方法得到Method对象。该方法传入两个参数:name代表指定方法的方法名,parameterType调用此方法要接收的参数。因为一个方法可能有不同参数,所以parameterType可以指定是哪一个具体方法。
3)使用Method实例方法invoke(Object obj, Object...arg)调用指定方法。该方法传入两个参数:obj代表指定的对象,即调用该对象身上的方法。当obj为null时,说明该方法是静态方法。arg代表调用该方法时实际传入的参数。
public class MethodDemo {public static void main(String[] args) throws Exception {//实现str.charAt(1)的效果String str = new String("abc");//1.得到String类的字节码文件对象Class cls = String.class;//2.通过Class实例方法getMethod得到Method对象Method method = cls.getMethod("charAt", int.class);//3.使用Method实例方法invoke调用指定方法System.out.println(method.invoke(str, 1));}}



---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net
0 0