Java'da son anahtar kelimenin kullanımı performansı artırır mı?


347

Java'da, finalanahtar kelimenin kullanılabileceği, ancak kullanımının nadir olduğu birçok yer görüyoruz .

Örneğin:

String str = "abc";
System.out.println(str);

Yukarıdaki durumda, strolabilirfinal ancak bu genellikle bırakılır.

Bir yöntem hiçbir zaman geçersiz kılmayacaksa, son anahtar kelimeyi kullanabiliriz. Benzer şekilde miras alınmayacak bir sınıf durumunda.

Nihai anahtar kelimenin bu durumların herhangi birinde veya hepsinde kullanılması performansı gerçekten artırıyor mu? Eğer öyleyse, nasıl? Lütfen açıkla. finalPerformans için gerçekten doğru bir şekilde kullanılması önemliyse, bir Java programcısı anahtar kelimeyi en iyi şekilde kullanmak için hangi alışkanlıkları geliştirmelidir?


Ben öyle düşünmüyorum, yöntem gönderme (çağrı sitesi önbelleğe alma ve ...) statik dilde değil dinamik dillerde bir sorun
Jahan

İnceleme amacıyla kullanılan PMD aracımı (eclipse eklentisi) çalıştırırsam, yukarıda gösterildiği gibi değişken için değişiklikler yapmanızı öneririz. Ama onun konseptini anlamadım. Gerçekten performans çok vuruyor ??
Abhishek Jain

5
Bunun tipik bir sınav sorusu olduğunu düşündüm. Final hatırlıyorum yapar onlar sınıflandırma edilemez çünkü IIRC nihai sınıfları bir şekilde JRE tarafından optimize edilebilir, performansa etkisi vardır.
Kawu

Aslında bunu test ettirdim. Tüm JVMs ben yerel değişkenler üzerinde son kullanımını test yaptım performansını artırmak (biraz, ama yine de yarar yöntemlerinde bir faktör olabilir). Kaynak kodu aşağıdaki cevabımda.
rustyx

1
"erken optimizasyon tüm kötülüklerin köküdür". Derleyicinin işini yapmasına izin ver. Okunabilir ve iyi yorumlanmış kod yazın. Bu her zaman en iyi seçimdir!
kaiser

Yanıtlar:


285

Genellikle hayır. Sanal yöntemler için HotSpot, yöntemin gerçekten geçersiz kılınmış olup olmadığını izler ve bir yöntemin geçersiz kılmadığı varsayımına ( yöntemi geçersiz kılan bir sınıfı yükleyene kadar) hangi optimizasyonları gerçekleştirebilir? bu optimizasyonları geri alabilir (veya kısmen geri alabilir).

(Tabii ki, bu HotSpot kullandığınızı varsayar - ancak bu en yaygın JVM, yani ...)

Bence finalperformans nedenlerinden ziyade net bir tasarıma ve okunabilirliğe dayanmalı. Performans nedenleriyle herhangi bir şeyi değiştirmek isterseniz, en net kodu şeklin dışında bükmeden önce uygun ölçümleri yapmalısınız - böylece elde edilen ekstra performansın daha düşük okunabilirliğe / tasarıma değip değmeyeceğine karar verebilirsiniz. (Deneyimlerime göre neredeyse hiç değmez; YMMV.)

DÜZENLEME: Son alanlardan bahsedildiği gibi, açık tasarım açısından, genellikle iyi bir fikir olduklarını ortaya koymaya değer. Ayrıca, çapraz iplik görünürlüğü açısından garantili davranışı değiştirirler: bir kurucu tamamlandıktan sonra, son alanların hemen diğer iş parçacıklarında görünür olması garanti edilir. finalJosh Bloch'un "miras için tasarım veya onu yasaklamak" kuralının destekçisi olarak , muhtemelen tecrübelerimin en yaygın kullanımı, muhtemelen finalsınıflar için daha sık kullanmalıyım ...


1
@Abhishek: Özellikle ne hakkında? En önemli nokta sonuncusu - neredeyse kesinlikle bu konuda endişelenmemelisiniz.
Jon Skeet

9
@Abishek: finalgenellikle kodun anlaşılmasını kolaylaştırdığı ve hataları bulmaya yardımcı olduğu için önerilir (çünkü programcıları niyeti açık hale getirir). PMD, muhtemelen finalperformans nedenleriyle değil, bu stil sorunları nedeniyle kullanılmasını önerir .
sleske

3
@Abhishek: Birçoğunun JVM'ye özgü olması muhtemeldir ve bağlamın çok ince yönlerine güvenebilir. Örneğin, HotSpot sunucusu JVM'nin bir sınıfta geçersiz kılındığında sanal yöntemlerin satır içine alınmasına izin vereceğine ve uygun olan yerlerde hızlı bir tür denetimine sahip olacağına inanıyorum . Ancak ayrıntıların sabitlenmesi zordur ve serbest bırakılanlar arasında değişebilir.
Jon Skeet

5
İşte, Etkili Java, 2nd Edition, Öğe 15 alıntı mutability Minimize olacaktır: Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.. Ayrıca An immutable object can be in exactly one state, the state in which it was created.vs Mutable objects, on the other hand, can have arbitrarily complex state spaces.. Kişisel deneyimlerime göre, anahtar kelimeyi kullanmak finalgeliştiricinin kodu "optimize etmek" değil, değişmezliğe doğru eğilme niyetini vurgulamalıdır. Bu bölümü okumanızı tavsiye ederim, büyüleyici!
Louis

2
Diğer cevaplar, finalanahtar kelimeyi değişkenler üzerinde kullanmanın bayt kodu miktarını azaltabildiğini ve bu da performans üzerinde etki yaratabileceğini göstermektedir.
Julien Kronegg

86

Kısa cevap: Endişelenme!

Uzun cevap:

Nihai yerel değişkenler hakkında konuşurken , anahtar kelimeyi kullanmanın final, derleyicinin kodu statik olarak optimize etmesine yardımcı olacağını ve sonuçta daha hızlı kodla sonuçlanabileceğini unutmayın. Örneğin, a + başağıdaki örnekteki son Dizeler statik olarak birleştirilir (derleme zamanında).

public class FinalTest {

    public static final int N_ITERATIONS = 1000000;

    public static String testFinal() {
        final String a = "a";
        final String b = "b";
        return a + b;
    }

    public static String testNonFinal() {
        String a = "a";
        String b = "b";
        return a + b;
    }

    public static void main(String[] args) {
        long tStart, tElapsed;

        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method with finals took " + tElapsed + " ms");

        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testNonFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method without finals took " + tElapsed + " ms");

    }

}

Sonuç?

Method with finals took 5 ms
Method without finals took 273 ms

Java Hotspot VM 1.7.0_45-b18 üzerinde test edilmiştir.

Peki gerçek performans artışı ne kadar? Söylemeye cesaret edemem. Çoğu durumda muhtemelen marjinal (bu sentetik testte ~ 270 nanosaniye, çünkü dize birleşiminden tamamen kaçınılır - nadir bir durum), ancak oldukça optimize edilmiş yardımcı program kodunda bir faktör olabilir . Her durumda, orijinal sorunun cevabı evet, performansı artırabilir, ancak en iyi ihtimalle .

Derleme zamanı avantajları bir yana, anahtar kelime kullanımının finalperformans üzerinde ölçülebilir bir etkisi olduğuna dair herhangi bir kanıt bulamadım .


2
Her iki durumu da 100 kez test etmek için kodunuzu biraz yeniden yazdım. Sonunda finalin ortalama süresi finali olmayanlar için 0 ms ve 9 ms idi. Yineleme sayısının 10M'ye çıkarılması, ortalamayı 0 ms ve 75 ms'ye ayarlar. Final olmayanlar için en iyi çalışma 0 ms idi. Belki de VM tespit sonuçlarını sadece atıyor falan? Bilmiyorum ama ne olursa olsun, final kullanımı önemli bir fark yaratıyor.
Casper Færgemand

5
Kusurlu test. Daha önceki testler JVM'yi ısıtacak ve daha sonraki test çağrılarına fayda sağlayacaktır. Testlerinizi yeniden sıralayın ve ne olduğunu görün. Her testi kendi JVM örneğinde çalıştırmanız gerekir.
Steve Kuo

16
Hiçbir test kusurlu değil, ısınma dikkate alındı. İkinci test HIZLI, daha hızlı değil. Isınma olmazsa ikinci test ÇİÇEK OLACAKTIR.
rustyx

6
TestFinal () öğesinde tüm zamanlar aynı nesneyi, dizeler havuzundan döndürdü, çünkü son dizelerin ve dizgi değişmezlerinin birleştirilmesinin yeniden derleme zamanında değerlendirildi. testNonFinal () her yeni nesneyi döndürdüğünde, hızdaki farkı açıklar.
anber

4
Senaryonun gerçekçi olmadığını düşündüren nedir? Stringbirleştirme, eklemekten çok daha maliyetli bir işlemdir Integers. Statik (mümkünse) yapmak daha verimlidir, testin gösterdiği budur.
rustyx

62

Evet yapabilir. Finalin performansı artırabileceği bir örnek:

Koşullu derleme , kod satırlarının belirli bir koşula bağlı olarak sınıf dosyasına derlenmediği bir tekniktir. Bu, bir üretim yapısında tonlarca hata ayıklama kodunu kaldırmak için kullanılabilir.

aşağıdakileri göz önünde bulundur:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (doSomething) {
       // do first part. 
    }

    if (doSomething) {
     // do second part. 
    }

    if (doSomething) {     
      // do third part. 
    }

    if (doSomething) {
    // do finalization part. 
    }
}

DoSomething özniteliğini son bir özniteliğe dönüştürerek, derleyiciye doSomething'i her gördüğünde derleme zamanı değiştirme kurallarına göre false ile değiştirmesi gerektiğini söylediniz. Derleyici ilk geçiş kodu değiştirir şey böyle:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (false){
       // do first part. 
    }

    if (false){
     // do second part. 
    }

    if (false){
      // do third part. 
    }

    if (false){
    // do finalization part. 

    }
}

Bu yapıldıktan sonra, derleyici ona bir kez daha bakar ve kodda erişilemez ifadeler olduğunu görür. En kaliteli bir derleyici ile çalıştığınız için, erişilemeyen bayt kodlarının hepsini sevmez. Böylece onları kaldırır ve bununla sonuçlanırsınız:

public class ConditionalCompile {


  private final static boolean doSomething= false;

  public static void someMethodBetter( ) {

    // do first part. 

    // do second part. 

    // do third part. 

    // do finalization part. 

  }
}

böylece aşırı kodları veya gereksiz koşullu kontrolleri azaltır.

Düzenleme: Örnek olarak, aşağıdaki kodu alalım:

public class Test {
    public static final void main(String[] args) {
        boolean x = false;
        if (x) {
            System.out.println("x");
        }
        final boolean y = false;
        if (y) {
            System.out.println("y");
        }
        if (false) {
            System.out.println("z");
        }
    }
}

Bu kodu Java 8 ile derlerken ve kod çözerken javap -c Test.class:

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static final void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: ifeq          14
       6: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       9: ldc           #22                 // String x
      11: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      14: iconst_0
      15: istore_2
      16: return
}

Derlenmiş kodun yalnızca son olmayan değişkeni içerdiğini belirtebiliriz x. Bu, son değişkenlerin en azından bu basit durum için performanslar üzerinde etkisi olduğunu kanıtlamaktadır.


1
@ AsukaszLech Bunu bir Oreilly kitabından öğrendim: Hardcore Java, son anahtar kelimeyle ilgili bölümlerinde.
mel3kings

15
Bu derleme zamanında optimizasyon hakkında konuşur, geliştirici derleme zamanında nihai boole değişkeninin VALUE değerini bilir, IF-CONDITIONS gerekli olmayan ve yapmayan bu senaryo için ilk etapta bloklar varsa tüm yazma noktası nedir bir anlamı var mı? Kanımca, bu performansı artırsa bile, bu ilk etapta yanlış koddur ve sorumluluğu derleyiciye iletmek yerine geliştiricinin kendisi tarafından optimize edilebilir ve soru esas olarak finalin kullanıldığı olağan kodlardaki performans iyileştirmelerini sormayı amaçlamaktadır. programlı bir anlam ifade eder.
Bhavesh Agarwal

7
Bunun amacı, mel3kings'in belirttiği gibi hata ayıklama ifadeleri eklemek olacaktır. Değişkeni bir üretim derlemesinden önce çevirebilir (veya derleme komut dosyalarınızda yapılandırabilirsiniz) ve dağıtım oluşturulduğunda bu kodun tümünü otomatik olarak kaldırabilirsiniz.
Adam


16

Hiç kimse aslında en azından bazı küçük bir fark olduğunu kanıtlamak için derlenmiş bazı gerçek kod yayınlamamasına şaşırdım.

Başvuru için buna karşı test edilmiştir javacsürümü 8, 9ve10 .

Bu yöntemi varsayalım:

public static int test() {
    /* final */ Object left = new Object();
    Object right = new Object();

    return left.hashCode() + right.hashCode();
}

Olduğu gibi bu kod derleme üreten tam olduğu gibi aynı bayt kodu finalmevcut olurdu (final Object left = new Object(); ).

Ama bu:

public static int test() {
    /* final */ int left = 11;
    int right = 12;
    return left + right;
}

üretir:

   0: bipush        11
   2: istore_0
   3: bipush        12
   5: istore_1
   6: iload_0
   7: iload_1
   8: iadd
   9: ireturn

Ayrılma finalüreten mevcut olması:

   0: bipush        12
   2: istore_1
   3: bipush        11
   5: iload_1
   6: iadd
   7: ireturn

Kod hemen hemen kendinden açıklayıcıdır, derleme zaman sabiti varsa, doğrudan işlenen yığınına yüklenir (önceki örneğin yaptığı gibi yerel değişkenler dizisine depolanmaz bipush 12; istore_0; iload_0) - hangi mantıklı çünkü kimse değiştiremez.

Öte yandan derleyicinin üretmediği ikinci durumda istore_0 ... iload_0benden öte, bu yuvanın 0herhangi bir şekilde kullanıldığı gibi değil (değişken dizisini bu şekilde küçültebilir, ancak bazı iç detayları eksik olabilirim, yapamıyorum kesin söyle)

Ne kadar küçük olduklarını göz önünde bulundurarak böyle bir optimizasyonu gördüğüme şaşırdım javac. Her zaman kullanmalı mıyız final? Ben bile JMH(başlangıçta istedim) bir test yazmak için gitmiyorum , fark ns(mümkün olduğunca hiç yakalanması için) sırasına eminim . Bunun bir sorun olabileceği tek yer, bir yöntemin boyutu nedeniyle satır içine alınamamasıdır (ve bildirme finalbu boyutu birkaç bayt küçülterek).

finalEle alınması gereken iki tane daha var . Birincisi, bir yöntemin final(bir JITperspektiften) olduğu zaman , böyle bir yöntemin monomorfik olmasıdır - ve bunlar tarafından en sevilenlerdirJVM .

Sonra finalörnek değişkenleri vardır (her kurucuda ayarlanması gerekir); bunlar, burada biraz dokunulduğunda ve tam olarak tarafından belirtildiği gibi , doğru bir şekilde yayınlanmış bir referansı garanti edeceklerinden önemlidir JLS.


Kod hata ayıklama seçenekleri () ile Java 8 (JDK 1.8.0_162) kullanarak derledi, kodunu kullanarak javac -g FinalTest.javadecompiled javap -c FinalTest.classve ( final int left=12ben var bipush 11; istore_0; bipush 12; istore_1; bipush 11; iload_1; iadd; ireturn) aynı sonuçları elde etmedi . Yani evet, üretilen bayt kodu birçok faktöre bağlıdır ve finalperformans üzerinde bir etki yaratıp yaratmadığını söylemek zordur . Ancak bayt kodu farklı olduğundan, bazı performans farklılıkları olabilir.
Julien Kronegg


13

Gerçekten iki (en azından) farklı vaka soruyorsunuz:

  1. final yerel değişkenler için
  2. final yöntemler / sınıflar için

Jon Skeet zaten cevap verdi 2). Yaklaşık 1):

Bunun bir fark yarattığını düşünmüyorum; yerel değişkenler için, derleyici değişkenin nihai olup olmadığını belirleyebilir (sadece birden fazla atanıp atanmadığını kontrol ederek). Dolayısıyla, derleyici yalnızca bir kez atanan değişkenleri optimize etmek isterse, değişkenin gerçekten bildirilip bildirilmediğine bakılmaksızın bunu yapabilir final.

final olabilir korumalı / public class alanları için bir fark yaratmak; derleyicinin alanın bir kereden fazla ayarlanıp ayarlanmadığını öğrenmesi çok zordur, çünkü farklı bir sınıftan (yüklenmemiş olabilir) olabilir. Ancak o zaman bile JVM, Jon'un tanımladığı tekniği kullanabilir (iyimser olarak optimize edin, alanı değiştiren bir sınıf yüklüyse geri alın).

Özet olarak, performansa yardımcı olması için herhangi bir neden göremiyorum. Yani bu tür bir mikro optimizasyonun yardımcı olması pek olası değildir. Emin olmak için karşılaştırmayı deneyebilirsiniz, ancak bunun bir fark yaratacağından şüpheliyim.

Düzenle:

Aslında Timo Westkämper cevabı göre final olabilir bazı durumlarda sınıf alanları için performansını artırmak. Ben düzeltilmiş duruyorum.


Derleyici doğru bir yerel değişken atanmış sayısını kontrol edebilirsiniz sanmıyorum: Ya if-then-else çok sayıda atamaları ile yapılandırır?
gyorgyabraham

1
@gyabraham: Derleyici, yerel değişkeni finaliki kez atamadığınızdan emin olmak için bu vakaları zaten denetler . Görebildiğim kadarıyla, aynı kontrol mantığı bir değişkenin olup olmadığını kontrol etmek için kullanılabilir (ve muhtemelen) final.
sleske

Yerel bir değişkenin nihai yapısı bayt kodunda ifade edilmez, bu nedenle JVM bunun nihai olduğunu bile bilmez
Steve Kuo

1
@SteveKuo: Bayt kodunda ifade edilmese bile, javacdaha iyi optimizasyona yardımcı olabilir . Ama bu sadece spekülasyon.
sleske

1
Derleyici, yerel bir değişkenin tam olarak bir kez atanıp atanmadığını bulabilir, ancak pratikte (hata kontrolünün ötesinde) bunu yapmaz. Öte yandan, bir finaldeğişken ilkel tipte veya türde ise Stringve hemen sorunun örneğinde olduğu gibi derleme zamanı sabiti ile atanırsa , değişken şartname başına bir derleme zamanı sabiti olduğundan derleyici satır içi olmalıdır . Ancak çoğu kullanım durumunda, kod farklı görünebilir, ancak sabitin performans açısından yerel bir değişkenten okunması veya okunması hala fark etmez.
Holger

6

Not: Java uzmanı değil

Java'mı doğru hatırlarsam, son anahtar kelimeyi kullanarak performansı artırmanın çok az yolu olurdu. Ben her zaman "iyi kod" için varlığını biliyordum - tasarım ve okunabilirlik.


1

Ben bir uzman değilim, ancak finalüzerine yazılmaz ve değişkenleri yalnız bırakmazsanız, sınıfa veya yönteme anahtar kelime eklemeniz gerekir . Bu tür şeyleri optimize etmenin herhangi bir yolu varsa, derleyici bunu sizin için yapacaktır.


1

Aslında, OpenGL ile ilgili bazı kodları test ederken, özel bir alanda son değiştiriciyi kullanmanın performansı düşürebileceğini buldum . İşte test ettiğim sınıfın başlangıcı:

public class ShaderInput {

    private /* final */ float[] input;
    private /* final */ int[] strides;


    public ShaderInput()
    {
        this.input = new float[10];
        this.strides = new int[] { 0, 4, 8 };
    }


    public ShaderInput x(int stride, float val)
    {
        input[strides[stride] + 0] = val;
        return this;
    }

    // more stuff ...

Ve bu, ShaderInput sınıfının da dahil olduğu çeşitli alternatiflerin performansını test etmek için kullandığım yöntem:

public static void test4()
{
    int arraySize = 10;
    float[] fb = new float[arraySize];
    for (int i = 0; i < arraySize; i++) {
        fb[i] = random.nextFloat();
    }
    int times = 1000000000;
    for (int i = 0; i < 10; ++i) {
        floatVectorTest(times, fb);
        arrayCopyTest(times, fb);
        shaderInputTest(times, fb);
        directFloatArrayTest(times, fb);
        System.out.println();
        System.gc();
    }
}

3. yinelemeden sonra, VM ısındığında, bu rakamları sürekli olarak son anahtar kelime olmadan aldım :

Simple array copy took   : 02.64
System.arrayCopy took    : 03.20
ShaderInput took         : 00.77
Unsafe float array took  : 05.47

İle final anahtar:

Simple array copy took   : 02.66
System.arrayCopy took    : 03.20
ShaderInput took         : 02.59
Unsafe float array took  : 06.24

ShaderInput testi rakamlarını not edin.

Alanları herkese açık mı yoksa özel mi yaptığım önemli değildi.

Bu arada, birkaç şaşırtıcı şey var. ShaderInput sınıfı, son anahtar kelimeyle bile diğer tüm varyantlardan daha iyi performans gösterir. Bu dikkat çekici bir b / c, temelde bir float dizisini saran bir sınıftır, diğer testler doğrudan diziyi manipüle eder. Bunu çözmeliyim. ShaderInput'un akıcı arayüzü ile bir ilgisi olabilir.

Ayrıca System.arrayCopy aslında küçük diziler için bir for döngüsünde öğeleri bir diziden diğerine kopyalamaktan biraz daha yavaştır. Ve sun.misc.Unsafe (burada gösterilmeyen doğrudan java.nio.FloatBuffer'ın yanı sıra) kullanarak uçsuz bucaksız performans gösterir.


1
Parametreleri sonlandırmayı unuttun. <pre> <code> genel ShaderInput x (son int adım, son kayan değer) {input [strides [stride] + 0] = val; bunu iade et; } </code> </pre> Deneyimlerime göre, herhangi bir değişken veya alan finali yapmak gerçekten performansı artırabilir.
Anticro

1
Oh, ve diğerlerini de sonlandır: <pre> <code> final int arraySize = 10; final float [] fb = yeni float [arraySize]; for (int i = 0; i <arraySize; i ++) {fb [i] = random.nextFloat (); } son int süreleri = 1000000000; for (int i = 0; i <10; ++ i) {floatVectorTest (times, fb); arrayCopyTest (times, fb); shaderInputTest (süreler, fb); directFloatArrayTest (times, fb); System.out.println (); System.GC (); } </code> </pre>
Anticro

1

Nihai (En azından üye değişkenler ve parametreler için) insanlar için daha fazladır, o zaman makine içindir.

Değişkenleri mümkün olduğunca nihai yapmak iyi bir uygulamadır. Keşke Java varsayılan olarak "değişkenleri" son yapmış ve değişikliklere izin vermek için bir "Değişken" anahtar kelimesi olsaydı. Değişmez sınıflar çok daha iyi iş parçacığı koduna yol açar ve sadece her üyenin önünde "final" olan bir sınıfa göz atmak hızlı bir şekilde değişmez olduğunu gösterecektir.

Başka bir durum - @ NonNull / @ Nullable ek açıklamalarını kullanmak için çok fazla kod dönüştürüyorum (Bir method parametresinin boş olmaması gerektiğini söyleyebilirim, sonra IDE, @ etiketli olmayan bir değişkeni geçtiğiniz her yerde sizi uyarabilir NonNull - her şey saçma bir dereceye yayılır). Bir üye değişkenin veya parametrenin nihai olarak etiketlendiğinde boş bırakılamayacağını kanıtlamak çok daha kolaydır, çünkü başka bir yere yeniden atanmadığını bilirsiniz.

Benim önerim varsayılan olarak üyeler ve parametreler için final uygulama alışkanlığı almaktır, Sadece birkaç karakter ama başka hiçbir şey yoksa kodlama stilinizi geliştirmek için sizi teşvik edecektir.

Yöntemler veya sınıflar için son başka bir kavramdır, çünkü çok geçerli bir yeniden kullanım şekline izin vermez ve okuyucuya fazla bir şey söylemez. En iyi kullanım muhtemelen her yerde tutarlı davranış güvenebilirsiniz böylece Dize ve diğer iç türleri son yapılan şeklidir - Bu hataların bir sürü (her ne kadar ben dize uzatmak için SEVDİ olurdu ....) olasılık)


0

Başka yerlerde de belirtildiği gibi, yerel bir değişken için 'nihai' ve biraz daha az bir ölçüde üye değişken, daha çok bir stil meselesidir.

'final' değişkeni değiştirmemeyi düşündüğünüz bir ifadedir (yani, değişken değişmez!). Derleyici kendi sınırınızı ihlal ederseniz şikayet ederek size yardımcı olabilir.

Tanımlayıcılar (üzgünüm, sadece değişken olmayan bir şeyi 'değişken' olarak adlandıramazsam) varsayılan olarak son olsaydı ve bunların değişken olduğunu açıkça belirtmeniz gerekiyorsa Java'nın daha iyi bir dil olacağı fikrini paylaşıyorum. Ama bunu söyledikten sonra, genellikle başlatılmış ve asla atanmamış yerel değişkenler üzerinde 'final' kullanmıyorum; sadece çok gürültülü görünüyor.

(Üye değişkenlerde final kullanıyorum)


-3

Final ile ilan edilen üyeler, program dışı olarak kullanılacağından, bu üyeler programda kullanılmazsa, yine de Çöp Toplayıcı tarafından ilgilenilmezler, bu nedenle kötü bellek yönetimi nedeniyle performans sorununa neden olabilirler.


2
Bu ne tür bir saçmalık? Bunun neden böyle olduğunu düşündüğünüz herhangi bir kaynağınız var mı?
J. Doe

-4

final anahtar kelime Java'da beş şekilde kullanılabilir.

  1. Bir sınıf kesindir
  2. Bir referans değişkeni kesindir
  3. Yerel bir değişken kesindir
  4. Bir yöntem kesindir

Bir sınıf kesindir: bir sınıf son demektir, genişletilemeyeceğimiz anlamına gelir veya kalıtım, kalıtım mümkün değildir demektir.

Benzer şekilde - Bir nesne kesindir: bir süre nesnenin iç durumunu değiştirmiyoruz, bu durumda nesnenin nihai nesne olduğunu belirtebiliriz. Nesne son değişken de nihai değil anlamına gelir.

Referans değişkeni sonlandırıldığında, başka bir nesneye yeniden atanamaz. Ancak, alanları son olmadığı sürece nesnenin içeriğini değiştirebilir


2
"Nesne son" demekle "nesne değişmez" demek istediniz.
gyorgyabraham

6
Haklısın, ama soruyu cevaplamıyorsun. OP ne finalanlama geldiğini sormadı , ama kullanmanın finalperformansı etkileyip etkilemediğini.
Honza Zidek
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.