zoukankan      html  css  js  c++  java
  • Java 反射机制

    根据李兴华的视频整理的

    大致是先得到Class的类的对象,然后在用这个对象调用newInstance方法创建实例,就可以对实例进行操作了

    Java反射的源头是Class这个类:

    public final class Class<T>extends Objectimplements Serializable, GenericDeclaration, Type, AnnotatedElement

    Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(booleanbytecharshortintlongfloatdouble)和关键字 void 也表示为 Class 对象。

    Class 没有公共构造方法Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

    以下示例使用 Class 对象来显示对象的类名:

         void printClassName(Object obj) {
             System.out.println("The class of " + obj +
                                " is " + obj.getClass().getName());
         }
    

     实例化Class对象有3中方法:

    1、Class.forName()

    public static Class<?> forName(String className)
                            throws ClassNotFoundException

    返回与带有给定字符串名的类或接口相关联的 Class 对象。

    这个最常用啦,比如说java连接数据库加载驱动时:Class.forName("com.mysql.jdbc.Driver") ;  字符串为 包名.类名

    2、类名.class

    3、对象.getClass()

    得到Class类的对象后就可以调用newInstance方法创建实例啦

    public T newInstance()
                  throws InstantiationException,
                         IllegalAccessException
    创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。如果该类尚未初始化,则初始化这个类。 

    注意:类中必须提供无参构造函数(如果不写构造函数,那么类本身就提供无参构造函数,如果写了构造函数,那么那个默认的就没有了),而且那个构造函数还得是可以访问的,如果是私有的话,那就不行啦

     1 package yxy;
     2 
     3 class Person{
     4     private String name;
     5     public String getName() {
     6         return name;
     7     }
     8 
     9     public void setName(String name) {
    10         this.name = name;
    11     }
    12     private Person(){
    13         this.setName("crane");
    14     }
    15     
    16     public String toString(){
    17         return "name= "+this.getName();
    18     }
    19 }
    20 
    21 public class Test {
    22     
    23     public static void main(String[] args) {
    24         // TODO Auto-generated method stub
    25         try {
    26             System.out.println(Class.forName("yxy.Person").newInstance());
    27         } catch (InstantiationException e) {
    28             // TODO Auto-generated catch block
    29             e.printStackTrace();
    30         } catch (IllegalAccessException e) {
    31             // TODO Auto-generated catch block
    32             e.printStackTrace();
    33         } catch (ClassNotFoundException e) {
    34             // TODO Auto-generated catch block
    35             e.printStackTrace();
    36         }
    37     }
    38 
    39 
    40 }
    java.lang.IllegalAccessException: Class yxy.Test can not access a member of class yxy.Person with modifiers "private"
        at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
        at java.lang.Class.newInstance(Unknown Source)
        at yxy.Test.main(Test.java:26)

    如果把12行改为public Person(){

    则运行结果为:name= crane

    如果是带参的可访问的构造函数也是不行的,

    不过可以用getConstructors来整(有点儿像病句哇)

    getConstructors()返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。

     1 package yxy;
     2 
     3 import java.lang.reflect.Constructor;
     4 
     5 class Person{
     6     private String name;
     7     public String getName() {
     8         return name;
     9     }
    10 
    11     public void setName(String name) {
    12         this.name = name;
    13     }
    14     public Person(){
    15         this.setName("crane");
    16     }
    17     public Person(String name){
    18         this.setName(name);
    19     }
    20     public String toString(){
    21         return "name= "+this.getName();
    22     }
    23 }
    24 
    25 public class Test {
    26     
    27     public static void main(String[] args) throws Exception {
    28         // TODO Auto-generated method stub
    29         Class<?> c=null;
    30         c=Class.forName("yxy.Person");
    31         Constructor<?>[] cons=null;
    32         cons=c.getConstructors();
    33         Person person=null;
    34         //输出所有公有构造函数,私有的是不能得到的
    35         for(Constructor<?> con:cons){
    36             System.out.println(con);
    37         }
    38         person=(Person) cons[1].newInstance("crane");
    39         System.out.println(person);
    40     }
    41 }

    运行结果:

    public yxy.Person()
    public yxy.Person(java.lang.String)
    name= crane

     呃,震惊了,私有属性和方法的也可以通过反射被看到:http://www.pengtaoblog.cn/article.asp?id=721

    呃,原来这个人写的都有啦:http://www.cnblogs.com/octobershiner/archive/2012/03/18/2404751.html  这是个好文章

    还有个好文章哇:候捷谈Java反射机制http://www.cppblog.com/javenstudio/articles/24640.html

    禁止反射http://bbs.csdn.net/topics/390472034?page=1#post-394609835

    反射的应用场景:http://bbs.itheima.com/thread-88932-1-1.html

    第一讲    反射的应用场景
    一、概述
    反射技术:
            Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
            简单一句话:反射技术可以对类进行解剖。
     
    二、应用场景
            一个已经可以使用的应用程序,因为程序已经做好可以运行使用,不能再进行代码的加入了。而当后期我们新的功能加入程序时,该怎么做呢?就如我们的电脑一样,后期我们可能会鼠标、键盘等,所以电脑给我们预留了usb接口,只要符合这个接口规则的设备,电脑就可以通过加载驱动等操作来使用。
            那这个程序能用了,如何使用后期出现的功能类呢?
            常用的作法,会提供一个配置文件,来供以后实现此程序的类来扩展功能。对外提供配置文件,让后期出现的子类直接将类名字配置到配置文件中即可。该应用程序直接读取配置文件中的内容。并查找和给定名称相同的类文件。进行如下操作:
            1)加载这个类。
            2)创建该类的对象。
            3)调用该类中的内容。
           应用程序使用的类不确定时,可以通过提供配置文件,让使用者将具体的子类存储到配置文件中。然后该程序通过反射技术,对指定的类进行内容的获取。
            好处:反射技术大大提高了程序的扩展性。

    更加详细的:http://blog.csdn.net/benjaminzhang666/article/details/9408611

    crane:SSH框架中都用到了反射机制(读配置文件获得类名,然后进行反射操作)

    《Effective Java》中文版第2版第53条中有说到反射机制的注意事项,

    反射是在运行时执行的,丧失了编译时类型检查的好处,包括异常检查,如果程序反射的调用不存在的方法,在运行时会失败,除非采取了特别的预防措施。

    详情参看那本书

  • 相关阅读:
    服务器的Redis连接不上解决方案
    给大家推荐一个很好的自学网站
    简单说下HashMap的实现原理
    LinkedList源码解析
    你要了解的jvm
    单例设计
    百度编辑器删除旧的图片
    Ueditor 单图、多图、视频、附件的上传及在线管理总结
    上传新图片删除旧图片
    webapi发布IIS时出现500.19错误:不能在此路径中使用此配置节。如果在父级别上锁定了该节,便会出现这种情况。锁定是默认设置的(overrideModeDefault="Deny")或者是通过包含overrideModeDefault="Deny"....
  • 原文地址:https://www.cnblogs.com/crane-practice/p/3671952.html
Copyright © 2011-2022 走看看