【问题标题】:How to replace a private function如何替换私有函数
【发布时间】:2013-01-03 07:55:25
【问题描述】:

我想替换我知道源代码的class 的函数。问题是我无法覆盖该函数,因为它是私有的,而且我无法扩展类并覆盖整个功能,因为 bad 调用在每个可能的构造函数中。

现在我完全迷失了,我不知道如何实现所需的功能(主题化 Android VideoView 控件的控件,即 MediaController)。有没有办法用反射或类似的东西替换函数?或者甚至可以不调用超类的构造函数而是调用超超类?

这是一个非常基本的类,它显示了我的问题:

public class Base {
    public Base(int state) {
        // must be called
    }
}
public class Example extends Base {
    public Example(int state, boolean bla) {
        super(state);
        badCall();
    }        
    public Example(int state) {
        this(state, false);
    }
    private badCall() {
        // doing bad things
    }
}

另外请注意,我需要有一个 Example 的实例,所以我不能简单地复制该类。

【问题讨论】:

  • 你能在构造函数运行后“反转”“badCall()”的效果吗?丑陋,但也许是“绒毛”最少的解决方案。或者也许(我没有 AOP 经验,所以不确定......)可以通过面向方面的编程来实现,并拦截调用。
  • 不,我不能“逆转效果”。这是关于 MediaController 中的播放/暂停按钮,我看不到任何方法来观察变化。 @assylias 是否也可以在 android 中使用它?我不知道那个类/框架。
  • 你不能重写第二个构造函数(带(int state))直接调用super(state)然后this.bla=false?
  • @GeorgeD 不,我不能重写 Example 类,因为它是 android 的一部分/一个封闭的框架。

标签: java inheritance reflection overriding extends


【解决方案1】:

这是一个使用模拟框架 (jmockit) 的人为示例。输出是:

原始私有方法
其他方法
新的私有方法
其他方法

public static void main(String[] args) {
    A a = new A(); //prints Original private method
    a.m2(); //prints Some other method

    new MockUp<A>() {

        @Mock
        public void m() {
            System.out.println("New private method");
        }
    };

    A b = new A(); //prints New private method
    b.m2(); //prints Some other method
}

static class A {

    public A() {
        m();
    }

    private void m() {
        System.out.println("Original private method");
    }

    public void m2() {
        System.out.println("Some other method");
    }
}

【讨论】:

【解决方案2】:

您可以使用AspectJ 访问私有方法:

public privileged aspect SomeClassExposerAspect {

  void around(SomeClass obj) : execution(private void badCall()) {        
       try {
          // use privileged access to return the private member
          ((Example )obj).badCall();
       }
       // safeguard against unexpected 3rd party library versions, if using load-time weaving
       catch (NoSuchMethodError e) {
          //log something
       }
   }
  }
}

这是一个很好的blog

【讨论】:

  • 这对于纯 java 项目看起来不错。但是我的项目在android上运行。还是非常感谢。我认为这可能对其他人有所帮助。
  • 可以使用AspectJ on Android
  • 如果我做对了这似乎很复杂我需要更改我没有经验的构建系统,这让我有点害怕。
【解决方案3】:

如果你有来源,我建议你“修补”课程。

编译构建你的修改版本并替换jar中的旧版本 或者在类路径的前面添加它,以便隐藏旧版本。

顺便说一句:您甚至可以通过这种方式修补 JVM 中的类,尽管这不是一个好主意。 ;)

【讨论】:

  • 他没有 JVM - 字节码操作技术在 android 上的工作方式不同
  • 康斯坦丁是对的,无论如何我都不确定这将如何与新的 android 版本一起工作,其中 dx 文件比我生成的文件更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 2020-03-26
  • 2014-05-12
  • 2016-02-05
  • 1970-01-01
  • 2015-03-21
  • 2015-07-05
相关资源
最近更新 更多