反射获取一个类的私有方法

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

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

原文地址:https://www.cnblogs.com/ghq120/p/8439204.html

时间: 2024-11-17 20:45:18

反射获取一个类的私有方法的相关文章

如何(通过反射调用一个类的私有方法)

1 public class Calcu { 2 3 private int add(int a,int b) { 4 return a+b; 5 } 6 } public class CalcuTest{ public static void main(String[] args) { Calcu ca=new Calcu(); Class<Calcu> clazz=Calcu.class; Object res=null; try { //返回一个方法对象, Method m=clazz.

在C#中我们能调用一个类的私有方法吗

博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:在C#中我们能调用一个类的私有方法吗.

利用反射获取一个类实例的所有属性名称和值 拼接为字符串

需要一个功能:获取一个类实例的所有属性名称和值并拼接为字符串,然后进行处理.代码保存在此以备后用. 建立一个类文件ClassToString.cs 以下代码可以直接使用,参数为一个类的实例,返回的是一个数组,[0]为属性名的拼接,[1]为属性Value的拼接. 对于类的属性类型没有限制,但是如果没有全部赋值的话,Value会范围默认值, 比如int为0,String为空,DateTime为0001/1/1 0:00:00,0,0,0 需要有需要的话可以在拼接的时候判断进行相应处理 ClassTo

java利用反射来调用一个类的私有方法

public class Calculator2{ private int add(int a,int b){ return a+b; } } public class Test { public static void main(String[] args){ Calculator2 calculator2 = new Calculator2(); Class<Calculator2> clazz = Calculator2.class; Object result = null; try{

Java通过反射获取一个类里的静态常量

public class FieldReflactTest{    public static final String a="test";    protected int b;    private int c;    String d;    public static void main(String[] args){       Field[] fields=FieldReflactTest.class.getDeclaredFields();       for(Field

java进阶之反射:反射基础之如何获取一个类以及如何获取这个类的所有属性和方法(1)

java学习一段时间之后,大家可能经常会听到反射这个词,那么说明java已经学习到一个高一点的层次了.接下来我会一步步和大家一起揭开java高级特性反射的神秘面纱. 首先介绍下类对象这个概念,可能会经常用到这个概念: 类对象:java中有句很经典的话"万事万物皆对象",相信大家都不陌生,这句话告诉了我们java的特征之一,那就是面向对象.java中类的概念我们都很熟悉,既然万事万物皆是对象,那么类是谁的对象呢?<对象的概念:一个类的实例>换句话说,类是谁的实例.如此就有了类

Java反射机制demo(五)—获得并调用一个类中的方法

这个demo在使用反射机制操作属性之前,主要原因是因为在.class文件字节码中,方法排在属性的前面. 1,获得一个类中的方法 先看一下方法和运行结果.获取所有的方法使用Class类中getMethos()方法. 待获取的类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package

Java反射机制demo(四)—获取一个类的父类和实现的接口

Java反射机制demo(四)—获取一个类的父类和实现的接口 1,Java反射机制得到一个类的父类 使用Class类中的getSuperClass()方法能够得到一个类的父类 如果此 Class 表示 Object 类.一个接口.一个基本类型或 void,则返回 null.如果此对象表示一个数组类,则返回表示该 Object 类的 Class 对象. 测试代码: package com.aaron.reflect; public class Demo4 { public static void

通过反射把一个类的属性的值赋值给另一个类

两个类我就不创建了,具体实现方法如下: /// <summary> /// 通过反射把一个类的属性的值赋值给另一个类 /// </summary> /// <typeparam name="D"></typeparam> /// <typeparam name="S"></typeparam> /// <param name="s"></param>