Java'daki “final” anahtar kelimesi nasıl çalışır? (Yine de bir nesneyi değiştirebilirim.)


480

Java'da final, değerlerinin değiştirilmeyeceğini belirtmek için değişkenlere sahip anahtar kelime kullanırız . Ama görüyorum ki sınıfın yapıcı / yöntemlerindeki değeri değiştirebilirsin. Yine, eğer değişken staticise bir derleme hatasıdır.

İşte kod:

import java.util.ArrayList;
import java.util.List;

class Test {
  private final List foo;

  public Test()
  {
      foo = new ArrayList();
      foo.add("foo"); // Modification-1
  }
  public static void main(String[] args) 
  {
      Test t = new Test();
      t.foo.add("bar"); // Modification-2
      System.out.println("print - " + t.foo);
  }
}

Yukarıdaki kod iyi çalışıyor ve hata yok.

Şimdi değişkeni şu şekilde değiştirin static:

private static final List foo;

Şimdi bir derleme hatası. Bu finalgerçekten nasıl çalışıyor?


foo görünür olmadığından nasıl derlenebilir?
Björn Hallström

5
@terealprashant bu doğru değil. Özel statik değişkenler geçerlidir, tanımlandıkları sınıf içindeki statik yöntemlerden erişilebilirler. Statik değişken, değişkenin bir kez var olduğu ve bir sınıf örneğine bağlı olmadığı anlamına gelir.
mbdavis

3
@mbdavis Oh Evet! teşekkür ederim. Ama yine de benim gibi düşünen insanlara yardımcı olmak için yorumu silmeyeceğim ve yorumunuz doğru yönde düşünmelerini sağlayacaktır.
therealprashant

@ therealprashant tamam endişelenme!
mbdavis

Yanıtlar:


518

Bir değişkeni her zaman başlatmanıza izin verilir final. Derleyici bunu yalnızca bir kez yapabilmenizi sağlar.

Bir finaldeğişkende saklanan bir nesnenin çağrı yöntemlerinin anlambilimiyle ilgisi olmadığını unutmayın final. Başka bir deyişle: finalsadece referansın kendisiyle ilgilidir ve referans verilen nesnenin içeriği ile ilgili değildir.

Java'nın nesne değişmezliği kavramı yoktur; bu, nesneyi dikkatlice tasarlayarak başarılır ve önemsiz bir çabadır.


12
t.foo = new ArrayList (); Eğer derleme hatası alırsınız ana yönteminde ve ... referans foo ArrayList sadece bir final nesneye binded edilir ... elinden başka ArrayList değil noktası
Code2Interface

50
hmmm. Onun referans ile ilgili tüm değer değil. Teşekkürler!
GS

2
Bir sorum var. Tanıdığım bir kişi "final" de değişkeni yığın üzerinde saklar. Bu doğru mu? Her yerde arama yaptım ve bu iddiayı onaylayabilecek veya reddedebilecek herhangi bir referans bulamadım. Hem Java hem de Android dokümanlarını araştırdım. Ayrıca "Java bellek modeli" arandı. Belki C / C ++ üzerinde bu şekilde çalışır, ama Java üzerinde bu şekilde çalıştığını sanmıyorum. Doğrumuyum?
android geliştirici

4
@androiddeveloper Java'daki hiçbir şey yığın / yığın yerleşimini açıkça denetleyemez. Daha spesifik olarak, HotSpot JIT derleyicisi tarafından karar verilen yığın yerleşimi, bir değişkenin olup olmadığını kontrol etmekten çok daha fazla olan kaçış analizine tabidir final. Değişken nesneler de yığın tahsis edilebilir. finalalanlar kaçış analizine yardımcı olabilir , ancak bu oldukça dolaylı bir yoldur. Ayrıca, son değişkenlerin etkili bir şekildefinal kaynak kodunda işaretlenenlerle aynı muameleye sahip olduğuna dikkat edin .
Marko Topolnik

5
finalsınıf dosyasında bulunur ve en uygun çalışma zamanı için önemli anlamsal sonuçları vardır. JLS, bir nesnenin alanlarının tutarlılığı konusunda güçlü bir garantiye sahip olduğundan maliyetlere de neden olabilir final. Örneğin, ARM işlemcisi, finalalanları olan bir sınıfın her kurucusunun sonunda açık bir bellek engelleme talimatı kullanmalıdır . Ancak diğer işlemcilerde buna gerek yoktur.
Marko Topolnik

574

Bu favori bir röportaj sorusu . Bu sorularla görüşmeci, nesnelerin yapıcılara, yöntemlere, sınıf değişkenlerine (statik değişkenler) ve örnek değişkenlere ilişkin davranışlarını ne kadar iyi anladığınızı bulmaya çalışır.

import java.util.ArrayList;
import java.util.List;

class Test {
    private final List foo;

    public Test() {
        foo = new ArrayList();
        foo.add("foo"); // Modification-1
    }

    public void setFoo(List foo) {
       //this.foo = foo; Results in compile time error.
    }
}

Yukarıdaki durumda, 'Test' için bir yapıcı tanımladık ve ona 'setFoo' yöntemi verdik.

Yapıcı hakkında: Yapıcı , anahtar kelime kullanılarak nesne oluşturma başına yalnızca bir kez çağrılabilir new. Yapıcı birden çok kez çağıramazsınız, çünkü yapıcı bunu yapmak için tasarlanmamıştır.

Yöntem hakkında: Bir yöntem istediğiniz kadar çağrılabilir (Asla bile) ve derleyici bunu bilir.

Senaryo 1

private final List foo;  // 1

foobir örnek değişkendir. TestSınıf nesnesi oluşturduğumuzda , örnek değişkeni foo, sınıf nesnesinin içine kopyalanır Test. Biz atarsanız fookurucu içinde, sonra derleyici yapıcı yalnızca bir kez çağrılan olacağını biliyor, bu yüzden yapıcı içine atama sorun yoktur.

Biz atarsanız foobir yöntem içinde, derleyici bir yöntem değeri için izin verilmez birden çok kez değişti gerekecektir anlamına gelen birden çok kez çağrılabilir bilir finaldeğişken. Derleyici yapıcı iyi bir seçim olduğuna karar verir! Son değişkene yalnızca bir kez bir değer atayabilirsiniz.

Senaryo 2

private static final List foo = new ArrayList();

fooartık statik bir değişkendir. Bir Testsınıf örneği oluşturduğumuzda , statik olduğu fooiçin nesneye kopyalanmayacaktır foo. Şimdi fooher nesnenin bağımsız bir özelliği değildir. Bu Testsınıfın bir özelliğidir . Ancak foobirden çok nesne tarafından görülebilir ve newsonuçta Testbirden çok nesne oluşturma sırasında değeri değiştiren yapıcıyı çağıracak anahtar kelime kullanılarak oluşturulan her nesne (Unutmayın static fooher nesnede kopyalanmaz, ancak birden çok nesne arasında paylaşılır) .)

Senaryo 3

t.foo.add("bar"); // Modification-2

Yukarıdaki Modification-2sorudan. Yukarıdaki durumda, başvurulan ilk nesneyi değiştirmiyorsunuz, ancak içine fooizin verilen içeriği ekliyorsunuz . Derleyici new ArrayList(), foobaşvuru değişkenine a atamaya çalışırsanız şikayet eder .
Kural Bir finaldeğişkeni başlattıysanız, değişkeni farklı bir nesneye başvuracak şekilde değiştiremezsiniz. (Bu durumda ArrayList)

final sınıfları alt sınıflara ayrılamaz
final yöntemleri geçersiz kılınamaz. (Bu yöntem üst sınıftadır)
son yöntemler geçersiz kılabilir. (Bunu dilbilgisel bir şekilde okuyun. Bu yöntem bir alt sınıftadır)


1
Sadece net olmak için. Senaryo 2'de , Test sınıfında ayarlanmış ve birden çok Test örneği oluşturulmuşsa foo, son atamaya rağmen bunun birden çok kez ayarlanacağını mı söylüyorsunuz foo?
Rawr

Senaryo 2 için son satırı anlamadım: Ama fooolabilir .. birden fazla nesne.) Bu, eğer bir anda birden fazla nesne oluşturursam, o zaman hangi nesneyi nihai değişkeni başlatan yürütmeye bağlıdır anlamına gelir?
Saumya Suhagiya

1
Senaryo 3 hakkında düşünmek için yararlı bir yol olduğunu düşünüyorum bir ArrayList finalbaşvurulan bellek adresine atama foo. Sen atama değildir finalilk elemanı tarafından başvurulan bellek adresine foo(ya da bu konuda herhangi bir öğe). Bu nedenle değiştiremezsiniz fooama değiştirebilirsiniz foo[0].
Pinkerton

Yüzünden Haliyle @Rawr, Senaryo 2 derleme zamanı hatasına neden olur foo = new ArrayList();- foobiz aynı sınıfta içindeler çünkü statik değişkene karşılık gelir.
flow2k

Java öğrenen bir C ++ geliştiricisiyim. C ++ 'daki anahtar kelimeyle finalaynı değişken üzerinde düşünmek güvenli constmidir?
Doug Barbieri

213

Nihai anahtar kelimenin çok sayıda kullanımı vardır:

  • Bir final sınıfı alt sınıflara ayrılamaz.
  • Son yöntem alt sınıflar tarafından geçersiz kılınamaz
  • Son değişken yalnızca bir kez başlatılabilir

Diğer kullanım:

  • Bir yöntem gövdesi içinde anonim bir iç sınıfa tanımlandığında, bu yöntem kapsamında nihai olarak bildirilen tüm değişkenlere iç sınıf içinden erişilebilir

Statik bir sınıf değişkeni JVM'nin başlangıcından itibaren mevcut olacaktır ve sınıfta başlatılması gerekir. Bunu yaparsanız hata mesajı görünmez.


24
Bu benim en sevdiğim cevap. Basit ve anlaşılır, java hakkında çevrimiçi dokümanlarda okumayı beklediğim şey bu.
RAnders00

Statik değişkenlerde istediğimiz kadarını başlatabilir miyiz?
jorge saraiva

1
@jorgesaraiva evet, statik değişkenler sabit değildir.
czupe

1
@jorgesaraiva Alanları (olmadığı sürece ) istediğiniz kadar atayabilirsiniz ( başlatmaz ) . Atama ve başlatma arasındaki fark için bu wiki'ye bakın . staticfinal

56

finalO üzerinde kullanılan ne kelime bağlı olarak iki farklı şekilde yorumlanabilir:

Değer türleri: For ints, doubledeğer değişmez ki ler vs, o sağlayacaktır

Referans türleri: Nesnelere finalyapılan başvurularda , başvurunun hiçbir zaman değişmemesini sağlar, yani her zaman aynı nesneyi ifade eder. Nesnenin içindeki değerlerin aynı kalması konusunda herhangi bir garanti vermez.

Bunun gibi, final List<Whatever> foo;garanti foohep atıfta aynı listede ancak içindekiler söz konusu listenin zaman içinde değişebilir.


23

Eğer yaparsanız foostatik, aşağıdaki örneklerde olduğu gibi (bunu tanımlamak veya satır içi) sınıf yapıcısı hazır hale getirmeniz gerekir.

Sınıf yapıcısı (örnek değil):

private static final List foo;

static
{
   foo = new ArrayList();
}

Çizgide:

private static final List foo = new ArrayList();

Buradaki sorun, finaldeğiştiricinin nasıl çalıştığı değil, staticdeğiştiricinin nasıl çalıştığıdır.

finalDeğiştirici zaman (yapıcı metotta hazır hale getirmeniz gerekir yani) senin yapıcı tamamlanıncaya çağrısını referans bir başlatma zorlar.

Satır içi bir özniteliği başlattığınızda, kurucu için tanımladığınız kod çalıştırılmadan önce başlatılır, böylece aşağıdaki sonuçları elde edersiniz:

  • eğer fooolduğunu static,foo = new ArrayList() daha önce çalıştırılacaktır static{}size sınıf için tanımladığınız kurucu yürütülür
  • eğer foodeğil static,foo = new ArrayList() sizin yapıcı işletilen önce çalıştırılacaktır

Satır içi bir özniteliği finalbaşlatmazsanız , değiştirici onu başlatmanızı ve yapıcıda yapmanız gerektiğini zorlar. Ayrıca birstatic değiştirici, yapıcı sınıf başlatma blok içinde niteliğini başlatmak zorunda kalacak: static{}.

Kodunuzda aldığınız hata static{}, sınıf yüklendiğinde, o sınıfın bir nesnesini somutlaştırdığınız zamandan önce çalıştırılmış olmasından kaynaklanmaktadır . Böylece, başlatmamış olacaksınızfoo sınıf oluşturulduğunda .

static{}Bloğu, tür bir nesne için yapıcı olarak düşünün Class. Burası,static final sınıf özelliklerinizin (satır içi yapılmazsa).

Kenar notu:

finalModifiye Garantisidir const-lik ilkel türde ve referanslar için.

Bir finalnesneyi beyan ettiğinizde, elde ettiğiniz şey bir final referanstır o nesneye , ancak nesnenin kendisi sabit değildir.

Ne bildirirken gerçekten ulaşmamızı finalEğer (gibi belirli bir amaç için bir nesne bildirmek kez niteliğini, yani final Listsen değişikliğe mümkün olmayacaktır: Eğer açıkladığımı) ve nesne bu amaçla kullanılacak sadece o, List foohiç başka List, ancak yine de değiştirebilir List(öğeleri ekleme / kaldırma yoluyla Listonun içeriği değişmiş aynıdır, yalnızca olacak kullanıyorsunuz).


8

Bu çok güzel bir röportaj sorusu. Bazen size nihai bir nesne ile değişmez nesne arasındaki farkın ne olduğunu sorabilirler.

1) Birisi son bir nesneden bahsettiğinde, referansın değiştirilemeyeceği, ancak durumunun (örnek değişkenleri) değiştirilebileceği anlamına gelir.

2) değişken olmayan bir obje, durumu olabilir biri değildir değiştirilebilir, ancak referans değiştirilebilir. Ör:

    String x = new String("abc"); 
    x = "BCG";

ref değişkeni x farklı bir dizeyi gösterecek şekilde değiştirilebilir, ancak "abc" değeri değiştirilemez.

3) Bir yapıcı çağrıldığında örnek değişkenleri (statik olmayan alanlar) başlatılır. Böylece, yapıcı içindeki değişkenlerin değerlerini başlatabilirsiniz.

4) "Ama sınıfın yapıcısında / yöntemlerinde değeri değiştirebileceğini görüyorum". - Bir yöntem içinde değiştiremezsiniz.

5) Sınıf yüklemesi sırasında statik bir değişken başlatılır. Yani bir kurucu içinde başlatamazsınız, daha önce bile yapılması gerekir. Bu nedenle, bildirimin kendisi sırasında statik bir değişkene değerler atamanız gerekir .


7

Java'daki finalanahtar kelime kullanıcıyı kısıtlamak için kullanılır. Java finalanahtar sözcüğü birçok bağlamda kullanılabilir. Final olabilir:

  1. değişken
  2. yöntem
  3. sınıf

finalAnahtar kelime, değişkenlerle uygulanabilecek finalhiçbir değeri yoktur değişken, boş denir finaldeğişken veya başlatılmamışfinal değişkeni. Yalnızca yapıcıda başlatılabilir. Blank finaldeğişkeni, yalnızca blokta staticbaşlatılacak olan da olabilir static.

Java son değişkeni:

Olarak herhangi bir değişken finalyaparsanız , değeri değiştiremezsiniz. ait final(O sabiti olacaktır) değişken.

Nın bir örneği finalDeğişken

Son değişken bir hız sınırı var, bu değişkenin değerini değiştireceğiz, ancak değiştirilemez çünkü bir değer atandıktan sonra son değişken asla değiştirilemez.

class Bike9{  
    final int speedlimit=90;//final variable  
    void run(){  
        speedlimit=400;  // this will make error
    }  

    public static void main(String args[]){  
    Bike9 obj=new  Bike9();  
    obj.run();  
    }  
}//end of class  

Java final sınıfı:

Olarak herhangi bir sınıf finalyaparsanız , .

Son sınıf örneği

final class Bike{}  

class Honda1 extends Bike{    //cannot inherit from final Bike,this will make error
  void run(){
      System.out.println("running safely with 100kmph");
   }  

  public static void main(String args[]){  
      Honda1 honda= new Honda();  
      honda.run();  
      }  
  }  

Java son yöntemi:

Herhangi bir yöntemi son olarak yaparsanız , bunu geçersiz kılamazsınız.

finalHonda'daki (run () yöntemi örneği, Bike'daki run () öğesini geçersiz kılamıyor)

class Bike{  
  final void run(){System.out.println("running");}  
}  

class Honda extends Bike{  
   void run(){System.out.println("running safely with 100kmph");}  

   public static void main(String args[]){  
   Honda honda= new Honda();  
   honda.run();  
   }  
}  

paylaştığı yer: http://www.javatpoint.com/final-keyword


7

Bazı basit tanımlardan bahsetmeye değer:

Sınıflar / Yöntemler

finalYöntemin alt sınıflar tarafından geçersiz kılınamayacağını belirtmek için sınıf yöntemlerinin bir kısmını veya tamamını bildirebilirsiniz.

Değişkenler

Bir finaldeğişken başlatıldıktan sonra her zaman aynı değeri içerir.

final temelde, duruma bağlı olarak herhangi bir şey (alt sınıflar, değişken "yeniden atama") üzerine yazmaktan / üst yazı yazmaktan kaçının.


1
Değişkenlerle ilgili son tanımın biraz kısa olduğunu düşünüyorum; "Java'da, son anahtar kelime bir dizi ilkel veri türüyle (int, kayan nokta, vb.) Kullanıldığında, değişkenin değeri değiştirilemez ancak final, ilkel olmayan değişkenlerle kullanıldığında (İlkel olmayan değişkenlerin "her zaman Java'daki nesnelere referanstır), belirtilen nesnenin üyeleri değiştirilebilir. geeksforgeeks.org/g-fact-48
ceyun

Aynı zamanda, özellikle ilkel ve ilkel olmayan vakalardan bahsetmek için de geçerlidir. Tks.
ivanleoncz

4

finalJava, kullanıcıyı kısıtlamak için ayrılmış bir anahtar kelimedir ve üye değişkenlere, yöntemlere, sınıfa ve yerel değişkenlere uygulanabilir. Nihai değişkenler genellikle staticJava'daki anahtar kelimeyle bildirilir ve sabit olarak kabul edilir. Örneğin:

public static final String hello = "Hello";

Kullandığımızda finalDeğişken bildirimli anahtar kelimeyi bu değişkenin içinde saklanan değer ikincisi olarak değiştirilemez.

Örneğin:

public class ClassDemo {
  private final int var1 = 3;
  public ClassDemo() {
    ...
  }
}

Not : Final olarak bildirilen bir sınıf genişletilemez veya devralınamaz (yani, süper sınıfın bir alt sınıfı olamaz). Nihai olarak ilan edilen yöntemlerin alt sınıflar tarafından geçersiz kılınamayacağına dikkat etmek de iyidir.

Son anahtar kelimeyi kullanmanın yararları bu başlıkta ele alınmaktadır .


2
the value stored inside that variable cannot be changed latterkısmen doğrudur. Yalnızca ilkel veri türleri için geçerlidir. Herhangi bir nesnenin finalarraylist gibi yapılması durumunda değeri değişebilir ancak referans olamaz. Teşekkür ederim!
GS

3

Kırmızı ve beyaz olmak üzere iki para kutunuz olduğunu varsayalım. Bu para kutularını sadece iki çocuğa atarsınız ve kutularının değiş tokuşuna izin verilmez. Kırmızı veya beyaz kumbaralarınız var (son) kutuyu değiştiremezsiniz ama kutunuza para koyabilirsiniz. Kimse umursamaz (Değişiklik-2).


2

Tüm cevapları okuyun.

finalAnahtar kelimenin, bir yöntem bağımsız değişkeninde kullanılabileceği başka bir kullanıcı durumu daha vardır :

public void showCaseFinalArgumentVariable(final int someFinalInt){

   someFinalInt = 9; // won't compile as the argument is final

}

Değiştirilmemesi gereken değişken için kullanılabilir.


1

Statik sonlandırdığınızda statik başlatma bloğunda başlatılması gerekir

    private static final List foo;

    static {
        foo = new ArrayList();
    }

    public Test()
    {
//      foo = new ArrayList();
        foo.add("foo"); // Modification-1
    }

1

finalAnahtar kelime değişken yalnızca bir kez başlatılır olabileceğini gösterir. Kodunuzda, terimlerin karşılanması için yalnızca bir final finali gerçekleştiriyorsunuz. Bu ifade, için yalnız başlatmayı gerçekleştirir foo. Not o final! = Değişmez, sadece aracı referans değişikliği yapamaz o.

foo = new ArrayList();

Eğer beyan zaman fooolarak static finaldeğişken sınıfı yüklendiğinde sıfırlanması gerekiyor ve örnekleme güvenemez başlatılamadı (aka yapıcısına çağrı) foostatik alanlar sınıfının bir örneği olmadan kullanılabilir olmalıdır çünkü. Statik alanı kullanmadan önce kurucunun çağrılmış olacağının garantisi yoktur.

static finalSenaryo altında yönteminizi yürüttüğünüzde , Testsınıf, tbu anda başlatılmadan önce yüklenir , başlatılmadığı bir fooanlam örneği yoktur, bu nedenle footüm nesneler için varsayılan olarak ayarlanır null. Bu noktada NullPointerException, listeye bir öğe eklemeye çalıştığınızda kodunuzun bir atar .


1

Her şeyden önce, kodunuzda başlattığınız (yani ilk kez atadığınız) yer foo burada:

foo = new ArrayList();

bu yüzden fan (tip List) bir amacı, bir referans türü, bir değer (int gibi) türü. Bu nedenle, Liste öğelerinizin depolandığı bir bellek konumuna (örn. 0xA7D2A834) bir referans tutar. Bunun gibi çizgiler

foo.add("foo"); // Modification-1

foo'nun değerini değiştirmeyin (yine, sadece bellek konumuna bir referanstır). Bunun yerine, referans verilen bellek konumuna sadece öğeler eklerler. Son anahtar kelimeyi ihlal etmek için foo'yu tekrar aşağıdaki gibi yeniden atamanız gerekir:

foo = new ArrayList();

Yani olur sana bir derleme hatası verir.


Şimdi, bununla, statik eklediğinizde ne olacağını düşünün anahtar kelimeyi .

Statik anahtar sözcüğünüz OLMADIĞINDA, sınıfı başlatan her nesnenin kendi foo kopyası vardır. Bu nedenle, yapıcı foo değişkeninin boş, yeni bir kopyasına mükemmel bir şekilde bir değer atar.

Ancak, static anahtar sözcüğüne sahip olduğunuzda, bellekte sınıfla ilişkilendirilmiş yalnızca bir foo vardır. İki veya daha fazla nesne oluşturacak olsaydınız, yapıcı her seferinde bir foo atamaya çalışarak son anahtar kelimeyi ihlal ederdi .


1
  1. Son değişken statik olmadığından yapıcıda başlatılabilir. Ancak statik yaparsanız yapıcı tarafından başlatılamaz (çünkü kurucular statik değildir).
  2. Listeye eklemenin, listenin sonlandırılmasıyla durması beklenmez. finalreferansı belirli bir nesneye bağlar. Bu nesnenin 'durumunu' değiştirebilirsiniz, ancak nesnenin kendisini değiştiremezsiniz.

1

Aşağıda finalin kullanıldığı farklı bağlamlar yer almaktadır.

Nihai değişkenler Nihai değişken yalnızca bir kez atanabilir. Değişken bir referanssa, bu, değişkenin başka bir nesneye başvurmak için yeniden bağlanamayacağı anlamına gelir.

class Main {
   public static void main(String args[]){
      final int i = 20;
      i = 30; //Compiler Error:cannot assign a value to final variable i twice
   }
}

son değişkene daha sonra değer atanabilir (beyan edildiğinde bir değerin atanması zorunlu değildir), ancak sadece bir kez.

Final sınıfları Final sınıfı genişletilemez (devralındı)

final class Base { }
class Derived extends Base { } //Compiler Error:cannot inherit from final Base

public class Main {
   public static void main(String args[]) {
   }
}

Son yöntemler Son yöntem alt sınıflar tarafından geçersiz kılınamaz.

//Error in following program as we are trying to override a final method.
class Base {
  public final void show() {
       System.out.println("Base::show() called");
    }
}     
class Derived extends Base {
    public void show() {  //Compiler Error: show() in Derived cannot override
       System.out.println("Derived::show() called");
    }
}     
public class Main {
    public static void main(String[] args) {
        Base b = new Derived();;
        b.show();
    }
}

1

Burada güncel ve derinlemesine bir cevap yazmayı düşündüm.

final anahtar kelime birkaç yerde kullanılabilir.

  1. sınıflar

Bu final class, başka hiçbir sınıfın bu son sınıfı genişletemeyeceği anlamına gelir . Java Çalışma Süresi ( JRE ) bir nesne başvurusunun son sınıf türünde olduğunu bildiğinde (örneğin F), bu başvurunun değerinin yalnızca F türünde olabileceğini bilir.

Ör:

F myF;
myF = new F();    //ok
myF = someOther;  //someOther cannot be in type of a child class of F.
                  //because F cannot be extended.

Bu nedenle, bu nesnenin herhangi bir yöntemini çalıştırdığında, bu yöntemin çalışma zamanında sanal bir tablo kullanılarak çözülmesi gerekmez . yani çalışma zamanı polimorfizmi uygulanamaz. Bu yüzden çalışma süresi bununla uğraşmıyor. Bu, işlem süresini kısaltarak, performansı artıracağı anlamına gelir.

  1. yöntemleri

final methodHerhangi bir sınıfın A değeri , o sınıfı genişleten herhangi bir alt sınıfın bu son yöntem (ler) i geçersiz kılamayacağı anlamına gelir . Dolayısıyla bu senaryodaki çalışma zamanı davranışı da sınıflar için bahsettiğim önceki davranışla aynıdır.

  1. alanlar, yerel değişkenler, yöntem parametreleri

Yukarıdaki gibi herhangi bir tür belirtilirse final, değer zaten sonlandırılmış demektir, bu nedenle değer değiştirilemez .

Ör:

Alanlar için yerel parametreler

final FinalClass fc = someFC; //need to assign straight away. otherwise compile error.
final FinalClass fc; //compile error, need assignment (initialization inside a constructor Ok, constructor can be called only once)
final FinalClass fc = new FinalClass(); //ok
fc = someOtherFC; //compile error
fc.someMethod(); //no problem
someOtherFC.someMethod(); //no problem

Yöntem parametreleri için

void someMethod(final String s){
    s = someOtherString; //compile error
}

Bu sadece finalreferans değerinin değiştirilemeyeceği anlamına gelir . yani yalnızca bir başlatmaya izin verilir. Bu senaryoda, çalışma zamanında, JRE değerlerin değiştirilemeyeceğini bildiğinden, tüm bu nihai değerleri (son referansların) L1 önbelleğine yükler . O Çünkü gerekmez için geri yüklemek dan tekrar ana belleğe . Aksi takdirde L2 önbelleğine yüklenir ve ana bellekten zaman zaman yüklenir. Yani aynı zamanda bir performans geliştirmesidir.

Bu nedenle, yukarıdaki 3 senaryoda, finalanahtar kelimeyi kullanabileceğimiz yerlerde belirtmediğimizde endişelenmemize gerek yok, derleyici optimizasyonları bunu bizim için yapacak. Derleyici optimizasyonlarının bizim için yaptığı birçok şey daha var. :)


0

Her şeyden önce doğrudur. Ayrıca başkalarının sınıfınızdan alt sınıflar oluşturmasını istemiyorsanız, sınıfınızı final olarak ilan edin. Daha sonra, sınıf ağacı hiyerarşinizin yaprak seviyesi haline gelir ve hiç kimse onu daha fazla genişletemez. Büyük sınıf hiyerarşisinden kaçınmak iyi bir uygulamadır.

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.