反射

来源:互联网 发布:破解压缩文件密码软件 编辑:程序博客网 时间:2024/05/23 20:56

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

一、反射概念

  • 反射就是把Java类中的各种成分映射成相应的Java类。
    • 例如,一个Java类中用一个Class类的对象来表示,
    • 一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个Java类来表示。
    • 就像汽车是一个类,其中的发动机,变速箱等等也是一个类。
    • 表示Java类的Class类显然要提供一系列的方法,来获取其中的变量,方法,构造方法,修饰符,包等信息。这些信息就是用相应类的实例对象来表示,他们是Field、Method、Contructor、Package等等。
  • 一个类中的每一个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象有什么用?怎么用?这正是学习和应用反射的要点。
  • 理解:
    • Java的类进入内存,变成一份份Java字节码文件,每一份字节码文件就是Class类的实例对象(因为Class类就是描述这些字节码文件的类,是所有字节码文件的类)。
    • 字节码文件就是把所有类的字节码文件抽取出的共性(属性、方法、各种信息)封装为一个统一的Class类,而每个字节码文件就是这个Class类的一个实例对象,所以这些对象可以调用Class类的方法,如getMehod(),isPrimitive(),getConstructor()等等。
    • 反射把这些组成部分封装起来
    • 组成部分的字节码文件: Field、Method、Contructor、Package等,这些字节码文件是Class类的实例对象,这些实例对象提供了一些方法暴露自己的信息。
    • 疑问?
      • 这些字节码文件与要反射的类有什么关系呢?
      • 比如说String.class.getConstructor();这一句是String的字节码字节码文件(Class类的实例对象)使用了 Contructor字节码文件 (Class类的实例对象)的 getConstructor()方法?
    • 牢记:
      • 字节码文件是对象,是Class类的实例对象。
    • 得到Class的三种方法:
01.String str1 = "abc";  02.//得到Class的三种方法:对象.getClass,类.class,Class.forName("类名")   03.Class cls1 = str1.getClass();  04.Class cls2 = String.class;  05.Class cls3 = Class.forName("java.lang.String");  
三、Field的反射


 

01.ReflectPoint pt1 = new ReflectPoint(3,5);  02.//通过字节码,得到Field类对象   03.Field fieldY = pt1.getClass().getField("y");  04.System.out.println(fieldY.get(pt1));//   05.  06.//得到private的字段   07.Field fieldX = pt1.getClass().getDeclaredField("x");//private�����ɼ�   08.fieldX.setAccessible(true); 09.System.out.println(fieldY.get(pt1)); 


 

四、Method的反射

01.Method methodCharAt = String.class.getMethod("charAt", int.class);  02.System.out.println(methodCharAt.invoke(str1,1));  03.System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//JDK1.4 


 

五、用反射调用其他类的main 方法。

01.//用反射调用其他的main方法   02.String startingClassName = args[0];  03.Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);  04.mainMethod.invoke(null, new Object []{new String[]{"111","222","333"}});  05.mainMethod.invoke(null, (Object)new String[] {"111","222","333"});  


 

六、数组与Object及其反射类型

  • 具有相同维度、相同类型的数组,它们使用同一份字节码。
  • 基本数据类型不是对象,也不是Object的子类。
  • 使用Arrarys的asList()转为List结合,可以打印出元素。
    • 如果参数是Object的之类,那么按照JDK1.4可以打印出元素。
    • 如果参数是基本数据类型,那么按照JDK1.5的传递一个可变参数,只打印数组的[I@65656。对于这段话,疑问··~
      private static void printObject(Object obj)  {      Class<? extends Object> clazz = obj.getClass();      if (clazz.isArray())      {          int len = Array.getLength(obj);          for (int i = 0; i < len; i++)          {              System.out.println(Array.get(obj, i));          }      }      else          System.out.println(obj);  }  

      七、反射的作用-举例

      • 例子来源:http://www.cnblogs.com/zxl-jay/archive/2011/09/25/2190585.html

      • 需求:设计一个主板,为了提高后期的扩展性,也就是为了后期提高电脑的额功能,对外提供了PCI的接口。以方便电脑功能的扩展。

        interface PCI{                        void open();                         void close();                   }                   class MainBoard{                       public void usePCI(PCI p){                           p.open();                           p.close();                           }                   }                   class MainBoardDemo{                       public static void main(String[] args){                           MainBoard mb=new MainBoard();                              //mb.usePCI(null);                                    mb.usePCI(NetCard);                           }                }   
      • 后期,要进行电脑功能的扩展,需加入一个网卡,只需要定义一个网卡类实现PCI接口,只要覆盖这个规则,主板就可以使用该板卡
    class NetCard implements PCI{                         public void open();{                                system.out.println("open");                            }                             public void close();{                                system.out.println("close");                           }                   }   

    那么为了使用其网卡,还需要做一个步骤就是在已定义好的应用程序中,建立网卡对象,并作为参数传入,那么就是对原有的程序进行修改。这样不利于程序的健壮性。

    可不可以在不修改源码的基础上运行后期出现的这些子类对象呢?

    只要在前期设计时,将后期指定的类进行对象的建立,这样后期的子类对象就不需要再建立对象,只要将子类名称告知即可。

    为了获取后期对象,并在前期可以使用,或对外提供了一个配置文件。前期程序可以直接操作该配置文件,后期的子类只需要将子类名称存入配置文件即可。

    这时就需要动态的获取指定的类并预先创建对象

    就用到了反射机制。重新修改一下应用程序。            class MainBoardDemo{                     public static void main(String[] args){                         MainBoard mb=new MainBoard();                         File file=new File("conf.txt");                         BufferenReader buff = new BufferenReader(new FileReader(file));                         String className = buff.readLine();                         Class clazz = Class.forName(className);                         PCI p = (PCI)clazz.newInstance();                         mb.usePCI(p);                         }                 }

  • 配置文件conf.txt

         当后期出现网卡或者声卡的时候,只需要将该子类的全类名存入配置文件即可, 源程序不需要进行修改

         在该例中,可以了解,反射给我们的程序带来了很强的扩展性。

  • 八、反射的作用-框架的概念

    • 比如在反射中,调用一个未知类的main(),未知类是后来的。这个反射就实现了一个小框架。
    • 框架是提前做好的,框架调用用户的类,就像房子是框架,新门是用户类。
    • 反射做的框架有个好处:将来的类可以调用以前的类。框架不需要知道将来的类叫什么。

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

     


  • 原创粉丝点击
    热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝付款显示支付宝账号异常怎么办 手机老卡换新卡淘宝付不了款怎么办 淘宝买东西退款卖家拒绝退款怎么办 淘宝店铺收藏图片怎么点不了怎么办 手机淘宝显示用户被限制登录怎么办 淘宝设置登录密码原密码忘了怎么办 斑马智行淘宝号换没法登录了怎么办 淘宝卖家手机版显示宝贝不全怎么办 在电脑上登的淘宝账号退不了怎么办 淘宝买家退款不退货写假货怎么办 淘宝卖家已发布商品没货了怎么办 京东换货附近没有京东自提点怎么办 一直显示手机淘宝已停止运行怎么办 唯品会买了不可以退货的衣服怎么办 淘宝店卖东西邮费太贵怎么办 支付宝登录上去必须手机验证怎么办 支付宝里的钱被盗了怎么办 淘宝绑定的支付宝账号忘记了怎么办 支付宝绑定的微博账号忘记了怎么办 怎么知道自己的淘宝密码忘了怎么办 更换扣扣头像图片太大放不下怎么办 每次登入淘宝都要手机验证码怎么办 手机停机收不到唯品会验证码怎么办 魅蓝手机账户密码忘了怎么办 支付宝登录失败请稍后再试怎么办 万王之王3d限制注册了怎么办 绑定手机号无法登陆以前微信怎么办 手机号注册了淘宝如果不用了怎么办 淘宝网登陆要手机验证码怎么办 手机清理了微信图片打不开了怎么办 到淘宝网买东西卖家拒绝退货怎么办 淘宝店铺检测出他人认证图片怎么办 文件过大无法复制到u盘怎么办 淘宝账号上不去总说网络不好怎么办 手机上登录微信一直闪退怎么办 京东账号手机号换了登陆不了怎么办 对方账号停止收款我们汇了款怎么办 淘宝店铺严重违规被扣12分怎么办 中国网银登陆不会自动弹出怎么办 高考报考的时候页面无法显示怎么办 如果卖家收到货不退款怎么办