反射除了可以取得一个类的完整结构外,还可以调用类中指定的方法或指定的属性,并且可以通过反射完成对数组的操作
定义一个类Person
package com.ReflectDemo;
interface Information{ // 定义Information接口
public static final String NATIONAL = "China" ; // 定义全局常量
public static final String AUTHOR = "张三" ; // 定义全局常量
public void sayChina() ; // 无参的,没有返回值的方法
public String sayHello(String name,int age) ; // 定义有两个参数的方法,并返回内容
}
public class Person implements Information{
private String name ;
private int age ;
public Person(){ // 无参构造
}
public Person(String name){
this.name = name ; // 设置name属性
}
public Person(String name,int age){
this(name) ;
this.age = age ;
}
public void sayChina(){ // 覆写方法
System.out.println("作者:" + AUTHOR + ",国籍:" + NATIONAL) ;
}
public String sayHello(String name,int age){
return "您好,我叫" + name + ",我今年:" + age + "岁了!" ;
}
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
};
一 、通过反射调用类中的方法
- 通过Class类的 getMethod() 方法取得一个Method 对象,并设置此方法操作时所需要的参数类型
- 使用 invoke 进行调用,并向方法中传递要设置的参数
下面代码调用Person类的 sayChina() 方法
package com.ReflectDemo;
import java.lang.reflect.Method ;
public class InvokeSayChinaDemo{
public static void main(String args[]){
Class<?> c1 = null ;
try{
c1 = Class.forName("com.ReflectDemo.Person") ; // 实例化Class对象
}catch(Exception e){}
try{
Method met = c1.getMethod("sayChina") ; // 找到sayChina()方法,此方法没有参数
met.invoke(c1.newInstance()) ; // 调用方法,传递对象实例
}catch(Exception e){
e.printStackTrace() ;
}
}
};
程序运行结果:
下面代码调用Person类的 sayHello() 方法,传递两个参数
package com.ReflectDemo;
import java.lang.reflect.Method ;
public class InvokeSayHelloDemo{
public static void main(String args[]){
Class<?> c1 = null ;
try{
c1 = Class.forName("com.ReflectDemo.Person") ; // 实例化Class对象
}catch(Exception e){}
try{
Method met = c1.getMethod("sayHello",String.class,int.class) ; // 找到sayChina()方法,两个参数的类型
String rv = null ;
rv = (String)met.invoke(c1.newInstance(),"张三",20) ; // 调用方法,传递实例以及两个参数值
System.out.println(rv) ;
}catch(Exception e){
e.printStackTrace() ;
}
}
};
程序运行结果:
二 、调用 getter 及 setter 方法
package com.ReflectDemo;
import java.lang.reflect.Method;
public class InvokeSetGetDemo {
public static void main(String[] args) {
Class<?> c1 = null; //声明Class对象
Object obj = null; //声明一个对象
try {
c1 = Class.forName("com.ReflectDemo.Person"); //实例化Class对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
obj = c1.newInstance(); //实例化操作对象
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
setter(obj,"name","张三",String.class); //调用setter方法
setter(obj,"age",20,int.class); //调用setter方法
System.out.print("姓名:");
getter(obj,"name"); //调用getter方法
System.out.print("年龄:");
getter(obj,"age"); //调用getter方法
}
/**
*
* @param obj 操作的对象
* @param att 操作的属性
* @param value 设置的属性值
* @param type 属性参数的类型
*/
public static void setter(Object obj,String att,Object value,Class<?> type){
try {
Method method = obj.getClass().getMethod("set" + upperFirstWord(att),type); //设置方法的参数类型
method.invoke(obj,value); //调用方法
} catch (Exception e) {
e.printStackTrace();
}
}
public static void getter(Object obj,String att){
try {
Method method = obj.getClass().getMethod("get" + upperFirstWord(att));
System.out.println(method.invoke(obj));
} catch (Exception e) {
e.printStackTrace();
}
}
public static String upperFirstWord(String word){ //单词首字母大写
String str = word.substring(0,1).toUpperCase() + word.substring(1);
return str;
}
}
程序运行结果:
三 、通过反射操作属性
package com.ReflectDemo;
import java.lang.reflect.Field;
public class InvokeFieldDemo {
public static void main(String[] args) throws Exception {
Class<?> c1 = null; //声明Class对象
Object obj = null; //声明一个对象
c1 = Class.forName("com.ReflectDemo.Person"); //实例化Class对象
obj = c1.newInstance(); //实例化操作对象
Field nameField = null; //表示name属性
Field ageField = null; //表示age属性
nameField = c1.getDeclaredField("name"); //取得name属性
ageField = c1.getDeclaredField("age"); //取得age属性
nameField.setAccessible(true); //在Person类中,name属性为private修饰封装,此处将name属性设置可被外部访问
nameField.set(obj,"张三"); //设置name属性的内容
ageField.setAccessible(true); //在Person类中,age属性为private修饰封装,此处将age属性设置可被外部访问
ageField.set(obj,20); //设置age属性的内容
System.out.println("姓名:" + nameField.get(obj)); //通过get取得属性内容
System.out.println("年龄:" + ageField.get(obj)); //通过get取得属性内容
}
}
程序运行结果:
注意:使用反射操作属性时,最好通过setter 和 getter方法。
以上程序是在扩大类属性的访问权限后直接操作属性,所以在Person类的并不需要setter及getter方法,但是在开发中,还是要通过setter及getter方法来操作属性。以上操作作为了解即可。
四 、通过反射操作数组
反射机制不仅应用在类上,也可以应用在引用数据类型数据上。
Class类中定义了getComponentType() 方法:
java.lang.reflect 包下的Array类提供静态方法来动态创建和访问Java数组:
1 、取得数组信息并修改数组内容
package com.ReflectDemo;
import java.lang.reflect.Array;
public class ClassArrayDemo {
public static void main(String[] args) throws Exception {
int temp[] = { 1,2,3 }; //声明一个整型数组
Class<?> arrObj = temp.getClass().getComponentType(); //取得数组的Class对象
System.out.println("类型:" + arrObj.getName()); //取得数组类型名称
System.out.println("长度:" + Array.getLength(temp)); //取得数组长度
System.out.println("第一个内容:" + Array.get(temp,0)); //取得数组第一个内容
Array.set(temp,0,6); //修改数组第一个内容
System.out.println("修改后的数组第一个的内容:" + Array.get(temp,0)); //取得修改后的数组第一个的内容
}
}
程序运行结果:
2 、修改数组的大小
package com.ReflectDemo;
import java.lang.reflect.Array;
public class ChangeArrayDemo {
public static void main(String[] args) throws Exception{
int temp[] = { 1,2,3} ; //声明一个整型数组
int newTemp[] = (int[]) arrayIncrease(temp, 5); //调用方法,改变数组长度
print(newTemp); //打印输出数组信息
System.out.println("\n---------------"); //换行
String t[] = { "hello","world","java" }; //声明一个字符串数组
String nt[] = (String[]) arrayIncrease(t, 8); //调用方法,改变数组长度
print(nt); 打印输出数组信息
}
public static Object arrayIncrease(Object temp,int length){ //改变数组长度
Class<?> c = temp.getClass(); //获取运行时的类
Class<?> arr = c.getComponentType(); //获取数组的Class对象
Object newArr = Array.newInstance(arr, length); //重新开辟新的数组大小
int arrLength = Array.getLength(temp); //获取数组长度
System.arraycopy(temp,0,newArr,0,arrLength); //复制数组内容
return newArr;
}
public static void print(Object temp){
Class<?> c = temp.getClass();
if(!c.isArray()){
return;
}
Class<?> arr = c.getComponentType();
System.out.println(arr.getName() + "数组的长度是:" + Array.getLength(temp));
for (int i = 0; i < Array.getLength(temp); i++) {
System.out.print(Array.get(temp,i) + "、");
}
}
}
程序运行结果: