黑马程序员 反射

来源:互联网 发布:nginx jetty 区别 编辑:程序博客网 时间:2024/05/16 14:18

java培训、android培训期待与您交流!

       反射技术
   反射就是把Java类中的各中成分映射成相应的Java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等也是一个个类。
   Class类代表Java类,它的各个实例对象分别对应各个类在内存中的字节码。一个类被加载到内存中会占用相应的空间,而这些空间里面实际上存放的就是字节码,这一个个空间可分别哦那个一个个对象来表示,而这些对象显然都具有一个相同的类型,即Class。
   九个预定义的Class实例对象:boolean,byte,char,short,int,long,float,double,void.
   获取字节码对应的实例对象(Class类型)的三种方式:
       类名.class-->System.class
       对象.getClass()-->new Date().getClass()
       Class.forName("类名")-->Class.forName("java.util.Date")  注意,在写类名称时要带上对应的包名!这种方式相对好一些,因为不需要明确具体的类或者对象。只要有这个类名称就可以了。
   反射技术的特点:动态获取一个字节码文件对象中的所有内容,包括函数,构造器等。有了这样的技术后可以大大的提高程序的扩展性。
   最常用的对象:Class,字节码文件也是一个对象,用Class来进行描述,想要操作一个字节码文件,必须要先获取字节码文件所对应的对象。
   动态获取指定的字节码中的内容(例如方法):Method[] getMethods(),这是一个返回包含某些Method对象的数组,这些对象反应此Class对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共成员方法,可以拿到多个方法。
                                             Method getMethod(String name,Class<?>... paraneterTypes),返回一个Method对象,它反映此Class对象所表示的类或接口的指定公共成员方法,可以拿到指定的方法,例如,Method method = clazz.getMethod("方法名",参数),如果无参则为null
                                             Method[] getDeclaredMethod(),返回Method对象的一个数组,这些对象反应此Class对象所表示的类或接口声明的所有方法,包括共有,保护,默认(包)访问和私有方法,但不包含继承的方法。
   调用方法可以用invoke()方法,这样,对应的方法就可以运行了。例:Class clazz = Class.forName("cn.itcast.bean.Person");//获取字节码文件对象
         Method method = clazz.getMethod("show",String.class,Int.class)//注意参数的写法为class.参数类型,如果空参数则为null
           Object obj = clazz.newInstance();//通过字节码文件对象的方法newInstance获取指定的字节码文件对象实例
           method.invoke(obj,zhang san,20);//传参数时一定要传入实际参数!无参时为null,method方法可以运行了
              如果调用的是一个静态方法的话,因为静态方法不需要对象,所以:Class clazz = Class.forName("cn.itcast.bean.Person");
                    Method method1 = clazz.getMethod("stcticMethod",null);//调用一个静态方法
                    method1.invoke(null,null);//静态方法不需要对象
         调用私有方法:Class clazz = Class.forName("cn.itcast.bean.Person");//获取字节码文件对象
                 Method method = clazz.getMethod("show",String.class,Int.class)//注意参数的写法为class.参数类型,如果空参数则为null
                //取消权限控制
                method.setAccessible(true);
                   Object obj = clazz.newInstance();//通过字节码文件对象的方法newInstance获取指定的字节码文件对象实例
                   method.invoke(obj,zhang san,20);//传参数时一定要传入实际参数!无参时为null,method方法可以运行了
     演示获取字节码对应的实例对象(Class类型)的三种方式:
package cn.itcast.reflect;

import cn.itcast.bean.Person;

public class ReflectDemo {

 /**
  * @param args
  * @throws Exception
  */
 public static void main(String[] args) throws Exception {
  getClassObject_3();
  
 }
 /**
  * 如何获取一个类的字节码文件对象呢?
  * 1,每一个对象都有一个共性的方法 getClass():这时Object类中的方法。
  */
 public static void getClassObject_1(){
  
  Person p = new Person();
  Class clazz = p.getClass();
  
  
  Person p1 = new Person();
  Class clazz1 = p1.getClass();
  System.out.println(clazz1.getName());
  
  System.out.println(clazz==clazz1);//true,同一个字节码对象
  
 }
 
 /**
  * 获取Class对象的第二种方式。
  * 2,通过数据类型的class属性来获取该类型的字节码文件对象。
  * 相对比第一种方式要简单。
  * 但是这两种都必须先要有Person类才行。
  * 并不有利于扩展。
  *
  */
 public static void getClassObject_2(){
  Class clazz = Person.class;
  
  System.out.println(clazz.getName());
  
 }
 /**
  * 第三中方式:
  * 3,使用Class类中的方法完成。方法:forName(className);
  * 这种方式相对好一些,因为不需要明确具体的类或者对象。只要有这个类名称就可以了。
  * 给定什么样的名称就获取什么样字节码文件对象。
  * 这也是我们最为 常用的获取字节码文件对象的方式。
  *
  * @throws Exception
  */
 public static void getClassObject_3() throws Exception{
  
  Class clazz = Class.forName("cn.itcast.bean.Person");
  
  System.out.println(clazz.getName());
  
  
 } 
}
       演示获取字节码中的方法:
package cn.itcast.reflect;

import java.lang.reflect.Method;

public class ReflectDemo2 {

 /**
  * @param args
  * @throws Exception
  */
 public static void main(String[] args) throws Exception {
  getPrivateFunction();
 }
 
 
 /**
  * 获取一个私有方法。
  * @throws Exception
  */
 public static void getPrivateFunction() throws Exception{
  Class clazz = Class.forName("cn.itcast.bean.Person");
  
  Method method = clazz.getDeclaredMethod("method", null);
  //System.out.println(method);
  
  //访问私有成员会有异常。如果想要访问可以通过暴力访问完成,
  //也就是取消掉权限的控制。
  method.setAccessible(true);
  //注意:一般不要暴力,因为既然私有,就是不建议被外部的访问的。
  
  
  Object obj = clazz.newInstance();
  method.invoke(obj, null);
 }
 
 /**
  * 获取一个带参数的方法并运行。
  * @throws Exception
  */
 public static void getParamterFunction() throws Exception{
  Class clazz = Class.forName("cn.itcast.bean.Person");
  
  Method method = clazz.getMethod("func", int.class,String.class);
  
  Object obj = clazz.newInstance();
  
  method.invoke(obj, 30,"haha");
  
  
  //调用一个静态方法。
  Method method2 = clazz.getMethod("staticFunc", null);
  method2.invoke(null, null);
  
 }
 
 /**
  * 获取单个方法。
  * @throws Exception
  */
 public static void getSingleFunction() throws Exception{
  Class clazz = Class.forName("cn.itcast.bean.Person");
  
  //获取指定名称方法。获取show方法对象。
  Method method = clazz.getMethod("show", null);
  
  
  //通过字节码文件对象的方法newInstance获取指定的字节码文件对象实例。
  Object obj = clazz.newInstance();
  method.invoke(obj, null);
  
 }
 
 /**
  * 动态获取指定字节码文件对象中的内容。
  * 1,获取字节码文件中的方法。
  * @throws Exception
  */
 public static void getFunction() throws Exception{
  
  
  //1,获取指定名称的字节码文件对象。
  Class clazz = Class.forName("cn.itcast.bean.Person");
  
  //2,通过Class类中的方法获取其字节码文件中的所有方法。
  //注意:getMethods方法获取的类中的公有方法。
  Method[] methods = clazz.getMethods();
  
  //可以通过getDeclaredMethods() 获取到指定类中的所有方法,包含私有,但不包含继承的。
  methods = clazz.getDeclaredMethods();
  
  //3,将方法遍历一下。
  for(Method method : methods){
   System.out.println(method);
  }
  
 }
}

 

java培训、android培训期待与您交流!

原创粉丝点击