欢迎访问成都北大青鸟天府校区~

  1. 加入收藏
  2. 设为主页

三分钟了解北大青鸟

×
当前位置: 主页 > 行业新闻 > IT技术讨论 >
  • 北大青鸟大数据课程
  • 北大青鸟网络工程师
  • 北大青鸟web设计专业
  • 北大青鸟云计算专业
  • 北大青鸟启蒙星课程

Java反射

来源:未知发布时间:2013-08-02 16:34

在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 Class<T>Java当中每一个对象都会有一个与之关联的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 {

Class<?> classType = 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 {

Class<?> classType = 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。
申请免费试学】【在线报名在线咨询

本文地址:
文章标题:

热点关注

×