Java反射机制的应用

反射除了可以取得一个类的完整结构外,还可以调用类中指定的方法或指定的属性,并且可以通过反射完成对数组的操作
定义一个类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 ;
	}
};

一 、通过反射调用类中的方法

  1. 通过Class类的 getMethod() 方法取得一个Method 对象,并设置此方法操作时所需要的参数类型
  2. 使用 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) + "、");
        }

    }
}

程序运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值