Neden bu fonksiyonun java ve kotlin ile çalıştığını , tailrec
ancak kotlin olmadan çalıştığını bilmek istiyorum tailrec
?
Kısa cevap, Kotlin yönteminizin JAVA yönteminden "daha ağır" olmasıdır . Her çağrıda "kışkırtan" başka bir yöntem denir StackOverflowError
. Aşağıda daha ayrıntılı bir açıklamaya bakın.
İçin Java bayt kodu eşdeğerleri reverseString()
Ben de senin yöntemleri için bayt kodu kontrol KOTLIN ve JAVA buna:
JAVA'da Kotlin yöntemi bayt kodu
...
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'da JAVA yöntemi bayt kodu
...
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);
}
}
...
Yani, 2 ana fark var:
Intrinsics.checkParameterIsNotNull(s, "s")
Her biri için çağrılır helper()
içinde Kotlin sürümü.
- JAVA yönteminde sol ve sağ indeksler artarken, Kotlin'de her özyinelemeli çağrı için yeni indeksler oluşturulur.
Şimdi Intrinsics.checkParameterIsNotNull(s, "s")
davranışı nasıl tek başına etkilediğini test edelim .
Her iki uygulamayı da test edin
Her iki durum için de basit bir test oluşturdum:
@Test
public void testJavaImplementation() {
char[] chars = new char[20000];
new Example().reverseString(chars);
}
Ve
@Test
fun testKotlinImplementation() {
val chars = CharArray(20000)
Example().reverseString(chars)
}
İçin JAVA için ise sınav sorunsuz başarılı KOTLIN nedeniyle bir kaçýrýlmýþtýr StackOverflowError
. Ben eklendi sonra ancak Intrinsics.checkParameterIsNotNull(s, "s")
hiç JAVA yöntemiyle buna da başarısız oldu:
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);
}
Sonuç
Kişisel Kotlin diline doladığı olarak yöntem daha küçük bir yineleme derinliğini sahip Intrinsics.checkParameterIsNotNull(s, "s")
olan ağırdır böylece her adımda ve JAVA muadili. Bu otomatik oluşturulan yöntemi istemiyorsanız, derleme sırasında burada yanıtlandığı gibi boş denetimleri devre dışı bırakabilirsiniz
Ancak, hangi yararın tailrec
getirildiğini anladığınızdan (özyinelemeli çağrınızı yinelemeli bir çağrıya dönüştürür) bunu kullanmalısınız.
tailrec
veya özyinelemeden kaçınmaktır; kullanılabilir yığın boyutu, çalıştırmalar, JVM'ler ve kurulumlar arasında ve yönteme ve parametrelerine bağlı olarak değişir. Ama saf meraktan (mükemmel bir neden!) Soruyorsanız, emin değilim. Muhtemelen bayt koduna bakmanız gerekir.