Programing

Java에서 Kotlin 확장 기능에 액세스

c10106 2022. 4. 17. 12:29
반응형

Java에서 Kotlin 확장 기능에 액세스

Java 코드에서 확장 기능에 액세스할 수 있는가?

나는 확장 기능을 코틀린 파일에 정의했다.

package com.test.extensions

import com.test.model.MyModel

/**
 *
 */
public fun MyModel.bar(): Int {
    return this.name.length()
}

어디에MyModel(생성된) 자바 클래스 입니다.자바코드로 접속하고 싶었는데

MyModel model = new MyModel();
model.bar();

하지만, 그것은 효과가 없다.IDE는 방법을 인식하지 못하고 컴파일이 실패한다.

코틀린의 정적 함수와 함께 사용할 수 있는 기능:

public fun bar(): Int {
   return 2*2
}

을 이용하여import com.test.extensions.ExtensionsPackage그래서 내 IDE가 올바르게 구성된 것 같다.

코틀린 문서에서 자바 인터럽트 파일 전체를 뒤져보고 구글도 많이 검색했지만 찾을 수가 없었다.

내가 뭘 잘못하고 있는 거지?이게 가능할까?

파일에 선언된 모든 Kotlin 함수는 기본적으로 동일한 패키지 내의 클래스의 정적 메서드에 대해 컴파일되며, Kotlin 소스 파일에서 파생된 이름("Kt" 접미사로 대체된 첫 번째 문자 대문자 ".kt" 확장명)으로 컴파일된다.확장 기능을 위해 생성된 방법에는 확장 기능 수신기 유형이 포함된 추가 첫 번째 매개변수가 있을 것이다.

원래 질문에 적용하면 Java 컴파일러는 이름이 serem.kt인 Kotlin 소스 파일을 볼 수 있다.

package com.test.extensions

public fun MyModel.bar(): Int { /* actual code */ }

다음과 같은 자바 클래스가 선언된 것처럼.

package com.test.extensions

class ExampleKt {
    public static int bar(MyModel receiver) { /* actual code */ }
}

Java의 관점에서 확장된 클래스에 대해서는 아무 일도 일어나지 않기 때문에, 단지 닷-싱택스를 사용하여 그러한 방법에 접근할 수는 없다.그러나 그들은 여전히 일반적인 Java 정적 방법으로 호출할 수 있다.

import com.test.extensions.ExampleKt;

MyModel model = new MyModel();
ExampleKt.bar(model);

정적 가져오기를 예제Kt 클래스에 사용할 수 있음:

import static com.test.extensions.ExampleKt.*;

MyModel model = new MyModel();
bar(model);

코틀린 최상위 확장 함수는 자바 정적 방법으로 컴파일된다.

지정된 Kotlin 파일Extensions.kt일괄하여foo.bar포함:

fun String.bar(): Int {
    ...
}

동등한 Java 코드는 다음과 같다.

package foo.bar;

class ExtensionsKt {
    public static int bar(String receiver) { 
        ...
    }
}

만약, 그게 아니라면,Extensions.kt그 선을 포함했다.

@file:JvmName("DemoUtils")

이 경우 Java 정적 클래스의 이름이 지정됨DemoUtils

코틀린에서는 다른 방법으로 확장 방법을 선언할 수 있다. (예를 들어, 회원 함수로서 또는 동반 객체의 확장으로서)

나는 Number라는 코틀린 파일을 가지고 있다.다음 기능을 가진 포맷팅.kt

fun Double.formattedFuelAmountString(): String? {
    val format = NumberFormat.getNumberInstance()
    format.minimumFractionDigits = 2
    format.maximumFractionDigits = 2
    val string = format.format(this)
    return string
}

Java에서 파일 번호로 간단히 액세스필요한 가져오기 후 다음 방법으로 포맷Ktimport ....extensions.NumberFormattingKt;

String literString = NumberFormattingKt.formattedFuelAmountString(item.getAmount());

새로운 KotlinEx로, 당신은 Java로 내선 전화를 직접 걸 수 있다.

ExtensionFileName.foo(field1...)

기본적으로, 그것이 하는 일은, 첫 번째 논쟁과 다른 주장들이 같은 장소에 있게 하는 것이다.

그래서 예를 들면.

확장명이 있음(Extension.kt 파일에)

Context.showToast(message:String){ 
...
}

자바에서는 이렇게 부른다.

ExtensionKt.showToast(context, message);

당신은 당신의 코틀린 코드에서 생성되는 실제 자바코드를 항상 볼 수 있다.Tools > Kotlin > Show Kotlin Bytecode, 그런 다음 클릭Decompile 널 수 이것은 당신에게 엄청나게 도움이 될 수 있다.당신의 경우 Java 코드는 당신이 가지고 있다면 이렇게 보일 것이다.MyModelExtensions.kt

public final class MyModelExtensionsKt {
   public static final int bar(@NotNull MyModel $receiver) {
      Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
      return $receiver.getName().length();
   }
}

당신은 이것을 사용함으로써 개선할 수 있다.@JvmName을 포함한 파일에.bar:

@file:JvmName("MyModels")
package io.sspinc.datahub.transformation

public fun MyModel.bar(): Int {
    return this.name.length
}

이 코드는 다음과 같은 결과를 가져올 것이다.

public final class MyModels {
   public static final int bar(@NotNull MyModel $receiver) {
      Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
      return $receiver.getName().length();
   }
}

사용.MyModels유효 자바(Effective Java)가 유틸리티 클래스에 대해 제안하는 내용과 일치한다.다음과 같이 메서드의 이름을 바꿀 수도 있다.

public fun MyModel.extractBar(): Int {
    return this.name.length
}

자바 쪽에서 보면 관용적으로 보일 것이다.

MyModels.extractBar(model);

나한테는 효과가 있어:

코틀린

자바 코드

내 프로젝트는 Java로 만들어진 오래된 안드로이드 프로젝트야; 이제 나는 첫 번째 코틀린 파일을 만들고 String extensions fun String.isNotNullOrMempty(): Boolean {...}

다음 방법으로 자바 파일에서 호출할 수 있다.StringUtilsKt.isNotNullOrMempty(스트링)

내 kotlin 파일 이름은 StringUtils이다.

클래스 파일의 기능을 복제해야 하는 경우:

ex Utils.kt에 대한 Kotlin 파일 생성

코드 입력

  class Utils {
                companion object {
                    @JvmStatic
                    fun String.getLength(): Int {//duplicate of func for java
                        return this.length
                    }
                }
            }

        fun String.getLength(): Int {//kotlin extension function
            return this.length
        }

OR

class Utils {
    companion object {

        @JvmStatic
        fun getLength(s: String): Int {//init func for java
            return s.length
        }
    }
}

fun String.getLength(): Int {//kotlin extension function
    return Utils.Companion.getLength(this)//calling java extension function in Companion
}

코틀린에서 다음을 사용하십시오.

val str = ""
val lenth = str.getLength()

Java에서는 다음을 사용하십시오.

String str = "";
 Integer lenth = Utils.getLength(str);

여기서의 다른 답변은 코틀린 패키지 파일의 최상위 레벨에 있는 확장 기능을 호출하는 경우를 다룬다.

하지만, 나의 경우는 클래스 안에 있는 확장 기능을 불러야 한다는 것이었다.구체적으로, 나는 오브젝트를 다루고 있었다.

해결책은 믿을 수 없을 정도로 간단하다.

당신이 해야 할 일은 당신의 확장기능에 다음과 같이 주석을 달기만 하면 된다.@JvmStatic, 네 할 수 거야당신의 자바코드는 그것에 접속하여 사용할 수 있을 것이다.

이와 같은 클래스를 연장하는 경우:

fun String.concatenatedLength(str: String): Int {
    return (this.length + str.length)
}

fun f() {
    var len = "one string".concatenatedLength("another string")
    println(len)
}

이를 위해 다음과 같이 컴파일 형식:

import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

public final class ExampleKt {
  public static final int concatenatedLength(@NotNull String $receiver, @NotNull String str) {
    Intrinsics.checkParameterIsNotNull((Object) $receiver, (String) "$receiver");
    Intrinsics.checkParameterIsNotNull((Object) str, (String) "str");
    return $receiver.length() + str.length();
  }

  public static final void f() {
    int len = ExampleKt.concatenatedLength("one string", "another string");
    System.out.println(len);
  }
}

여기에 더 많은 가 있다.

내가 알기로는 이건 불가능해.확장 문서를 읽어보니

public fun MyModel.bar(): Int {
    return this.name.length()
}

서명으로 새로운 방법을 창조하다.

public static int MyModelBar(MyModel obj) {
    return obj.name.length();
}

그리고 나서, 코틀린은 폼의 호출에 기능하는 지도를 만든다.myModel.bar(), if.bar()에서 찾을 수 없다MyModel클래스는 자신이 출력하는 서명 및 이름 지정 체계와 일치하는 정적 방법을 찾는다.이는 확장이 정적으로 가져오기 때문에 정의된 방법을 재정의하지 않는다는 그들의 진술에서 나온 가정일 뿐이라는 점에 유의하십시오. 나는 그들이 확실히 알 만큼 충분히 멀리 가지 못했다.

따라서 위의 내용이 사실이라고 가정하면, 컴파일러는 단지 알 수 없는 방법이 물체에 호출되어 오류가 발생하는 것을 볼 수 있기 때문에, 코틀린 확장자는 단순한 오래된 자바 코드에서 호출될 수 있는 방법이 없다.

참조URL: https://stackoverflow.com/questions/28294509/accessing-kotlin-extension-functions-from-java

반응형