私は、Javaとkotlinに2つのほとんど同じコードを持っています
Javaの:
public void reverseString(char[] s) {
helper(s, 0, s.length - 1);
}
public void helper(char[] s, int left, int right) {
if (left >= right) return;
char tmp = s[left];
s[left++] = s[right];
s[right--] = tmp;
helper(s, left, right);
}
Kotlin:
fun reverseString(s: CharArray): Unit {
helper(0, s.lastIndex, s)
}
fun helper(i: Int, j: Int, s: CharArray) {
if (i >= j) {
return
}
val t = s[j]
s[j] = s[i]
s[i] = t
helper(i + 1, j - 1, s)
}
Javaコードは、巨大な入力が、原因kotlinコードとテストに合格しStackOverFlowError
、私は追加しない限り、tailrec
前にキーワードをhelper
kotlinで機能。
私は、この機能は、Javaにもとコリンに働く理由を知りたいのtailrec
ではなくなしkotlinにtailrec
?
PS:私は何を知っていtailrec
ません
私は、この関数がで働く理由を知りたいのjavaともにkotlinで
tailrec
はなく、中にkotlinなしtailrec
?
あなたのため、短い答えはKotlinの方法は、より「重い」ですJAVAの 1。すべての呼び出しで、それは「誘発」という別のメソッドを呼び出しますStackOverflowError
。だから、以下のより詳細な説明を参照してください。
以下のためのJavaバイトコードの同等物 reverseString()
私はあなたの中にメソッドのバイトコードをチェックしKotlinとJAVAに対応:
JAVAでKotlin方法バイトコード
...
public final void reverseString(@NotNull char[] s) {
Intrinsics.checkParameterIsNotNull(s, "s");
this.helper(0, ArraysKt.getLastIndex(s), s);
}
public final void helper(int i, int j, @NotNull char[] s) {
Intrinsics.checkParameterIsNotNull(s, "s");
if (i < j) {
char t = s[j];
s[j] = s[i];
s[i] = t;
this.helper(i + 1, j - 1, s);
}
}
...
JAVAでのJavaメソッドのバイトコード
...
public void reverseString(char[] s) {
this.helper(s, 0, s.length - 1);
}
public void helper(char[] s, int left, int right) {
if (left < right) {
char temp = s[left];
s[left++] = s[right];
s[right--] = temp;
this.helper(left, right, s);
}
}
...
だから、2つの主な違いがあります:
Intrinsics.checkParameterIsNotNull(s, "s")
それぞれに呼び出されるhelper()
でKotlinのバージョン。- で左と右の指標JAVAの中にいる間方法は、インクリメントますKotlin新しいインデックスが各再帰呼び出しのために作成されます。
だから、LETのテストはどのようにIntrinsics.checkParameterIsNotNull(s, "s")
一人で行動に影響を与えます。
両方の実装をテスト
私は両方のケースのための簡単なテストを作成しました:
@Test
public void testJavaImplementation() {
char[] chars = new char[20000];
new Example().reverseString(chars);
}
そして
@Test
fun testKotlinImplementation() {
val chars = CharArray(20000)
Example().reverseString(chars)
}
以下のためにJAVAのためにしながら、テストは問題なく成功しKotlinそれは無残に失敗したためStackOverflowError
。私が追加した後、しかし、Intrinsics.checkParameterIsNotNull(s, "s")
にJAVAの方法それは同様に失敗しました:
public void helper(char[] s, int left, int right) {
Intrinsics.checkParameterIsNotNull(s, "s"); // add the same call here
if (left >= right) return;
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
helper(s, left + 1, right - 1);
}
結論
あなたのKotlinのそれは呼び出しの方法は、より小さな再帰の深さを持っているIntrinsics.checkParameterIsNotNull(s, "s")
すべてのステップで、したがって、そのより重いJAVAの対応。あなたは、この自動生成されたメソッドを使用しない場合は答えとして、あなたは、コンパイル時にヌルチェックを無効にすることができ、ここで
しかし、あなたは利益が何かを理解するのでtailrec
(反復1にあなたの再帰呼び出しに変換)もたらし、あなたはそのいずれかを使用する必要があります。