正常访问java类的方式是先导入要访问的类所在的包,然后实例化对象,最后调用包里面的方法。但是有时候也会存在这样的情况,你需要的类所在的包并不在你的开发套件(SDK)中,而且你也不能把相关的包导入到你的开发工程当中来,但是你又必须要使用这个包中的相关类。有没有一种方式可以在不需要包的情况下也能访问包中的类呢,在这种情况下就可以使用反射机制。关于反射机制的具体原理可以参考相关的书籍和文章,本文主要举几个小例子来说明一下反射机制的使用方法。
一、使用的一般步骤
a、获得指定的类
b、获得类中需要调用的方法
c、实例化对象 (如果是调用静态方法,不要实例化对象)
d、设置对象的属性 (这一步可以根据情况来决定是否需要设置对象的属性)
e、调用获得的方法
基本开发环境:
操作系统:Ubuntu12.04
JDK版本:java version "1.7.0_101"
二、反射机制的几种使用情景
1、访问类中静态方法
在指定类中实现两个静态方法,然后通过反射机制来获取这两个静态方法并调用它们。在这里定义两个类,一个类为cn/edu/syau/Demo.java,这个类中定义需要访问的方法和属性等;一个类为Reflect.java,在这个类中实现反射机制来访问Demo类中方法和属性。
Demo.java内容如下:
package cn.edu.syau;
/* Define a Demo class */
public class Demo {
/* Define a static method */
public static void printString(String str) {
System.out.println(str);
}
public static void printHello() {
System.out.println("Hello,world!");
}
}
Reflect.java的内容如下:
import java.lang.reflect.Method;
public class Reflect {
public static void main(String args[]) throws Exception{
/* 1 get class */
Class<?> cls = Class.forName("cn.edu.syau.Demo");
/* 2 get method */
Method printStr = cls.getMethod("printString", String.class);
Method printHello = cls.getMethod("printHello");
/* 3 create object */
/* 4 call method */
printStr.invoke(null, "TECH-PRO"); /* call printString method */
printHello.invoke(null); /* call printHello method */
}
}
编译上面这个程序的具体命令:
javac cn/edu/syau/Demo.java
javac Reflect.java
java Reflect
通过分析,可以看出调用Demo类中两个静态方法,结果如下:
2、访问类中的普通方法
在Demo类中实现两个普通方法,Demo类如下所示:
package cn.edu.syau;
/* Define a Demo class */
public class Demo {
/* Define a static method */
public void printString(String str) {
System.out.println(str);
}
public void printHello() {
System.out.println("Hello,world!");
}
}
在Reflect类中页要进行相应的修改,内容如下:
import java.lang.reflect.Method;
public class Reflect {
public static void main(String args[]) throws Exception{
/* 1 get class */
Class<?> cls = Class.forName("cn.edu.syau.Demo");
/* 2 get method */
Method printStr = cls.getMethod("printString", String.class);
Method printHello = cls.getMethod("printHello");
/* 3 create object */
Object obj = cls.newInstance();
/* 4 call method */
printStr.invoke(obj, "TECH-PRO"); /* call printString method */
printHello.invoke(obj); /* call printHello method */
}
}
运行结果如下:
3、访问类实例化通过带参构造函数
Demo类的具体实现如下:
package cn.edu.syau;
/* Define a Demo class */
public class Demo {
private String name = null;
private int age = 0;
/* Define a constructor method with parameters */
public Demo(String name, int age) {
this.name = name;
this.age = age;
}
/* Define a print informations method */
public void printInfo() {
System.out.println("name : " + this.name);
System.out.println("age : " + this.age);
}
}
Reflect类的实现如下:
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
public class Reflect {
public static void main(String args[]) throws Exception{
/* 1 get class */
Class<?> cls = Class.forName("cn.edu.syau.Demo");
/* 2 get method */
Method printInfo = cls.getMethod("printInfo");
/* 3 create object */
Constructor<?> con = cls.getConstructor(String.class, int.class); /* get constructor metho */
Object obj = con.newInstance("TECH-PRO", 25); /* create obj */
/* 4 call method */
printInfo.invoke(obj); /* call printInfo method */
}
}
运行结果如下:
4、设置、访问类中的属性
访问类中的属性有两种方式,一种是通过setter/getter方法来设置,第二种是直接获得属性并进行设置。
4.1 通过getter/setter方法
Demo类的定义如下:
package cn.edu.syau;
/* Define a Demo class */
public class Demo {
private String name = null;
private int age = 0;
/* Define a empty constructor method */
public Demo(){}
/* Define a constructor method with parameters */
public Demo(String name, int age) {
this.name = name;
this.age = age;
}
/* Define a print informations method */
public void printInfo() {
System.out.println("name : " + this.name);
System.out.println("age : " + this.age);
}
/* define setter and getter methods */
public void setAge(int age){this.age = age;}
public int getAge(){return this.age;}
public void setName(String name){this.name = name;}
public String getName(){return this.name;}
}
Reflect类的实现如下:
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
public class Reflect {
public static void main(String args[]) throws Exception{
/* 1 get class */
Class<?> cls = Class.forName("cn.edu.syau.Demo");
/* 2 get method */
Method printInfo = cls.getMethod("printInfo");
Method setName = cls.getMethod("setName", String.class);
Method setAge = cls.getMethod("setAge", int.class);
/* 3 create object */
Object obj = cls.newInstance();
/* 4 call method */
setName.invoke(obj, "TECH-PRO"); /* call setName method */
setAge.invoke(obj, 25); /* call setAge method */
printInfo.invoke(obj); /* call printInfo method */
}
}
编译运行结果如下:
4.2 直接对属性进行设置和访问
Demo类的实现和4.1相同,Reflect类的具体实现如下:
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Reflect {
public static void main(String args[]) throws Exception{
/* 1 get class */
Class<?> cls = Class.forName("cn.edu.syau.Demo");
/* 2 get method */
Method printInfo = cls.getMethod("printInfo");
/* 3 create object */
Object obj = cls.newInstance();
/* 4 set member values */
Field name = cls.getDeclaredField("name"); /* get private field */
Field age = cls.getDeclaredField("age");
name.setAccessible(true); /* set field access is public */
age.setAccessible(true);
name.set(obj, "TECH-PRO"); /* set name's value */
age.set(obj, 25); /* set age's value */
/* 5 call method */
printInfo.invoke(obj); /* call printInfo method */
}
}
编译运行结果如下: