zoukankan      html  css  js  c++  java
  • 反射获取一个类的私有方法

    今天在刷面试题的时候,发现一个题目是编写程序通过反射获取一个类的私有方法,因为之前学反射的时候也学的浅,没有考虑到这样的事情。今天敲了一下,虽然也就是那么几行代码,还是磕磕绊绊的,最后终于搞定了,这里总结一下

    Java反射得到一个类的私有方法

    获得私有方法的流程是

    (1)获取目标类

    (2)获取目标方法

      Method method=clazz.getDeclaredMethod(name);//可以调用类中的所有方法(不包括父类中继承的方法)

      Method method=clazz.getMethod(name);//可以调用类中有访问权限的方法(包括父类中继承的方法)

    (3)method.toGenericString()或method.toString()方法来输出方法的字符串形式

    toGenericString() 
              返回描述此 Method 的字符串,包括类型参数。

    toString() 
              返回描述此 Method 的字符串。

     目前没有弄清这两种方法的具体区别,测试的方法中输出的结果一样,以后弄清区别再来更改。

    (4)使用invoke()方法调用方法

     

    package test0210;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class test1 {
        //类的私有方法
        private String testMethod(int num){
            return "输入的数字为:"+num;
        }
        
        public static void main(String[] args) {
            try {
                Class clazz = Class.forName("test0210.test1");
                Method method = clazz.getDeclaredMethod("testMethod", int.class);
                //打印完整地方法表示字符串
                System.out.println(method.toGenericString());
                //调用方法
                Object obj = method.invoke(clazz.newInstance(), 2);
                System.out.println(obj);
                
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

     上面的代码将测试和私有方法放在了一起,没有出现异常。

    下面的代码将测试和方法分开在两个类中,运行后会出现 java.lang.IllegalAccessException异常

    package test0210;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class test2 {
        public static void main(String[] args) {
            try {
                
                Class<?> clazz = Class.forName("test0210.test1");
                Method method = clazz.getDeclaredMethod("testMethod", int.class);
                
                System.out.println(method.toGenericString());
                
                Object obj = method.invoke(clazz.newInstance(), 2);
                System.out.println(obj);
                
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    查询资料说明该异常是在反射中调用了private修饰的方法。咦,反射不是可以得到私有的方法,为什么这里不能,没办法继续上网查资料。。。

    最后搞明白了是缺少setAccessible(true)方法,使用继承父类(AccessibleObject类)来的setAccessible()方法,来设置或取消访问检查,以达到访问私有对象的目的。

    Class<?> clazz = Class.forName("test0210.test1");
    Method method = clazz.getDeclaredMethod("testMethod", int.class);
    method.setAccessible(true);
                
    System.out.println(method.toGenericString());

    Java反射机制调用私有方法,是不是破坏了Java的封装性?

      答案是否定的。要探讨这个问题,就必须要知道什么是封装性,什么是安全?

      封装,是将具体的实现细节隐藏,而把功能作为整体提供给类的外部使用,也就是说,公有方法能够完成类所具有的功能。当别人使用这个类时,如果通过反射直接调用私有方法,可能根本实现不了类的功能,甚至可能会出错,因此通过反射调用私有方法可以说是没有任何用处的,开发人员没有必要故意去破坏封装好的类。从这点上看,封装性并没有被破坏。

      安全,如果意思是保护实现源码不被别人看见,那没有作用。不用反射也能轻易获取源码。

      我以为反射机制只是提供了一种强大的功能,使得开发者能在封装之外,按照特定的需要实现一些功能。

      Java语言是一个严谨的编程语言,语言本身是静态的。为了能让语言具有动态编程的特性,必须要有反射机制。而反射机制本身就是底层的处理,不可能按表层的封转特性来处理。也就是说不给调用私有方法的能力,很多程序受到局限,那么实现起来就麻烦了。
      举一个生活的例子,你家的电视机是要由外壳的,目的是不让普通人接触到电视中的电路。那么Java语言的基本面向对象特征正是这个层次的应用。也就是对于普通程序员的程序,是通过遥控器来操作电视的。但是,如果你是一个专业的电工的话,那么可以打开电视机的后盖,调整电视中的电路和结构,甚至如果是电工的话,那么调台可能都不使用遥控器,而是通过调整内部电路的电阻的阻值来实现。Java中的反射机制正是提供更高要求的编程来使用的,不需要考虑基本面向对象的特征,而是要考虑能否得到和控制代码中的一切,这样反射机制编程才有意义。

    参考网站

    [1]通过反射访问任意类的私有方法和属性

    http://blog.csdn.net/a997208868/article/details/48133129

    [2]Java反射机制详解

    http://www.cnblogs.com/lzq198754/p/5780331.html

    [3]https://zhidao.baidu.com/question/239368481.html

  • 相关阅读:
    BZOJ 1069 最大土地面积
    BZOJ 1059 矩阵游戏
    BZOJ 3570 动物园
    Luogu 3934 Nephren Ruq Insania
    Luogu 3233 [HNOI2014]世界树
    CF613D Kingdom and its Cities
    Luogu 4001 [BJOI2006]狼抓兔子
    Luogu 2824 [HEOI2016/TJOI2016]排序
    POJ 3463 Sightseeing
    Luogu 2495 [SDOI2011]消耗战
  • 原文地址:https://www.cnblogs.com/ghq120/p/8439204.html
Copyright © 2011-2022 走看看