黑马程序员-JAVA基础加强-反射1

来源:互联网 发布:知不足者下一句 编辑:程序博客网 时间:2024/05/16 12:33
------- android培训、java培训、期待与您交流! ---------

反射
Class类
        Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有不同的属性值。Java程序中的各个Java类,可以用一个类来描述这类事物,这个类的名字就是Class,它主要描绘了类的名字,类的访问属性,类所属于的包名,字段名称的列表、方法名称的列表,等等。每个java类都是Class的一个实例对象,它们的内容不同,但是它们的特征相同,譬如,都有方法,有字段,有父类,有包。
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可以分别用一个个的对象来表示,这些对象具有相同的类型,这个类型就是Class类
Class字节码得到的三种方式
        1.类名.class,例如,System.class
        2.对象.getClass(),例如,new Date().getClass()
        3.Class.forName("类名"),例如,Class.forName("java.util.Date");
获取类的字节码举例
        1. 类名.class,例如,System.class
        2.对象.getClass(),例如,new Date().getClass()
        3.Class.forName("类名"),例如,Class.forName("java.util.Date");
得到类的字节码的两种情况
        1.该类的字节码已经加载到内存中了,现在去拿到其字节码不需要加载了,直接找到字节码返回。
        2.该类的字节码还未加载到虚拟机,于是用类加载器去加载,加载以后,就把字节码缓冲起来,同时用Class.forName("java.lang.String")返回刚才加载进来的字节码。
     Class.forName的作用:返回字节码,第一种返回已加载过的字节码,第二种用类加载器去加载,然后缓存至JVM,以后得到该字节码就不用加载了。
九个预定义Class实例对象
        有九种预定义的 Class 对象,表示八个基本类型和 void。这些类对象由 Java 虚拟机创建,与其表示的基本类型同名,即 boolean、byte、char、short、int、long、float 和 double。
         int.class==Integer.Type
反射
       反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。
Constructor类(构造方法)
得到某个类所有的构造方法:

       1.Constructor [] constructors= Class.forName("java.lang.String").getConstructors();得到某一个构造方法:
       2.Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);//获得方法时要用到类型创建实例对象:
       通常方式:String str = new String(new StringBuffer("abc"));
       反射方式:Constructor constructor1 = String.class.getConstructor(StringBuffer.class);//先得到该类的构造方法String str = (String)constructor1.newInstance(new StringBuffer("abc"));//调用获得的方法时要用到上面相同
类型的实例对象
       Class.newInstance()方法:例子:String obj = (String)Class.forName("java.lang.String").newInstance();//该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。用到了缓存机制来保存默认构造方法的实例对象。
Field类字段的反射
Field类:代表某个类中的一个成员变量,通过getField得到的Field对象是对应到类上面的成员变量,所以字段fieldX 代表的是类上的所有字段变量,而不是具体的对象的x变量。
常用方法介绍:
        Class.getField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
        Field.get(Object obj) 返回指定对象上此 Field 表示的字段的值。
        Class.getDeclaredField(String name)返回一个 Field 对象,用于获取私有变量的获取
        void|setAccessible(boolean flag) 将私有字段对象的方法设置安全检查
获取字段值:
package cn.itcast.day1;public class ReflectPoint {private int x;public  int y;//为了给这两个变量赋值,我们通过构造方法给这两个变量赋值public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}}import java.lang.reflect.Field;public class ReflectTest{public static void main(String[] args)throws Exception{ReflectPoint pt1=new ReflectPoint(3,5);Field fieldY =pt1.getClass().getField("y");//获取y字段的字节码对象System.out.println(fieldY.get(pt1));//获取y字段的值Field fieldX =pt1.getClass().getDeclaredField("x");//用于获取声明过的变量fieldX.setAccessible(true);//讲X字段的方法设置为安全System.out.println(fieldX.get(pt1)); }}

Method类

         Method类代表某个类的一个成员方法得到类中的某一个方法:
        例子: Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
调用方法:
        通常方式:System.out.println(str.charAt(1));
        反射方式: System.out.println(charAt.invoke(str, 1)); 如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!

反射指定类中的方法:

//获取类中所有的方法。public static void method_1() throwsException {Class clazz =Class.forName("cn.itcast.bean.Person");Method[] methods = clazz.getMethods();//获取的是该类中的公有方法和父类中的公有方法。methods = clazz.getDeclaredMethods();//获取本类中的方法,包含私有方法。  for(Method method : methods)   {   System.out.println(method);   }}//获取指定方法;public static void method_2() throwsException {Class clazz =Class.forName("cn.itcast.bean.Person");//获取指定名称的方法。Method method =clazz.getMethod("show", int.class,String.class);//想要运行指定方法,当然是方法对象最清楚,为了让方法运行,调用方法对象的invoke方法即可,但是方法运行必须要明确所属的对象和具体的实际参数。Object obj = clazz.newInstance();method.invoke(obj, 39,"hehehe");//执行一个方法}//想要运行私有方法。public static void method_3() throwsException {Class clazz = Class.forName("cn.itcast.bean.Person");//想要获取私有方法。必须用getDeclearMethod();Method method =clazz.getDeclaredMethod("method", null);// 私有方法不能直接访问,因为权限不够。非要访问,可以通过暴力的方式。method.setAccessible(true);//一般很少用,因为私有就是隐藏起来,所以尽量不要访问。}//反射静态方法。public static void method_4() throwsException {Class clazz =Class.forName("cn.itcast.bean.Person");Method method =clazz.getMethod("function",null);method.invoke(null,null);}
------- android培训、java培训、期待与您交流! ---------
原创粉丝点击