Java反射机制

一、什么是JAVA的反射机制

  Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection? APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public,?static? 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。

  Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes。

  换言之,Java可以加载一个运行时才得知名称的class,获得其完整结构。

  二、JDK中提供的Reflection?API

  Java反射相关的API在包java.lang.reflect中,JDK?1.6.0的reflect包如下图:

  #FormatImgID_0#

  Member接口该接口可以获取有关类成员(域或者方法)后者构造函数的信息。

  AccessibleObject类该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认? Java?语言访问控制检查的能力。

  Array类该类提供动态地生成和访问JAVA数组的方法。

  Constructor类提供一个类的构造函数的信息以及访问类的构造函数的接口。

  Field类提供一个类的域的信息以及访问类的域的接口。

  Method类提供一个类的方法的信息以及访问类的方法的接口。

  Modifier类提供了?static?方法和常量,对类和成员访问修饰符进行解码。

  Proxy类提供动态地生成代理类和类实例的静态方法。

  三、JAVA反射机制提供了什么功能

  Java反射机制提供如下功能:

  在运行时判断任意一个对象所属的类

  在运行时构造任意一个类的对象

  在运行时判段任意一个类所具有的成员变量和方法

  在运行时调用任一个对象的方法

  在运行时创建新类对象

  在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。

  这里首先定义用于测试的类:

  +?View?Code

  1、获取类的Class对象

  Class?类的实例表示正在运行的?Java?应用程序中的类和接口?;袢±嗟腃lass对象有多种方式:

  调用getClassBoolean?var1?=?true;

  Class?classType2?=?var1.getClass();

  System.out.println(classType2);

  输出:class?java.lang.Boolean

  运用.class?语法Class?classType4?=?Boolean.class;

  System.out.println(classType4);

  输出:class?java.lang.Boolean

  运用static?method?Class.forName()Class?classType5?=? Class.forName("java.lang.Boolean");

  System.out.println(classType5);

  输出:class?java.lang.Boolean

  运用primitive?wrapper?classes的TYPE?语法

  这里返回的是原生类型,和Boolean.class返回的不同Class?classType3?=?Boolean.TYPE;

  System.out.println(classType3);

  输出:boolean

  2、获取类的Fields

  可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。JAVA?的Class类提供了几个方法获取类的属性。

  public?FieldgetField(String?name)返回一个?Field?对象,它反映此?Class? 对象所表示的类或接口的指定公共成员字段

  public?Field[]?getFields()返回一个包含某些?Field?对象的数组,这些对象反映此?Class? 对象所表示的类或接口的所有可访问公共字段

  public?FieldgetDeclaredField(Stringname)返回一个?Field?对象,该对象反映此?Class? 对象所表示的类或接口的指定已声明字段

  public?Field[]?getDeclaredFields()返回?Field?对象的一个数组,这些对象反映此?Class? 对象所表示的类或接口所声明的所有字段

  +?View?Code

  输出:

  public?int?com.quincy.ExtendType.pubIntExtendField

  public?java.lang.String?com.quincy.ExtendType.pubStringExtendField

  public?int?com.quincy.Type.pubIntField

  public?java.lang.String?com.quincy.Type.pubStringField

  public?int?com.quincy.ExtendType.pubIntExtendField

  public?java.lang.String?com.quincy.ExtendType.pubStringExtendField

  private?int?com.quincy.ExtendType.prvIntExtendField

  可见getFields和getDeclaredFields区别:

  getFields返回的是申明为public的属性,包括父类中定义,

  getDeclaredFields返回的是指定类定义的所有定义的属性,不包括父类的。

  3、获取类的Method

  通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法

  Class类提供了几个方法获取类的方法。

  public?MethodgetMethod(String?name,?Class...?parameterTypes)返回一个?Method? 对象,它反映此?Class?对象所表示的类或接口的指定公共成员方法

  public?Method[]?getMethods()返回一个包含某些?Method?对象的数组,这些对象反映此?Class? 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共?member?方法

  public?MethodgetDeclaredMethod(String?name,Class...?parameterTypes)返回一个? Method?对象,该对象反映此?Class?对象所表示的类或接口的指定已声明方法

  public?Method[]?getDeclaredMethods()返回?Method?对象的一个数组,这些对象反映此?Class? 对象表示的类或接口声明的所有方法,包括公共、?;?、默认(包)访问和私有方法,但不包括继承的方法

  +?View?Code

  输出:

  public?void?com.quincy.ExtendType.setIntExtendField(int)

  public?int?com.quincy.ExtendType.getIntExtendField()

  public?void?com.quincy.Type.setIntField(int)

  public?int?com.quincy.Type.getIntField()

  public?final?native?void?java.lang.Object.wait(long)?throws? java.lang.InterruptedException

  public?final?void?java.lang.Object.wait()?throws? java.lang.InterruptedException

  public?final?void?java.lang.Object.wait(long,int)?throws? java.lang.InterruptedException

  public?boolean?java.lang.Object.equals(java.lang.Object)

  public?java.lang.String?java.lang.Object.toString()

  public?native?int?java.lang.Object.hashCode()

  public?final?native?java.lang.Class?java.lang.Object.getClass()

  public?final?native?void?java.lang.Object.notify()

  public?final?native?void?java.lang.Object.notifyAll()

  private?void?com.quincy.ExtendType.Log(java.lang.String)

  public?void?com.quincy.ExtendType.setIntExtendField(int)

  public?int?com.quincy.ExtendType.getIntExtendField()

  4、获取类的Constructor

  通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例

  Class类提供了几个方法获取类的构造器。

  public?Constructor?getConstructor(Class...?parameterTypes)返回一个? Constructor?对象,它反映此?Class?对象所表示的类的指定公共构造方法

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

  public?Constructor?getDeclaredConstructor(Class...? parameterTypes)返回一个?Constructor?对象,该对象反映此?Class?对象所表示的类或接口的指定构造方法

  public?Constructor[]?getDeclaredConstructors()返回?Constructor? 对象的一个数组,这些对象反映此?Class?对象表示的类声明的所有构造方法。它们是公共、?;?、默认(包)访问和私有构造方法

  +?View?Code

  5、新建类的实例

  通过反射机制创建新类的实例,有几种方法可以创建

  调用无自变量ctor1、调用类的Class对象的newInstance方法,该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败.

  Class?classType?=?ExtendType.class;

  Object?inst?=?classType.newInstance();

  System.out.println(inst);

  输出:

  Type:Default?Constructor

  ExtendType:Default?Constructor

  com.quincy.ExtendType@d80be3

  2、调用默认Constructor对象的newInstance方法

  Class?classType?=?ExtendType.class;

  Constructor?constructor1?=?classType.getConstructor();

  Object?inst?=?constructor1.newInstance();

  System.out.println(inst);

  输出:

  Type:Default?Constructor

  ExtendType:Default?Constructor

  com.quincy.ExtendType@1006d75

  调用带参数ctor3、调用带参数Constructor对象的newInstance方法

  Constructor?constructor2?=

  classType.getDeclaredConstructor(int.class,?String.class);

  Object?inst?=?constructor2.newInstance(1,?"123");

  System.out.println(inst);

  输出:

  Type:Default?Constructor

  ExtendType:Constructor?with?parameters

  com.quincy.ExtendType@15e83f9

  6、调用类的函数

  通过反射获取类Method对象,调用Field的Invoke方法调用函数。

  +?View?Code

  7、设置/获取类的属性值

  通过反射获取类的Field对象,调用Field方法设置或获取值

  +?View?Code

  +?View?Code

  四、动态创建代理类

  代理模式:代理模式的作用=为其他对象提供一种代理以控制对这个对象的访问。

  代理模式的角色:

  抽象角色:声明真实对象和代理对象的共同接口

  代理角色:代理角色内部包含有真实对象的引用,从而可以操作真实对象。

  真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

  动态代理:

  java.lang.reflect.ProxyProxy?提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类

  InvocationHandler是代理实例的调用处理程序? 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的?invoke?方法。

  动态Proxy是这样的一种类:

  它是在运行生成的类,在生成时你必须提供一组Interface给它,然后该class就宣称它实现了这些interface。你可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic? Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。

  在使用动态代理类时,我们必须实现InvocationHandler接口

  步骤:

  1、定义抽象角色

  public?interface?Subject?{

  public?void?Request();

  }

  2、定义真实角色

  public?class?RealSubject?implements?Subject?{

  @Override

  public?void?Request()?{

  //?TODO?Auto-generated?method?stub

  System.out.println("RealSubject");

  }

  }

  3、定义代理角色

  public?class?DynamicSubject?implements?InvocationHandler?{

  private?Object?sub;

  public?DynamicSubject(Object?obj){

  this.sub?=?obj;

  }

  @Override

  public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)

  throws?Throwable?{

  //?TODO?Auto-generated?method?stub

  System.out.println("Method:"+?method?+?",Args:"?+?args);

  method.invoke(sub,?args);

  return?null;

  }

  }

  4、通过Proxy.newProxyInstance构建代理对象

  RealSubject?realSub?=?new?RealSubject();

  InvocationHandler?handler?=?new?DynamicSubject(realSub);

  Class?classType?=?handler.getClass();

  Subject?sub?=? (Subject)Proxy.newProxyInstance(classType.getClassLoader(),

  realSub.getClass().getInterfaces(),?handler);

  System.out.println(sub.getClass());

  5、通过调用代理对象的方法去调用真实角色的方法。

  sub.Request();

  输出:

  class?$Proxy0?新建的代理对象,它实现指定的接口

  Method:public?abstract?void?DynamicProxy.Subject.Request(),Args:null

  RealSubject?调用的真实对象的方法

Java交流裙:109--1181--875

java-数据类型

http://www.makeru.com.cn/live/1394_203.html?s=156461

常用工具类

http://www.makeru.com.cn/live/1394_253.html?s=156461

javaweb后端开发案例

http://www.makeru.com.cn/live/1394_366.html?s=156461

http://www.makeru.com.cn/live/1394_365.html?s=156461

?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,172评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,346评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,788评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,299评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,409评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,467评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,476评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,262评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,699评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,994评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,167评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,499评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,149评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,387评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,028评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,055评论 2 352