您的位置:首页 > 编程语言 > Java开发

Java学习之反射机制笔记--4

2016-05-19 11:47 573 查看
4、Java反射机制深入研究

1)通过反射调用类中的方法

在正常情况下,一个类的对象产生后,就可以调用这个类的方法;如果要调用的话,则必须要知道要调用的方法名是什么,之后通过Class类的getMethod()方法,得到一个Method对象,之后调用Method对象来执行此方法,但是,在调用方法的时候,会牵扯到方法中的参数问题,所以通过getMethod得到的对象,必须设置好需要的参数类型

package com.reflection.demo4;
import java.lang.reflect.Method ;
public class InvokeSayChinaDemo{
public static void main(String args[]){
Class<?> c1 = null ;
try{
c1 = Class.forName("com.reflection.demo4.Person") ;	// 实例化Class对象
}catch(Exception e){}
try{
Method  met = c1.getMethod("sayChina") ;	// 找到sayChina()方法
met.invoke(c1.newInstance()) ;	// 调用方法
}catch(Exception e){
e.printStackTrace() ;
}
}
};


作者:李兴华,国籍:China

调用sayChina方法,执行调用的是invoke方法,执行的时候,还需要传递参数进去,而且需要实例化对象
如果要调用的方法中有参数,则必须设置参数的类型及内容

package com.reflection.demo4;
import java.lang.reflect.Method ;
public class InvokeSayHelloDemo{
public static void main(String args[]){
Class<?> c1 = null ;
try{
c1 = Class.forName<span style="font-family:SimSun;">("com.reflection.demo4.Person") ;	// 实例化Class对象</span>
}catch(Exception e){}
try{
Method  met = c1.getMethod("sayHello",String.class,int.class) ;	// 找到sayChina()方法
String rv = null ;
rv = (String)met.invoke(c1.newInstance(),"李兴华",30) ;	// 调用方法
System.out.println(rv) ;
}catch(Exception e){
e.printStackTrace() ;
}
}
};
李兴华,你好!我今年:30岁了!

2)通过反射调用类中的setter和getter

setter和getter是标准的属性访问方法,如果一个类的属性被封装,则必须通过setter和getter方法设置和取得,实际上此方法的操作之所以这样规定,主要是由于反射机制给予支持造成的。

通过反射,可以调用setter和getter

如果想调用setter,例如name属性设置,即setName()方法写,方法的第二个单词的首字母要大写,

package com.reflection.demo4;
import java.lang.reflect.Method ;
public class InvokeSetGetDemo{
public static void main(String args[]){
Class<?> c1 = null ;
Object obj = null ;
try{
c1 = Class.forName("com.reflection.demo4.Person") ;	// 实例化Class对象
}catch(Exception e){}
try{
obj = c1.newInstance() ;
}catch(Exception e){}
setter(obj,"name","李兴华",String.class) ;	// 调用setter方法
setter(obj,"age",30,int.class) ;	// 调用setter方法
System.out.print("姓名:") ;
getter(obj,"name") ;
System.out.print("年龄:") ;
getter(obj,"age");
}
/**
Object obj:要操作的对象
String att:要操作的属性
Object value:要设置的属性内容
Class<?> type:要设置的属性类型
*/
public static void setter(Object obj,String att,Object value,Class<?> type){
try{
Method met = obj.getClass().getMethod("set"+initStr(att),type) ;	// 得到setter方法
met.invoke(obj,value) ;	// 设置setter的内容
}catch(Exception e){
e.printStackTrace() ;
}
}
public static void getter(Object obj,String att){
try{
Method met = obj.getClass().getMethod("get"+initStr(att)) ;	// 得到setter方法
System.out.println(met.invoke(obj)) ;	// 调用getter取得内容
}catch(Exception e){
e.printStackTrace() ;
}
}
public static String initStr(String old){	// 将单词的首字母大写方法
String str = old.substring(0,1).toUpperCase() + old.substring(1) ;
return str ;
}
};
姓名:李兴华

年龄:30

3)通过反射操作属性

如果要操作一个类中的属性,则可以通过getField()来完成

package com.reflection.demo4;
import java.lang.reflect.Field ;
public class InvokeFieldDemo{
public static void main(String args[]) throws Exception{
Class<?> c1 = null ;
Object obj = null ;
c1 = Class.forName("com.reflection.demo4.Person") ;	// 实例化Class对象
obj = c1.newInstance() ;
Field nameField = null ;
Field ageField = null ;
nameField = c1.getDeclaredField("name") ;	// 取得name属性
ageField = c1.getDeclaredField("age") ;	// 取得name属性
nameField.setAccessible(true) ;	// 此属性对外部可见
ageField.setAccessible(true) ;	// 此属性对外部可见
nameField.set(obj,"小米") ;	// 设置name属性内容
ageField.set(obj,3) ;			// 设置age属性内容
System.out.println("姓名:" + nameField.get(obj)) ;
System.out.println("年龄:" + ageField.get(obj)) ;
}
};


在访问私有属性的时候,必须让属性可见,设置属性可见---属性.setAccessible(true)

4)通过反射操作数组

反射不光可以应用在类上,也可以应用在任何引用数据类型上,包括数组,数组使用Array类完成

Class类中存在一个方法:getComponentType()返回一个数组

得到数组指定下标的内容Array.get(Object arr,int index)

修改数组指定下标的内容Array.get(Object arr,int index)

开辟新数组Array.newInstance(Class<?> componentType, int length)

取得数组信息并修改内容

package com.reflection.demo4;
import java.lang.reflect.Array ;
public class ClassArrayDemo{
public static void main(String args[]) throws Exception{
int temp[] = {1,2,3} ;// 声明一整型数组
Class<?> c = temp.getClass().getComponentType() ;	// 取得数组的Class对象
System.out.println("类型:" + c.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)) ;
}
};
类型:int

长度:3

第一个内容:1

第一个内容:6

使用Array类还可以修改数组大小

修改的内容其实就是开辟一个新的工程,还要把旧的内容拷贝到新的数组之中去

package com.reflection.demo4;

import java.lang.reflect.Array ;
public class ChangeArrayDemo{
public static void main(String args[]) throws Exception{
int temp[] = {1,2,3} ;// 声明一整型数组
int newTemp[] = (int []) arrayInc(temp,5) ;	// 重新开辟空间5
print(newTemp) ;
System.out.println("\n-------------------------") ;
String t[] = {"hello","world","Java"} ;
String nt[] = (String [])arrayInc(t,8) ;
print(nt) ;
}
public static Object arrayInc(Object obj,int len){
Class<?> c = obj.getClass() ;
Class<?> arr = c.getComponentType() ;	// 得到数组的Class
Object newO = Array.newInstance(arr,len) ;	// 开辟新的数组大小,同时指明长度
int co = Array.getLength(obj) ;
System.arraycopy(obj,0,newO,0,co) ;	// 拷贝从0开始内容
return newO ;
}
public static void print(Object obj){	// 数组输出
Class<?> c = obj.getClass() ;
if(!c.isArray()){	// 判断是否是数组
return;
}
Class<?> arr = c.getComponentType() ;
System.out.println(arr.getName()+"数组的长度是:" + Array.getLength(obj)) ;	 // 输出数组信息
for(int i=0;i<Array.getLength(obj);i++){
System.out.print(Array.get(obj,i) + "、") ;	// 通过Array输出
}
}
};
int数组的长度是:5

1、2、3、0、0、

-------------------------

java.lang.String数组的长度是:8

hello、world、Java、null、null、null、null、null、
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: