Soru Son statik yöntemin davranışı


Statik yöntemle değiştiricilerle uğraştım ve garip bir davranışa rastladım.

Bildiğimiz gibi, örnek değil, sınıfla ilişkilendirildiklerinden, statik yöntemler geçersiz kılınamaz.

Yani, aşağıdaki snippet'ime sahip olursam, iyi derler

//Snippet 1 - Compiles fine
public class A {
    static void ts() {
    }
}

class B extends A {
    static void ts() {
    }
}

Ancak, A sınıfındaki son değiştiriciyi statik yönteme eklerseniz, derleme başarısız olur. B'deki ts (), A'da ts () 'yi geçersiz kılmaz; geçersiz kılma yöntemi statik son.

Statik yöntem geçersiz kılınamadığında bu neden oluyor?


98
2017-11-16 17:43


Menşei


Bu soru için çok tuhaf, +1 gibi görünüyor, ama şimdiye kadar hiçbir cevap tatmin edici değil. - Rakesh Juyal
Bu geçersiz değil. Hala A.ts'de () var. - Alex Feinman


Cevaplar:


Statik yöntemler geçersiz kılınamaz, ancak gizlenebilirler. ts() B yöntemi, (polimorfizme tabi olmayan) ts() A ama onu gizler. Ararsan ts() B içinde (DEĞİL A.ts() veya B.ts() ... sadece ts()), B'den biri çağrılacak ve A değil. Bu, polimorfizme tabi olmadığından, çağrı ts() A’da asla B’deki olana yönlendirilmez.

Anahtar kelime final yöntemin gizlenmesini engeller. Bu yüzden gizlenemezler ve bunu yapmak için bir girişim derleyici hatasıyla sonuçlanır.

Bu yardımcı olur umarım.


137
2017-11-16 17:47



Belki de cevabınızı bitirmek için, inanıyorum ki, buradaki sorun temelde kötü bir derleyici hata mesajıdır. saklamak ts () 'da A. Statik bir yöntemin bildirilmesi, sonunun gizlenemeyeceğini beyan etmektir. - Sean Owen
@ Owen Owen: Ben de öyle düşünüyorum. 'Gizle' terimi, Java Spesifikasyonunda bile kullanılır, bu yüzden onu derleyici mesajında ​​kullanmayın. - NawaMan
Bu neden bir özelliktir? Hangi bağlamda yararlı olur? - immibis
public class Test {son statik genel boşluk ana (String ... srik) {System.out.println ("Ana yöntemde"); ts (); kamu statik boşluk ts () {Çocuk c = yeni Çocuk (); c.ts (); System.out.println ("Test ts"); }} public class Çocuk Test'i genişletir {public static void ts () {System.out.println ("Child ts"); }} Merhaba Bu senaryoda neler olduğunu açıklayabilir misiniz? - srikanth r
@SeanOwen Bunun doğru olduğunu düşünmüyorum, derleyici bunu A#ts devralınıyor ve böyle bir yöntem zaten var BAynı imzaya ve farklı bir değiştiriciye sahip iki yönteme sahip olmak (final) aşırı yük olarak çalışmayacaktı ... Keşke bunun için basit bir mesaj düşünebilseydim - Eugene


statik yöntemler geçersiz kılınamaz

Bu tam olarak doğru değil. Örnek kod, gerçekten de, B'deki metodun, A.'deki ts'yi gizlediği anlamına gelir. Yani tam olarak geçersiz kılmamaktadır. Üzerine Javaranch güzel bir açıklama var.


11
2017-11-16 17:48



Tam olarak doğru değil. Statik yöntemler geçersiz kılınamaz, ancak bunları sınıf adı yerine bir örnek başvurusunda çağırıyorsanız gizlenebilir. - John Mercier
Maalesef bağlantınız artık çalışmıyor. Bunu düzeltmek mümkün mü? - Mathias Bader


Statik yöntemler, örneğe değil, sınıfa aittir.

A.ts() ve B.ts() her zaman ayrı yöntemler olacak.

Asıl sorun, Java'nın bir örnek nesnesinde statik yöntemleri çağırmanıza izin vermesidir. Üst sınıftan aynı imzaya sahip statik yöntemler şunlardır: gizli alt sınıfın bir örneğinden çağrıldığında. Ancak, geçersiz kılmaya / gizleyemezsiniz son yöntemler.

Hata mesajının geçersiz kılınmış yerine gizli kelimeyi kullanacağını düşünürdünüz ...


9
2017-11-16 17:55





Aşağıdakileri göz önünde bulundurarak, statik bir yöntem sonunu oluşturmayı düşünecek konumda kendinizi bulabilirsiniz:

Aşağıdaki sınıflara sahip olmak:

class A {
    static void ts() {
        System.out.print("A");
    }
}
class B extends A {
    static void ts() {
        System.out.print("B");
    }
}

Şimdi bu yöntemleri çağırmanın 'doğru' yolu

A.ts();
B.ts();

sonuçta AB ancak aynı zamanda örneklerde yöntemleri de arayabilirsiniz:

A a = new A();
a.ts();
B b = new B();
b.ts();

sonuçta AB de.

Şimdi aşağıdakileri dikkate alın:

A a = new B();
a.ts();

Bu yazdırır A. Sınıfta bir nesneye sahip olmanızdan dolayı bu sizi şaşırtabilir B. Ama sen onu bir referans türünden çağırıyorsun A, arayacak A.ts(). Yazdırabilirsiniz B aşağıdaki kod ile:

A a = new B();
((B)a).ts();

Her iki durumda da sahip olduğunuz nesne aslında sınıftan B. Ancak, nesneye işaret eden göstericiye bağlı olarak, A ya da B.

Şimdi sınıfın geliştiricisi olduğunu söyleyelim A ve alt sınıfa izin vermek istiyorsunuz. Ama sen gerçekten bir yöntem istiyorsun ts(), bir alt sınıftan bile çağrıldığında, bunu yapmak istediğiniz şeyi yapar ve bir alt sınıf sürümü tarafından gizlenmemelidir. O zaman yapabilirsin. finalve alt sınıfa gizlenmesini önler. Ve aşağıdaki kodun, sınıfınızdan yöntemi çağırdığından emin olabilirsiniz. A:

B b = new B();
b.ts();

Tamam, bir şekilde inşa edilmiş, ama bazı durumlarda mantıklı olabilir.

Örnekler üzerinde ancak doğrudan sınıflardaki statik yöntemleri çağırmamalısınız - o zaman bu sorun olmaz. Örneğin IntelliJ IDEA örneğinde bir statik yöntem çağrılırsa ve statik bir yöntem sonlandırırsanız, size bir uyarı gösterecektir.


5
2017-09-12 11:53





Derleme hatasının burada oldukça yanıltıcı olduğunu düşünüyorum. "Geçersiz kılınmış yöntem statik final" dememeli, bunun yerine "geçersiz kılınmış yöntem son" demelidir. Statik değiştirici burada alakasız.


1
2017-11-16 18:10



Yani B'deki statik metodu A'da geçersiz kılıyor musunuz? - Koray Tugay
@KorayTugay Sadece derleyicinin önce potansiyel geçersiz bir yöntem (bir an için statik olarak göz ardı edilir), başarısız olarak son noktayı görür. Sadece vahşi bir tahmin olsa - Eugene
Balus, bence StackOverflow'taki tek düşük kaliteli cevap bu. Tüm istisnai cevaplarınız göz önünde bulundurulduğunda, bu onlara ait değildir. @BalusC - Koray Tugay
@KorayTugay: o zaman yorum yapmak için yeterince itibarım yoktu :) Eğer geri ping yaparsan, cevabı sileceğim, sorun değil. - BalusC


B'deki ts () yöntemi, A'da ts () yöntemini geçersiz kılmaz, sadece başka bir yöntemdir. B sınıfı, statik olduğu için ts () yöntemini görmez, bu nedenle ts () olarak adlandırılan kendi yöntemini bildirebilir.

Ancak, yöntem sonlanırsa, derleyici, A'da B'de geçersiz kılınmaması gereken bir ts () yönteminin bulunduğunu alır.


0
2017-11-16 17:49



Bunun, 'final' in neden birdenbire bu yöntemlerin bir arada bulunamayacağı anlamına geldiğini açıklayamıyorum. Dediğin gibi, 'final' olmadan, sorun yok. Bunun geçersiz sayılmadığını söylüyorsunuz, ama sonra sorunun B'nin A'nın yöntemini geçersiz kılmayacağı olduğunu söylüyorsunuz. - Sean Owen
Tabii ki, B'nin A'da ts () yöntemini görmediğini belirtiyorum (bu 'gizli'), ancak son değiştirici, bir diğerini uzatan sınıflardan gelen yöntemleri 'gizlemez'. Ama eh, tamam. - amischiefr