当前位置: 首页 > 面试题库 >

是否可以在Java运行时实现接口?

松献
2023-03-14
问题内容

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

以下代码片段很好地说明了我的问题。

码:

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在编译时可能会或可能不会实现的接口。

码:

public interface ExampleInterface {
    public void run();
}

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

  1. run()仅在c是的实例时调用ExampleInterface
  2. getRunConditions(Clazz c)并且executeClazz(Clazz c)都是我无法访问的类中的私有方法。
  3. 在编译时,Clazz 包含名为的方法run()
  4. ExampleExecutor 不是 我的课程。我无法以任何方式访问它(我什至无法获得该类的实例)。

码:

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

显然 ,以下方法在语法上不可行
,但这是我正在尝试实现的方法。基本上,如果c尚未实现ExampleInterface,请将c设置为Implement
ExampleInterface,然后提供必须重写的方法。

请注意以下几点:

  1. extendInterface( Name of Interface)是我为了说明我的目标而创建 的组合语法
  2. run() 必须 在运行时在这里定义。
  3. 我不能使用包装器或代理类作为解决方案。IE,该Clazz对象必须最终实现ExampleInterface,而我不能使用解决方法。(如果您想知道原因,请参考 此链接 )。

码:

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

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

同时,我还希望偶尔增加对run()默认情况下不支持的支持。由于我无权访问Clazz对象的创建,因此无法通过自己实现接口来实现。

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

注意:
虽然唯一的解决方案可能需要反射(如果需要,请在下面发布),但是我正在使用的库具有一个安全管理器,该管理器阻止所有反射的使用。IE,一种反射性解决方案将来可能对其他人有用,但对我而言将毫无用处。

另外,我并不是说只在自己的程序中使用一个库。一个已经在运行的主机应用程序(这就是我正在使用的库所针对的)符合并运行我为其编写的代码。如果该应用程序不喜欢我提供的任何代码(即,IE与其安全管理器发生冲突),则该代码甚至不会被编译。

为什么我需要这样做:

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

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

例如:mouseClicked(CustomMouseEvent evt)可能是接口中一部分的方法CustomMouseListener。有时候,Clazz当我单击鼠标(因此继承了CustomMouseListener)时,我正在使用的实例会很在意,而其他时候却没有。

Clazz实例不同,我始终关心是否单击了鼠标,并且始终需要触发事件。

实际上,ExampleInterface实际上是以下情况:

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

问题答案:

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

在加载时需要执行此操作的原因是,许多JVM不允许您更改字段,而某些JVM不允许您在类加载后添加方法。

一个更简单的解决方案是反编译该类,对其进行修改然后再次对其进行编译。假设可以反编译该类,这将节省大量时间和精力。

我正在使用的库中有一个安全管理器,它阻止所有反射的使用

这是一个奇怪的选择,因为您可以在调用库之前放置自己的SecurityManager,并且它不能阻止您执行任何操作。



 类似资料:
  • 问题内容: 例如,假设我想“提取” 为三个单独的变量,例如: 我该怎么做,而忽略了 “为什么要这么做呢?” 您可能会被问到这个问题。 之前已经多次问过类似的问题,但是从未给出真正的答案,因为OP真正需要的是使用不同的方法。很好,但这有可能吗? 我看过反射,似乎没有任何方法可以使我甚至向实例添加额外的字段,更不用说动态创建本地了。 问题答案: 是否可以在Java运行时创建变量? 简单回答是不。 Ja

  • 问题内容: 现在我以下: 1)一个Java接口。 2),它的具体的java类 不 执行上述接口,但 不 包含的方法签名的接口中定义的方法中的每一个匹配。 由于我无法更改第2项的实现,因此我想知道是否可以使接受第1项实例作为参数的方法接受没有类强制转换的第2项。 感觉像Spring中的各种编织/强制/ AOP机制应该可以实现这一点,但是我不知道该怎么做。 有没有办法做到这一点? 问题答案: 您可以强

  • 问题内容: 假设我在使用Java 8类型注释的类中具有以下成员: 是否可以在运行时使用反射读取在String类型上使用的给定注释?如果是这样,将如何进行? 更新:这是注释类型的定义: 问题答案: 是的,有可能。表示这种结构的反射类型称为。这是如何获取注释的示例:

  • 问题内容: 我在运行时加载JSON配置文件,并使用接口定义其预期结构: 由于可以使用自动填充等功能,因此可以方便地访问各种属性。 问题: 有没有一种方法可以使用此声明来检查我加载的文件的正确性? 即我没有意外的属性? 问题答案: 没有。 当前,类型仅在开发和编译期间使用。类型信息不会以任何方式转换为已编译的JavaScript代码。

  • 问题:有没有一种方法可以使用这个声明来检查我加载的文件的正确性?我没有意外的财产?

  • 问题内容: 昨晚我在玩Java8 Lambda,我想知道是否有可能在运行时检索Lambda表达式。简而言之,据我所知,Lambda表达式在运行时被转换为(静态)方法,然后使用InvokeDynamics进行调用。 让我们举一个这样的例子: 其中将是以a 作为参数的自定义方法。在此方法内部,在这种情况下,如何以类似于Lambda表达式()的形式检索参数? 我尝试使用ASM5_BETA读取参数类的生成