苏州北大青鸟|电脑人才培训中心『官方网站』

高中生毕业了做什么?高中生学什么好 苏州北大青鸟、苏州北大青鸟学费、苏州北大青鸟地址
ACCP7.0培训-入手最快 JAVA培训—收入最高 .NET培训—就业面最宽 网络营销培训—需求量最大
高中毕业学什么好 大学生找不到工作怎么办 学什么技术有前途(好转行) 初中(中专)毕业学什么好
当前位置: 主页 > 青鸟百科 >

北大青鸟:JAVA语言的反射机制

时间:2013-07-07 13:43来源:北大青鸟苏州电脑人才 作者:北大青鸟苏州电脑人才 点击:

  在Java运行时环境中,对于任意一个类能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射机制(Reflection)。

  Java反射机制主要提供一下功能。

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

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

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

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

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

  一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。

  尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是:“反射、映像、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class的能力(the ability of the program to examine itself)”被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

  在JDK中,主要由以下类来实现Java反射机制,这些类位于java.lang.reflect包中。

  Class类:代表一个类。

  File类:代表类的成员变量(成员变量也成为类的属性)

  Method类:代表类的方法。

  Construtor类:代表类的构造方法

  Arry类:提供了动态创建数组,以及访问数组的元素的静态方法。

  Class ClassJava当中每一个对象都会有一个与之关联的class对象,这个class对象是唯一的。这个class对象是在JDK启动的时候就加载进来的,那么他是我们反射的入口点。

  newInstance()

  Creates a new instance of the class represented by this Class object.

  创建一个新的实例,是由这个Class对象所代表的那个类的实例

  Class Method:对于我在类中定义的任意一个方法都会有一个与之关联的Method对象,这个Method会获得这个方法的所有信息,除了方法定义之外,其他都能获得。

  Java的每一个类他里面的每一个方法都会有一个与之对应的Method对象,如果要想通过反射来调用这个方法的时候,你就要获得这个方法与之对应的Method对象,获得Method对象之后,就能通过Method对象所代表的那个方法。

  getMethod(String name, Class... parameterTypes)方法

  想获取一个方法通过这个方法的名字和方法的参数(因为有重载所以才要参数)

  invoke(Object obj, Object... args)

  返回一个Object类型,其实就是方法的返回类型(引用(int--integer))

  代码实例

  package com.test;

  import java.lang.reflect.Method;

  public class InvokeTester {

  public int add(int param1, int param2) {

  return param1 + param2;

  }

  public String echo(String msg) {

  return "hello:" + msg;

  }

  public static void main(String[] args) throws Exception {

  ClassclassType = InvokeTester.class;

  // 获得InvokeTester类所对应的Class对象

  Object invokeTester = classType.newInstance();

  // 以上两行代码等价于

  // InvokeTester it = new InvokeTester();

  Method addMethod = classType.getMethod("add", int.class, int.class);

  // 这个Method对象就等价于add方法

  Object result = addMethod.invoke(invokeTester, new Object[]{100,200});

  //以上两行代码等价于it.add(100,200);

  System.out.println((Integer) result);

  Method echoMethod = classType.getMethod("echo",

  new Class[] { String.class });

  //以上两行代码等价于it.echo("hello");

  Object result2 = echoMethod.invoke(invokeTester, new Object[]{"hello"});

  System.out.println((String)result2);

  }

  }

  getConstructor(Class... parameterTypes)

  获得某个特定的构造方法所对应的对象,在通过构造方法Constructor的newInstance(Object... initargs)方法生成类的实例

  getDeclaredFields()获得对象的所有属性,每个属性对应一个Field对象

  实例2package com.test;

  import java.lang.reflect.Field;

  import java.lang.reflect.Method;

  public class ReflectTester {

  public Object copy(Object object) throws Exception {

  ClassclassType = object.getClass();

  System.out.println("Class:" + classType.getName());

  // 通过默认构造方法创建一个新的对象

  Object objectCopy = classType.getConstructor(new Class[] {})

  .newInstance(new Object[] {});

  // 上面这行代码等价于Object objectCopy2 = classType.newInstance();这个是唯一的,

  // 使用默认的构造方法,而这里使用的则是万能的,能通过不同的构造方法实例对象

  // 而且getConstructor方法和newInstance方法的参数个数和类型一定要匹配

  // 先是构造方法的参数类型,然后是实例对象为构造方法传的真实参数

  // 获得对象的所有属性

  Field fields[] = classType.getDeclaredFields();

  for (int i = 0; i < fields.length; i++) {

  Field field = fields[i];

  String fieldName = field.getName();

  String firstLetter = fieldName.substring(0, 1).toUpperCase();

  // 获得和属性对应的getXXX()方法的名字

  String getMethodName = "get" + firstLetter + fieldName.substring(1);

  // 获得和属性对应的setXXX()方法的名字

  String setMethodName = "set" + firstLetter + fieldName.substring(1);

  // 获得和属性对应的getXXX()方法

  Method getMethod = classType.getMethod(getMethodName,

  new Class[] {});

  // 获得和属性对应的setXXX()方法

  Method setMethod = classType.getMethod(setMethodName,

  new Class[] { field.getType() });

  // 调用原对象的getXXX()方法

  Object value = getMethod.invoke(object, new Object[] {});

  System.out.println(fieldName + ":" + value);

  // 调用拷贝对象的setXXX()方法

  setMethod.invoke(objectCopy, new Object[] { value });

  }

  return objectCopy;

  }

  public static void main(String[] args) throws Exception {

  Customer customer = new Customer("Tom", 21);

  customer.setId(new Long(1));

  Customer customerCopy = (Customer) new ReflectTester().copy(customer);

  System.out.println("Copy information:" + customerCopy.getId() + " "

  + customerCopy.getName() + " " + customerCopy.getAge());

  }

  }

  class Customer {

  private Long id;

  private String name;

  private int age;

  public Customer() {

  }

  public Customer(String name, int age) {

  this.name = name;

  this.age = age;

  }

  public Long getId() {

  return id;

  }

  public void setId(Long id) {

  this.id = id;

  }

  public String getName() {

  return name;

  }

  public void setName(String name) {

  this.name = name;

  }

  public int getAge() {

  return age;

  }

  public void setAge(int age) {

  this.age = age;

  }

  }

  通过反射操作一维数组

  public static void main(String args[]) throws Exception

  {

  Class classType = Class.forName("java.lang.String");

  // 创建一个长度为10的字符串数组

  Object array = Array.newInstance(classType, 10);

  // 把索引位置为5的元素设为"hello"

  Array.set(array, 5, "hello");

  // 获得索引位置为5的元素的值

  String s = (String) Array.get(array, 5);

  System.out.println(s);

  }

  Class class十分特殊,他和一般的classes一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive、Java types

  (boolean,byte,char,short,int,long,float,double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM便自定产生一个Class object。如果你想借由“修改Java标准库源码”来观察Class object的实际生成时机(例如在Class的constructor内添加一个println(),不能够!因为Class并没有public constructor)

  Class是Reflection起源。针对任何你想探勘的class,唯有先为他产生一个cClass object,接下来才能经由后者唤起为数十多个的Reflection APIS。(北大青鸟苏州电脑人才)
 


标签:

(原文标题:北大青鸟:JAVA语言的反射机制

(责任编辑:苏州北大青鸟



相关新闻

更多
分享按钮
------分隔线----------------------------
招生专题