1、通过反射机调用类中的方法:
在正常情况下一个类的对象功能产生后,就可以直接调用类中的方法了,如果想
调用的话,则肯定必须清楚的知道要调用的方法的名字是什么,之后通过Class类中的
方法,得到一个方法的Method 对象,之后通过Method对象
来执行方法,但是在方法调用的时候,会牵扯到方法中的参数问题,所以通过getMethod()取得
的时候,必须设置好需要的参数类型;
执行调用的方法是:invoke方法,执行的时候需要传递参数进去,而且需要实例化对象;
package com.lid;
interface China{//定义China接口
public static final String NATIONAL="China";//定以全局常量
public static final String AUTHOR="lid";//定以全局常量
public void sayChina();//无参数的,没有返回值得方法
public String sayHello(String name,int age);//定义有两参数的方法
}
public class Demo implements China{
private String name;
private int age;
public Demo(){}
public Demo(String name){
this.name=name;
}
public Demo(String name,int age){
this(name);
this.age=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;
}
public void sayChina(){//覆写方法
System.out.println("作者:"+AUTHOR+",国籍"+NATIONAL);
}
public String sayHello(String name,int age){
return name+",你好!我今年:"+age+"岁了";
}
}
package com.lid.demo02;
import java.lang.reflect.*;
public class InvokeSayChina{
public static void main(String args[]){
Class<?> c1=null;
try{
c1=Class.forName("com.lid.Demo");//实例化Class对象
Method met=c1.getMethod("sayChina");//找到sayChina方法---通过方法名和参数类型
met.invoke(c1.newInstance());//调用方法
}
catch(Exception e){
e.printStackTrace();
}
}
}
同过反射调用无参数的方法的整体思路:
(1).创建Demo的Class类对象【Class.forName("com.lid.Demo")】;
(2).通过Class类对象的方法得到想要的方法【c1.getMethod("sayChina")】;
(3).通过Method类型的对象执行找到的方法【met.invoke(c1.newInstance())】;
2、得到带参数的方法:
package com.lid.demo02;
import java.lang.reflect.*;
public class InvokeSayHello{
public static void main(String args[]){
Class<?> c1=null;
try{
c1=Class.forName("com.lid.Demo");//实例化Class对象
Method met=c1.getMethod("sayHello",String.class,int.class);//找到sayChina方法---通过方法名和参数类型
String rv;
rv=(String)met.invoke(c1.newInstance(),"lid",20);//调用方法
System.out.println(rv);
}
catch(Exception e){
e.printStackTrace();
}
}
}
3、通过反射机制调用Setter和Getter方法:
setter和getter方法是一个标准的属性的访问方法,如果一个类的属性被封装,必须通过setter和getter方法来设置和
取得,实际上此方法的操作之所以这样规定:主要是因为反射机制给予支持的;
通过反射机制调用setter和getter方法:
如果想调用setter,例如属性:name属性,则这样设置setter方法--setName(),方法的第二个单词首字母大写;
package com.lid.demo02;
import java.lang.reflect.*;
public class InvokeSayChina{
public static void main(String args[]){
Class<?> c1=null;
Object obj=null;
try{
c1=Class.forName("com.lid.Demo");//实例化Class对象
obj=c1.newInstance();
setter(obj,"name","lid",String.class);
setter(obj,"age",20,int.class);
System.out.println("姓名:");
getter(obj,"name");
System.out.println("年龄:");
getter(obj,"age");
}
catch(Exception e){
e.printStackTrace();
}
}
public static String initStr(String old){
String str=old.substring(0,1).toUpperCase()+old.substring(1);
return str;
}
/**
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);
met.invoke(obj,value);//设置setter的内容
}
catch(Exception e){
}
}
public static void getter(Object obj,String att) throws Exception{
try{
Method met=obj.getClass().getMethod("get"+initStr(att));
System.out.println(met.invoke(obj));
}
catch(Exception e){
}
}
}
以上的操作,在日后的开发中用户也许不会涉及的代码的开发,但是原来必须掌握;
4、通过反射调用属性:
在访问私有属性是必须让这个属性可见:
package com.lid.demo02;
import java.lang.reflect.*;
public class InvokeSayChina{
public static void main(String args[]) throws Exception{
Class<?> c1=null;
Object obj=null;
c1=Class.forName("com.lid.Demo");//实例化Class对象
obj=c1.newInstance();
Field nameField=null;
Field ageField=null;
nameField=c1.getDeclaredField("name");
ageField=c1.getDeclaredField("age");
nameField.setAccessible(true);//设置属性的可见
ageField.setAccessible(true);
nameField.set(obj,"lid");
ageField.set(obj,20);
System.out.println("姓名:"+nameField.get(obj));
System.out.println("年龄:"+ageField.get(obj));
}
}
5、反射机制不光只能用在类中,也可以应用在任意的引用数据类型上,当然,这就包含了数组,
数组使用Array类完成;
Class类中存在以下方法:getComponentType()
package com.lid.demo02;
import java.lang.reflect.*;
public class ClassArray{
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));
}
}
使用Array类还可以修改数组的大小
修改的过程实际上就是一个创建的过程,创建一个新的数组,所以还要
把就得内容拷贝到新的数组中去;
package com.lid.demo02;
import java.lang.reflect.*;
public class ClassArray{
public static void main(String args[]) throws Exception{
int temp[]={1,2,3};//声明一个数组
int newTemp[]=(int[])arrayInc(temp,5);//重新开辟一个数组
print(newTemp);
}
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);//拷贝数据
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 输出
}
}
}