当前位置: 首页 > 知识库问答 >
问题:

增加界面的可见性

林蕴藉
2023-03-14

我有两个包裹:

package com.test.hidden;
public class FancyClass {
    public void registerListener(MyListener listener) {
        // ...
    }
}
package com.test.hidden;
interface MyListener {
    void doSomething();
}

2.com.test.myapp:

这里有一个FancyClass的实例,我想向它注册一个新的MyListener对象。

显然这是行不通的,因为com.test.myapp中不可见mylistener。我的直觉是在com.test.hidden中创建一个新接口,它扩展了MyListener并且是公共的:

package com.test.hidden;
public interface MyListenerWrapper extends MyListener {
    @Override
    void doSomething();
}
package com.test.myapp
import com.test.hidden.FancyClass
import com.test.hidden.MyListenerWrapper

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {

        val fc = FancyClass()
        fc.registerListener(object : MyListenerWrapper {
            override fun doSomething() {
                // ...
            }
        })
    }
}

但我得到一个IllegalAccessErr:

java.lang.IllegalAccessError: Illegal class access: 'com.test.myapp.MainActivity' attempting to access 'com.test.hidden.MyListener' (declaration of 'com.test.myapp.MainActivity' appears in /data/app/com.test.myapp-ZzNlHhuBCCdAEV4QsZHspw==/base.apk)
        at com.test.myapp.MainActivity.onCreate(MainActivity.kt:15)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2899)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3054)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1814)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:280)
        at android.app.ActivityThread.main(ActivityThread.java:6710)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

当我将mylistener的可见性更改为public时,它工作得很好,所以我怀疑Java不喜欢增加子接口中接口的可见性。为什么这行不通,如何解决?

共有1个答案

鲜于海
2023-03-14

Kotlin不喜欢在公共方法中公开内部API,如果这样做,实际上会给编译器带来错误。如果您从Kotlin调用代码,这也会影响Java代码,但它会在运行时而不是在编译时抛出异常。

至于解决方案,Kotlin有internal,但这是一个真正特殊的关键字:与Java的包private(无修饰符)不同,internal使其在模块中的任何地方都可见。

这也是一种解决方案:转换为Kotlin并使用internal。如果您正在制作一个库,它在模块外是不可见的,但您至少可以在内部声明它。

而最终的解决之道:公之于众。我强烈建议您使用此选项,而不是其他选项,主要是因为它是最简单的选项,而且不需要繁琐的设计。此外,如果您打算访问其他地方的接口,那么您必须使用特定的实现,而不是通用的超类,这并不总是可行的(但这取决于您的使用)。

还有只使用Java的选择,但我想您更喜欢混合,因为您已经在这么做了。但正如Michael提到的,您确实应该避免这种设计:这是糟糕的设计。如果我是你,我会公开的。

 类似资料:
  • 问题内容: 默认情况下,接口中的所有方法是否都具有“公共可见性”模式? 问题答案: 接口中的所有方法默认为。 请参阅Java语言规范6.6.1,其中规定 接口的所有成员都是隐式的。

  • 我使用PHPMailer通过smtp-relay.gmail.com发送电子邮件-见上一篇文章通过G-Suite建立帐户后,我的凭据被接受,但是当电子邮件发送时,我可以看到纯文本版本,以及html版本,一路上还有一些其他角色: ... 然后是html版本,以以下内容结尾: 当我使用香草版本时,它工作得很好,没有看到纯文本或哑剧边界数据: 变量$htmlMessage仍然保存与以前相同的信息,但现在

  • 问题内容: 有谁知道是否有任何执行以下操作的闩锁实现: 有一种减少锁存器值的方法,或者如果该值为零则等待 具有等待锁存器值为零的方法 具有将数字添加到锁存器值的方法 问题答案: 除了从AQS开始,您可以使用下面的简单实现。它有些天真(它是同步的,而AQS是无锁算法),但是除非您希望在满足条件的情况下使用它,否则它可能已经足够好了。 注意:我尚未对其进行深入测试,但它的行为似乎与预期的一样: 输出:

  • 为什么我们不能降低能见度,但可以提高能见度? 此外,我需要实现模板模式,其中可见的公共方法只能是基类。

  • 问题内容: 如何使用不带HTML标记的Selenium Webdriver获得网页的可见文本部分? 我需要与Htmlunit中的函数HtmlPage.asText()等效的东西。 仅使用WebDriver.getSource函数获取文本并使用jsoup解析文本是不够的,因为页面中可能存在隐藏的元素(通过外部CSS),我对此并不感兴趣。 问题答案: 这样做(或使用其他选择器选择顶部元素),然后对该元

  • 有什么方法可以确定已经附加到场景但设置为不可见的节点的边界(尤其是高度和宽度)吗? 我想仅在其宽度超过100px时才在屏幕上显示标签...但它始终为 0: sysout的结果:(还有n.getWidth()也好不到哪里去) BoundingBox[minX: 0.0, minY: 0.0, minZ: 0.0,宽度: 0.0,高度: 0.0,深度: 0.0, maxX: 0.0, maxY: 0.