【问题标题】:How to hide visibility of Kotlin internal class in Java from different modules?如何从不同的模块中隐藏 Java 中 Kotlin 内部类的可见性?
【发布时间】:2020-11-06 06:55:14
【问题描述】:

我正在开发我在 Kotlin 中开发的 Android 库。我将某些类的访问修饰符保留为internal。内部类仅在 Kotlin 的该库模块中可见。如果我在应用程序中实现该库,那么它根本不可见。

但是从 Java 代码访问该库时会出现问题。如果我创建 .java 文件并键入该库的 internal 类的名称,则 IDE 会建议名称,并且它已被解析和编译,没有任何错误。

例如

库模块:

internal class LibClass {
    // Fields and Methods
}

DemoApp 模块中实现上述库后:

应用模块

科特林:
fun stuff() {
    val lib = LibClass() // Error.. Not resolving
}
爪哇:
public void stuff() {
    LibClass lib = new LibClass() // Successfully resolving and compiling
}

这就是问题所在。如何从 Java 中保护该类?

谢谢!

【问题讨论】:

  • 这不应该是这样,在我的 IDE 中我无法编译它。你确定你是在 app 模块中访问 LibClass 吗?
  • 是的,我可以从应用模块访问它。它只是在类名下方显示红色错误下划线但编译成功
  • 不确定它是否可行,但可以尝试使用@JvmName 注释您的类,并为其指定一个无效的 Java 名称,例如包含空格、连字符或其他内容。
  • 好的。我会试试这个,然后告诉你
  • @SaurabhThorat 我尝试使用@JvmName,但它不起作用。仅当在 .kt 文件中创建顶级函数时才有效。它不适用于班级。

标签: android class kotlin internals modifier


【解决方案1】:

如果你想隐藏类而不是每个函数或字段的可见性,你可以在你的类顶部使用@file:JvmSynthetic

例如

@file:JvmSynthetic
package  com.example.app

internal class LibClass {
    var count: Int = 0

    internal fun exampleFun() {
        
    }
}

【讨论】:

    【解决方案2】:

    不是完美的解决方案,但我找到了两个 hacky 解决方案

    @JvmName 用空格或特殊符号注释 internal class 的每个公共方法,这样会在 Java 中产生语法错误。

    例如

    internal class LibClass {
    
        @JvmName(" ") // Blank Space will generate error in Java
        fun foo() {}
    
        @JvmName(" $#") // These characters will cause error in Java
        fun bar() {}
    }
    

    由于上述解决方案不适合管理大型项目或似乎不是好的做法,因此以下解决方案可能会有所帮助。

    @JvmSynthetic 注释 internal class 的每个公共方法,Java 无法通过这些方法访问公共方法。

    例如

    internal class LibClass {
    
        @JvmSynthetic
        fun foo() {}
    
        @JvmSynthetic
        fun bar() {}
    }
    

    注意:

    这在this article中有详细解释。

    【讨论】:

    • 但是如果库本身混合了 Kotlin 和 Java 并且 Java 使用 @file:JvmName("SomeName") 使用 Kotlin 代码会怎样。设置为空白或 #$ 使库的 java 类也无法访问它们。如何解决这个问题?
    • @GopalSAkshintala 那不合适。要么使用 100% Kotlin 或 Java(据我所知)。
    【解决方案3】:

    我看到你有一个带有 internal 修饰符的类,它不能在 kotlin 类中实例化,但可以在 Java 文件中实例化。 如果它是一个独立的类,您可以将其构造函数设为私有并允许使用静态方法(Companion 对象)进行实例化。

    【讨论】:

    • 谢谢。但是,如果我将其设为私有,那么我也无法从其他 kotlin 类访问它。
    猜你喜欢
    • 2018-01-05
    • 2022-01-14
    • 1970-01-01
    • 2023-03-11
    • 2015-10-29
    • 2012-06-10
    • 2012-05-10
    • 1970-01-01
    • 2015-01-11
    相关资源
    最近更新 更多