黑马程序员--03.反射--05【反射获取成员方法】

反射----5

      反射获取成员方法

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

1.    反射获取成员方法

1). 成员方法类java.lang.reflect.Method

Method类的基本概念

[1]. Method所在的位置

Method类位于java语言包 (lang)的反射子包(reflect)java.lang.reflect

[2]. Method描述的事物

Method抽象的是各个类成员方法的总体。

[3]. Method类的源码声明

public final

class Method extends AccessibleObject implements …{…}

【结论】MethodField一样不可以被继承类。

注意,MethodField不是泛型类

2). 获取成员方法类实例对象的方式

测试类:

public class Person {
    private int age;
    private String name;
    private static String country ="China";
   
    public void show(){
       System.out.println(name +"... show run..."+ age);
    }
   
    private void showII(){
       System.out.println(name +"... showII runs..."+ age);
    }
 
    public void method(){
       System.out.println(name +"... method run..."+ age);
    }
 
    public void paramMethod(String str, int num){
       System.out.println(".paramMethod run..."+ str+":"+ num);
    }
    
    public static void staticMethod(String message){
	System.out.println(message +", I am from "+country);
    }
}

(1). Class类对象4种方法可以获取Method类对象。

[1].  Class类getMethods()方法

public Method[] getMethods()throwsSecurityException {…}

{1}. 获取一个类的对象所有public成员方法对应的Method对象

【注意】包含父类的public方法

{2}. 测试代码:

Class clazz = Class.forName("cn.itcast.bean.Person");
Method[] methods =clazz.getMethods();
for(Method method: methods){
    sop(method);
}

打印结果:(获取到父类的public方法)

public voidcn.itcast.bean.Person.paramMethod(java.lang.String,int)

public void cn.itcast.bean.Person.show()

public void cn.itcast.bean.Person.method()

public final native java.lang.Classjava.lang.Object.getClass()

public native int java.lang.Object.hashCode()

public booleanjava.lang.Object.equals(java.lang.Object)

public java.lang.Stringjava.lang.Object.toString()

public final native voidjava.lang.Object.notify()

public final native voidjava.lang.Object.notifyAll()

public final native void java.lang.Object.wait(long)throws java.lang.InterruptedException

public final voidjava.lang.Object.wait(long,int) throws java.lang.InterruptedException

public final void java.lang.Object.wait()throws java.lang.InterruptedException

 

[2].  Class类getDeclaredMethods()方法

    public Method[]getDeclaredMethods()throws SecurityException {…}

{1}.获取一个类的对象所有任意访问权限(private/protected/public/默认)成员方法对应的Method对象

【注意】不包含父类的方法,仅仅包含子类任意访问权限的方法

{2}. 测试代码:

Class clazz = Class.forName("cn.itcast.bean.Person");
Method[] methods =clazz.getDeclaredMethods();
for(Method method: methods){
    sop(method);
}

打印结果:

public voidcn.itcast.bean.Person.paramMethod(java.lang.String,int)

private void cn.itcast.bean.Person.showII()

public void cn.itcast.bean.Person.show()

public void cn.itcast.bean.Person.method()

[3].  Class类 getMethod(Stringname, Class<?>…parameterTypes)方法

public Method getMethod(String name, Class<?>...parameterTypes) {…}

依据给定的方法名(name)参数列表(parameterTypes) 获取指定的public方法类对象

name指定调用的方法名,以String的形式出现。

parameterTypes指定方法的形参,由于方法的参数可能是各种各样,所以使用的是Class<?>[] ====>可变参数数组Class<?>…

[4]. Class类 getDeclaredMethod(String nameClass<?>…)方法

public Method getDeclaredMethod(String name,Class<?>... parameterTypes)throws NoSuchMethodException, SecurityException {…}

依据给定的方法名(name)参数列表(parameterTypes) 获取指定的任意权限方法类对象

(2). 调用Method类对象的invoke方法来调用指定的方法

Method类invoke()方法源码声明

public Object invoke(Object obj, Object... args)throws …;

    第一个参数Object指定的是调用这个方法所以依靠的对象,不能使用泛型。

    第二个参数Object… args指定方法的实参,由于方法实参可能是各种各样对象,所以使用的是Object…args,而不是T…args

(3). 操作不同权限字段类对象

[1]. 操作公有public字段类对象

{1}. getMethod()操作public方法类对象

【示例代码1】反射调用无参方法show( )

Class clazz = Class.forName("cn.itcast.bean.Person");
Constructor constructor =clazz.getConstructor(String.class, int.class);
Object obj =constructor.newInstance("Benjamin", 28);
Method method =clazz.getMethod("show", null);
method.invoke(obj, null);
 

运行结果:

Person param run...Benjamin:28

Benjamin... show run...28

 

【示例代码1】反射调用有参方法 voidparamMethod(String str,int num)

Class clazz = Class.forName("Person");
Object obj = clazz.newInstance();
 
Method method =clazz.getMethod("paramMethod", String.class, int.class);
method.invoke(obj, "Benjamin", 110);

运行结果:

Person run...

paramMethod run...Benjamin:110

 

{2}. getField( )操作公有字段类对象 ----抛出异常

【示例代码】 

Class clazz = Class.forName("cn.itcast.bean.Person");
Constructor constructor =clazz.getConstructor(String.class, int.class);
Object obj =constructor.newInstance("Benjamin", 28);
Method method =clazz.getMethod("showII", null);
method.invoke(obj, null);

运行结果抛出异常:

Person param run...Benjamin:28

java.lang.NoSuchMethodException: cn.itcast.bean.Person.showII()

 

【分析】由于getMethod仅仅能获取public类型的方法。但是showII ( )是private类型的方法,所以getMethod没有获取到这个字段。

[2]. 操作其他非公有字段类对象

{1}.使用getDeclaredField( )直接操作非公有类型的字段 -----直接抛出异常

【示例代码】

Class clazz = Class.forName("cn.itcast.bean.Person");
Constructor constructor =clazz.getConstructor(String.class, int.class);
Object obj =constructor.newInstance("Benjamin", 28);
 
Method method =clazz.getDeclaredMethod("showII", null);
method.invoke(obj, null);
 

运行结果抛出异常:

Person param run...Benjamin:28

java.lang.IllegalAccessException: Class ReflectDemoIV can not accessa member of class cn.itcast.bean.Person with modifiers "private"

【分析】使用getDeclaredMethod( )方法获取任意类型的方法,所以没有抛出

java.lang.NoSuchFieldException的异常。但是由于showII ( ) 是private类型的,所以不能直接操作。因此抛出非法权限访问异常

正确操作非公有字段的方法】采用getDeclaredMethod()获取指定的非公有方法,然后指示JVM取消对反射的对象进行Java访问权限检查的机制。之后再进行操作

{2}.使用getDeclaredMethod( )+ 取消对反射对象进行访问权限检查机制 操作非public方法

【示例代码】

Class clazz = Class.forName("cn.itcast.bean.Person");
 
Constructor constructor =clazz.getConstructor(String.class, int.class);
Object obj =constructor.newInstance("Benjamin", 28);
 
Method method =clazz.getDeclaredMethod("showII", null);
//指示JVM取消对访问权限的检查
method.setAccessible(true);
method.invoke(obj, null);
 

运行结果

Person param run...Benjamin:28

Benjamin... showII runs...28

3). 反射调用静态成员

(1). 反射调用静态成员变量

[1]. 反射调用静态成员字段非静态成员字段的步骤是一样的,只是在第二次关联的时候,在Field对象set(Objectobj, Object value)第一个参数设置为null或者get(Object obj)设置为null即可。也就是只要是关联具体对象的地方,就设置null

【示例代码】

Class clazz =Class.forName("cn.itcast.bean.Person");
Field field =clazz.getDeclaredField("country");
 
//country是private类型的  所以访问的时候 要只是JVM取消权限访问机制
field.setAccessible(true);
 
//country字段为静态的 不属于任何对象  所以  传入null
System.out.println(field.get(null));
field.set(null, "USA");
System.out.println(field.get(null));

打印结果:


(2). 反射调用静态成员方法

[1]. 反射调用静态成员方法非静态成员方法的步骤是一样的,只是在第二次关联的时候,不要为方法关联所属的对象即可,将相应关联对象信息设置为null

【示例代码】

Class clazz =Class.forName("cn.itcast.bean.Person");
//调用静态方法 不用创建对象  ---关联对象的位置传入null
Method method =clazz.getMethod("staticMethod", String.class);
method.invoke(null, "Hello"); //静态方法

打印结果:


[2]. 传统方法调用静态成员方法非静态成员方法的方式是不一样

{1}. 传统的方式调用非静态方法:“对象引用.成员非静态方法

{2}. 传统的方式调用静态方法:“类名.成员静态方法”和“对象引用.成员静态方法

(3). 反射的优势

【总结】无论是 静态成员还是 非静态成员,反射调用 这些成员的格式完全是统一的。格式化代码,有利于框架技术的搭建。

2.    传统调用方法 VS 反射调用方法

(1). 反射调用步骤

通过Method的方法invoke()方法调用指定方法的步骤

step1:通过以字符串形式给出的全类名 ===>获取Class对象

step2:调用Class对象newInstance()方法来实例化Class对象对应类的实例

step3关联String方法名+Class<?>形式参数列表

Class对象指定的方法第一次关联 ===> Method对象

关联形参列表原因就是同名的函数存在重载问题要通过不同的参数列表来确定到底是重载中的哪一个方法

关联方法:调用Method类的get[Declared]Method函数。

step4关联形式参数列表对应的实际参数列表+方法所属的对象

(2). 传统调用方法 和 反射调用方法的关系


----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值