是否可以在Java中在运行时实现接口? [英] Is it possible to implement an interface at runtime in Java?

查看:256
本文介绍了是否可以在Java中在运行时实现接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个项目,其中有很多对象是由库创建的,我无法访问这些对象的创建过程。

I am working on a project where there are a lot of objects that are created by a library, and I have no access to the creation process of these objects.

以下片段是说明我的问题的一个很好的例子。

The following snippets serve as a good example to illustrate my problem.

代码:

public class Clazz {
    //The contents of Clazz are irrelevant
    //Clazz is NOT my class. I have no access to its internal structure.
    //However, I do have access to Clazz objects that were created elsewhere.
}

ExampleInterface 是一个Clazz在编译时可能会或可能不会实现的接口。

ExampleInterface is an interface that Clazz may or may not implement at compile time.

代码:

public interface ExampleInterface {
    public void run();
}

以下代码是我遇到的问题。请注意以下内容:

The following code is the problem that I am running into. Take note of the following:


  1. run()仅在c为c时调用 ExampleInterface的实例

  2. getRunConditions(Clazz c) executeClazz(Clazz c)都是我无法访问的类中的私有方法。

  3. 在编译时, Clazz 包含名为 run()的方法。

  4. ExampleExecutor 我的班级。我无法以任何
    的方式访问它(我甚至无法获得该类的实例)。

  1. run() is only called when c is an instance of ExampleInterface.
  2. getRunConditions(Clazz c) and executeClazz(Clazz c) are both private methods in a class that I do not have access to.
  3. At compile time, Clazz will not contain a method named run().
  4. ExampleExecutor is not my class. I have no access to it in any way (I can't even get an instance of the class).

代码:

public class ExampleExecutor {
    public void executeClazz(Clazz c) {
        if ((c instanceof ExampleInterface) && getRunConditions(c)) {
            ExampleInterface ex = (ExampleInterface) c;
            ex.run();
        }
    }
}

显然以下方法在语法上不可能,但这正是我想要实现的。基本上,如果c还没有实现 ExampleInterface ,请设置c以实现 ExampleInterface ,然后提供必须的方法被覆盖。

Obviously the following method isn't syntactically possible, but it is what I am trying to achieve. Basically, if c doesn't already implement ExampleInterface, set c to implement ExampleInterface, and then provide the methods that must be overridden.

请注意以下事项:


  1. extendInterface( 接口名称 是<强大的>虚构的语法 I
    是为了说明我的目标而创建的。

  2. run()必须在这里定义(在运行时)。

  3. 我不能使用包装器或代理类作为解决方案。 IE, Clazz 对象必须结束实现 ExampleInterface ,我无法使用变通方法。 (参考 此链接 如果你想知道原因)。

  1. extendInterface(Name of Interface) is made-up syntax I created in an attempt to illustrate my goal.
  2. run() must be defined here (at runtime).
  3. I cannot use a wrapper or proxy class as a solution. IE, the Clazz object must wind up implementing ExampleInterface, and I can't use a workaround. (refer to this link if you want to know why).

代码:

public void implementInterface(Clazz c) {
    if (!(c instanceof ExampleInterface)) {
        c.extendInterface(ExampleInterface {
            @Override
            public void run() {
                //code
            }
        });
    }
}

为了澄清,我遇到的问题是我需要始终知道何时 run() Clazz 中被调用。如果 Clazz 曾经没有实现 ExampleInterface ,我不知道什么时候 run() 应该被调用。

To clarify, the issue that I am running into is that I need to always know when run() is called in Clazz. If Clazz ever doesn't implement ExampleInterface, I can't know when run() should be called.

同时,我还想偶尔添加对 run()<的支持/ code>默认情况下不支持。因为我无法创建 Clazz 对象,所以我不能通过自己实现这个界面来实现这一点。

At the same time, I would also like to occasionally add support for run() when it by default isn't supported. Because I have no access to the creation of Clazz objects, I can't do this by implementing the interface myself.

问题:简单来说,是否可以在运行时实现接口(并提供所需的方法)?

注意:虽然唯一的解决方案可能需要反射(如果是这样,请在下面发布),我使用的库有一个安全管理器阻止所有反射的使用。 IE,一个反思性的解决方案将来可能对其他人有用,但对我来说没用。

NOTE: While the only solution may require reflection (and if so please post it below), the library I am using has a security manager that blocks the use of all reflection. IE, a reflective solution may be of use to others in the future, but will be of no use to me.

另外,我并不是说只使用一个库在我自己的程序中。已经运行的主机应用程序(我正在使用的库是这样做的)符合,然后运行我为它编写的代码。如果该应用程序不喜欢我提供的任何代码(IE,与其安全管理器冲突),则代码永远不会被编译。

Also, I don't mean just using a library in my own program. An already running host application (which is what the library I am using was made for) complies and then runs code that I write for it. If that application doesn't like any of the code that I provide (IE, conflicts with its security manager), the code is never even compiled.

为什么我需要这样做:

它与我正在使用的库有关。因为 ExampleExecutor 是一个我无法访问的方法,而且我无法控制Clazz的创建,我无法确定何时执行run()

It has to do with the library that I am using. Because ExampleExecutor is a method that I don't have access to, and I can't control the creation of Clazz, I can't determine when run() is executed.

我需要知道什么时候 run()被执行是因为实际上, run()是一个事件处理程序,它是我正在使用的库的一部分。

The reason why I need to know when run() is executed is because in actuality, run() is an event handler that is part of the library I am using.

例如: mouseClicked(CustomMouseEvent evt)可能是接口 CustomMouseListener 的一部分。有时候 Clazz 的实例我在点击鼠标时会小心谨慎(因此继承 CustomMouseListener ),而其他它没有。

For example: mouseClicked(CustomMouseEvent evt) might be a method that is part of the interface CustomMouseListener. Sometimes the instance of Clazz I am working with cares when the mouse is clicked (and therefore inherits CustomMouseListener), while other times it doesn't.

Clazz 实例不同,我总是关心鼠标是否被点击,并且总是需要触发事件。

Unlike the Clazz instance, I always care if the mouse is clicked, and always need the event to be triggered.

实际上, ExampleInterface 实际上是以下内容:

In reality, the ExampleInterface would actually be the following:

public interface CustomMouseListener {
    public void mouseClicked(CustomMouseEvent evt);
    public void mousePressed(CustomMouseEvent evt);
    public void mouseReleased(CustomMouseEvent evt);
    //etc
}


推荐答案

做你建议的唯一方法是使用字节码Instrumentation。您可以添加一个代理,在加载之前更改要修改的clazz的字节代码。

The only way to do what you suggest is to use byte code Instrumentation. You can add an agent which changes the byte code of the clazz you want to modify before it is loaded.

您需要在加载时执行此操作的原因是JVMs不允许你更改字段,有些不允许你在加载类之后添加方法。

The reason you need to do this at load time is that many JVMs will not allow you to change fields and some don't allow you to add methods after the class is loaded.

一个更简单的解决方案是反编译类,修改它并再次编译。假设该类可以被反编译,这将节省您大量的时间和精力。

A simpler solution is to decompile the class, modify it and compile it again. Assuming the class can be decompiled this will save you a lot of time and effort.


我使用的库有一个安全管理器阻止使用所有反射

the library I am using has a security manager that blocks the use of all reflection

这是一个奇怪的选择,因为你可以在调用库之前安装自己的SecurityManager,它可以' t阻止你做任何事情。

This is an odd choice because you can put in place your own SecurityManager before calling the library and it can't prevent you from doing anything.

这篇关于是否可以在Java中在运行时实现接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆