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

在正常情况下,得到类的对象后,我们就可以直接调用类中的方法了,如果要想调用的话,则肯定必须清楚地知道要调用的方法是什么,之后通过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方法来实现:

public Object invoke(Object obj,
Object... args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException

示例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) 得到类中公共属性

public Field getField(String name)
throws NoSuchFieldException,
SecurityException

2)得到本类属性

public Field getDeclaredField(String name)
throws NoSuchFieldException,
SecurityException

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

1) 获取属性内容

public Object get(Object obj)
throws IllegalArgumentException,
IllegalAccessException

2) 设置属性内容

public void set(Object obj,
Object value)
throws IllegalArgumentException,
IllegalAccessException

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

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、

Java反射机制(三):调用对象的私有属性和方法的更多相关文章

  1. Java反射学习总结二(用反射调用对象的私有属性和方法)

    大家都知道正常的调用是不可以访问对象的private修饰的属性和方法的,这也是Java的封装性原则. 但是有没有方法可以强制去访问对象的private修饰的属性和方法呢?那就是用反射!(这个可能在面试 ...

  2. Java反射机制(创建Class对象的三种方式)

    1:SUN提供的反射机制的类: java.lang.Class<T> java.lang.reflect.Constructor<T> java.lang.reflect.Fi ...

  3. Java反射机制(获取Class对象的三种方式+获取Class中的构造函数进行对象的初始化+获取反射类的字段+获取反射类的一般方法)

    反射技术其实就是动态加载一个指定的类,并获取该类中的所有内容.而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员,简单来说:反射技术可以对一个类进行解剖,反射大大增强 ...

  4. 利用JAVA反射机制实现调用私有方法

    1.fragment是AccessibilityFragment的對象.须要被調用的方法的類. setAccessible(true)并非将方法的訪问权限改成了public.而是取消java的权限控制 ...

  5. Java通过反射机制修改类中的私有属性的值

    首先创建一个类包含一个私有属性: class PrivateField{ private String username = "Jason"; } 通过反射机制修改username ...

  6. 通过java反射机制,获取对象的属性和值(包括所有继承的父类)

    java的反射机制提供了两种方法: getDeclaredFields() :该方法能获取到本类的所有属性,包括private,protected和public,但不能获取到继承的父类的属性. get ...

  7. JavaScript基础对象创建模式之私有属性和方法(024)

    JavaScript没有特殊的语法来表示对象的私有属性和方法,默认的情况下,所有的属性和方法都是公有的.如下面用字面声明的对象: var myobj = { myprop: 1, getProp: f ...

  8. Python面向对象之私有属性和方法

    私有属性与私有方法 应用场景 在实际开发中,对象的某些属性或者方法 可能只希望在对象的内部被使用,而不希望在外部被访问到: 私有属性 就是对象不希望公开的属性: 私有方法 就是对象不希望公开的方法: ...

  9. Java反射机制调用对象的方法 —— 将一个对象的属性值赋值给另一个对象的属性

    模拟一个场景: 众所周知,EasyExcel导出Excel文档是依赖于注解完成的,在实体类需要导出的属性上面加上注解,导出的时候会自动识别该属性. 假如我们现在需要导出用户的信息,又不想污染原本的实体 ...

随机推荐

  1. 洛谷1081 (NOIp2012) 开车旅行——倍增预处理

    题目:https://www.luogu.org/problemnew/show/P1081 预处理从每个点开始a能走多少.b能走多少.可以像dp一样从后往前推. 但有X的限制.所以该数组可以变成倍增 ...

  2. SQLServer —— 流程控制语句

    一.IF - ELSE 语法: IF(条件) BEGIN 语句1 语句2 ... END ELSE BEGIN 语句1 语句2 ... END 说明: ELSE是可选部分,如果有多条语句,才需要BEG ...

  3. Node.js入门笔记

    第一步自然是安装了.我是用Webstorm这个ide,安装分2步: 1.安装nodejs,下载Windows下的安装版本号.注意是以msi为扩展名的,然后下一步.没啥好说的,下载地址例如以下: 32位 ...

  4. Directx11教程(12) 禁止alt+enter全屏窗口

    原文:Directx11教程(12) 禁止alt+enter全屏窗口        在D3D11应用程序中,我们按下alt+enter键,会切换到全屏模式.有时候,我们在WM_SIZE中有一些代码,全 ...

  5. jQuery图片从下往上滚动效果

    在线演示 本地下载

  6. oracle如何加固你的数据库

    要注意以下方面 1. 修改sys, system的口令. 2. Lock,修改,删除默认用户: dbsnmp,ctxsys等. 3. 把REMOTE_OS_AUTHENT改成False,防止远程机器直 ...

  7. js遮罩

    1.1 背景半透明遮罩层样式 需要一个黑色(当然也可以其他)背景,且须设置为绝对定位,以下是项目中用到的css样式: /* 半透明的遮罩层 */ #overlay { background: #000 ...

  8. 并发编程之submit和execute区别

    前言 使用线程池难免会用到submit和execute,但是submit是有坑的,此处做个记录 1.submit坑 此处随便写一个方法,进入内部查看execute和submit /** * @Auth ...

  9. JavaScript的六种数据类型与隐式转换

    一.六种数据类型 javascript的数据类型包括: (1)基本数据类型:number.string.boolean.null.undefined (2)对象:object object又包括Fun ...

  10. Effective C++: 02构造、析构、赋值运算

    05:了解C++默默编写并调用哪些函数 1:一个空类,如果你自己没声明,编译器就会为它声明(编译器版本的)一个copy构造函数.一个copy assignment操作符和一个析构函数.此外如果你没有声 ...