java 对象中必须有属性和方法_Java反射机制(三):调用对象的私有属性和方法...

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

在正常情况下,得到类的对象后,我们就可以直接调用类中的方法了,如果要想调用的话,则肯定必须清楚地知道要调用的方法是什么,之后通过Class类中的getMethod方法,可得到Method对象。

public Method getMethod(String name,

Class>... parameterTypes)

throws NoSuchMethodException,

SecurityException

当获取到Method对象后,可以通过该对象来执行方法,但是在方法调用的时候,因为会牵扯到方法中参数的问题,所以通过getMethod()取得的时候,必须设置好参数类型。

package org.chen.yuan.reflect;

interface China{// 定义China接口

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 China{

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 ;

}

};我们调用sayChina()方法,此方法中没有任何参数。

执行调用的方法,需通过Method的invoke方法来实现:

示例1:(调用无参的方法)

package org.chen.yuan.reflect;

interface China{// 定义China接口

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 China{

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 ;

}

};我们在Person.java 类中定义了一个无参方法sayChina和一个有参数的方法sayHello,接下来,我们调用无参数的方法:

package org.chen.yuan.reflect;

import java.lang.reflect.Method;

public class InvokeSyaChinaDemo

{

public static void main(String[] args)

{

Class> c1 = null;

try

{

c1 = Class.forName("org.chen.yuan.reflect.Person");

Method met = c1.getMethod("sayChina");

met.invoke(c1.newInstance());

}

catch (Exception e)

{

e.printStackTrace();

}

}

}输出: 作者:沉缘,国籍:China

可以看出,通过上述反射的方式,我们能够顺利的调用Person类中的方法。 那思考下,如果我们要调用含有参数的方法sayHello,该如何做呢?

可以想象,如果方法里存在了参数,则必须设置参数的类型及内容。

public class InvokeSayHelloDemo

{

public static void main(String[] args) throws Exception

{

Class> c1 = null;

c1 = Class.forName("org.chen.yuan.reflect.Person");

Method met = c1.getMethod("sayHello", String.class, int.class);

String result = (String) met.invoke(c1.newInstance(), "沉缘", 25);

System.out.println(result);

}

}输出: 沉缘,你好!我今年:25岁了!

二、 通过反射调用类中的setter及getter方法

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

通过反射可以调用setter及getter方法。

package org.chen.yuan.reflect;

import java.lang.reflect.Method;

public class InvokeSetGetDemo

{

public static void main(String[] args) throws Exception

{

Class> c1 = null;

Object obj = null;

c1 = Class.forName("org.chen.yuan.reflect.Person");

obj = c1.newInstance();

setter(obj, "name", "沉缘", String.class);

getter(obj, "name");

setter(obj, "age", 25, int.class);

getter(obj, "age");

}

/**

* @param obj 要操作的对象

* @param att 要操作的属性

* @param value 要设置的属性数据

* @param 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);

}

catch (Exception e)

{

e.printStackTrace();

}

}

/**

* @param obj 要操作的对象

* @param att 要操作的属性

*/

public static void getter(Object obj, String att) throws Exception

{

Method met = obj.getClass().getMethod("get" + initStr(att));

System.out.println(met.invoke(obj));

}

/**

* 将单词首字母大写

*

* @param old

* @return

*/

public static String initStr(String old)

{

String newStr = old.substring(0, 1).toUpperCase() + old.substring(1);

return newStr;

}

}

三、 通过反射调用属性

如果假设要操作一个类中的属性,则也可以通过Field完成,而不必麻烦的通过setter和getter。Class类中,获取类中Field的方法:

1) 得到类中公共属性

2)得到本类属性

public Field getDeclaredField(String name)

throws NoSuchFieldException,

SecurityException

而在Field类中,提供了获取属性内容及设置属性内容的方法:

1) 获取属性内容

2) 设置属性内容

还有一点需要注意,访问类中的私有属性时,必须要让该属性对外可见:

public void setAccessible(boolean flag)

throws SecurityException

该方法继承自Field的父类:

java.lang.reflect

Class AccessibleObject

只要把该方法的参数内容设置为true即可。

public class InvokeFieldDemo

{

public static void main(String args[]) throws Exception

{

Class> c1 = null;

Object obj = null;

c1 = Class.forName("org.chen.yuan.reflect.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, 25); // 设置age属性内容

System.out.println("姓名:" + nameField.get(obj));

System.out.println("年龄:" + ageField.get(obj));

}

};

输出:

姓名:沉缘

年龄:25

可见,操作属性,未必需要setter和getter方法的支持,但是,为了保证程序的安全性,最好还是通过setter和getter方法对属性进行操作。

四、 通过反射操作数组

反射机制不光能用在类中,也可以应用在任意的引用数据类型上,当然,这就包含了数组,数组使用Array类完成。

Class类中存在以下一个方法:

public Class> getComponentType()

Array类中得到数组指定下标的内容:

public static Object get(Object array,

int index)

throws IllegalArgumentException,

ArrayIndexOutOfBoundsException

Array类中修改内容:

public static void set(Object array,

int index,

Object value)

throws IllegalArgumentException,

ArrayIndexOutOfBoundsException

Array类中开辟新的数组:

public static Object newInstance(Class> componentType,

int... dimensions)

throws IllegalArgumentException,

NegativeArraySizeException

取得数组信息并修改内容:

package org.chen.yuan.reflect;

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

数组修改的过程,实际上就是创建一个新的数组的过程,所以要把旧的数组内容拷贝到新的数组中去。

package org.chen.yuan.reflect;

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[] = {"chenyuan", "wuqing", "lengxue"};

String nt[] = (String[]) arrayInc(t, 8);

print(nt);

}

public static Object arrayInc(Object obj, int len)

{

Class> c = obj.getClass();

Class> arr = c.getComponentType(); // 得到数组的

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输出

}

}

};输出:

nt数组的长度是:5

1、2、3、0、0、

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

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

chenyuan、wuqing、lengxue、null、null、null、null、null、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值