CodeGym /Java Blogu /Rastgele /Java'daki sabit değerler: final, sabitler ve değişmez
John Squirrels
Seviye
San Francisco

Java'daki sabit değerler: final, sabitler ve değişmez

grupta yayınlandı
MERHABA! "Değiştirici" kelimesini zaten biliyorsunuz. En azından, erişim değiştiricileri (genel, özel) ve statik değiştirici ile karşılaştınız. Bugün final adlı özel bir değiştiriciyi tartışacağız . Son değiştiricinin, programımızın sabit, net ve değişmeyen davranışların gerekli olduğu kısımlarını "sıkılaştırdığını" söyleyebilirsiniz. Programlarınızda onu kullanabileceğiniz üç yer vardır: sınıflar, yöntemler ve değişkenler. Java'daki sabit değerler: final, sabitler ve değişmez - 2 Sırayla üzerlerinden geçelim. Son değiştirici bir sınıf bildiriminde kullanılıyorsa , bu, sınıfın miras alınamayacağı anlamına gelir. AnimalÖnceki derslerde basit bir kalıtım örneği kullandık: bir ebeveyn sınıfımız ve iki alt sınıfımız vardı : CatveDog

public class Animal {
}



public class Cat extends Animal {
   // Fields and methods of the Cat class
}


public class Dog extends Animal {

   // Fields and methods of the Dog class
}
Ancak, sınıf üzerinde son değiştiriciyi kullanırsak Animal, Catve Dogsınıfları onu miras alamaz.

public final class Animal {

}

public class Cat extends Animal {

   // Error! Cannot inherit from final Animal
}
Derleyici hemen bir hata üretir. Java'da birçok son sınıf zaten uygulanmaktadır. Sık kullandıklarınız arasında Stringen bilinenidir. Ayrıca, bir sınıf final olarak bildirilirse , sınıfın tüm yöntemleri de final olur . Bu ne anlama gelir? Son değiştirici kullanılarak bir yöntem bildirilirse , bu yöntemi geçersiz kılamazsınız. Örneğin, burada Animalbir yöntem bildiren bir sınıfımız var speak(). Ancak, köpekler ve kediler kesinlikle farklı şekillerde "konuşur". CatBöylece, talk() yöntemlerini hem sınıflarda hem de sınıflarda bildireceğiz Dog, ancak bunları farklı şekilde uygulayacağız.

public class Animal {
  
   public void speak() {
       System.out.println("Hello!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void speak() {
       System.out.println("Woof!");
   }
}
Catve Dogsınıflarını üst sınıfta bildirilen yöntemi geçersiz kıldık . Şimdi, bir hayvan, ne tür bir nesne olduğuna bağlı olarak farklı şekilde konuşacaktır:

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       Dog dog = new Dog();
      
       cat.speak();
       dog.speak();
   }
}
Çıktı: Miyav! Hav! AnimalAncak, sınıfın yöntemini final olarak bildirirsek speak(), diğer sınıflarda geçersiz kılamayız:

public class Animal {

   public final void speak() {
       System.out.println("Hello!");
   }
}


public class Cat extends Animal {

   @Override
   public void speak() {// Error! A final method can't be overridden!
       System.out.println("Meow!");
   }
}
speak()Ve nesnelerimiz , üst sınıfta tanımlanan yöntemi kullanmaya zorlanacak :

public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   cat.speak();
   dog.speak();
}
Çıktı: Merhaba! Merhaba! Şimdi, son değişkenlerle ilgili. Sabitler olarak da bilinirler . Birincisi (ve en önemlisi), sabit bir değere atanan ilk değer değiştirilemez. Bir kez ve herkes için atanır.

public class Main {
  
   private static final int CONSTANT_EXAMPLE = 333;

   public static void main(String[] args) {

       CONSTANT_EXAMPLE = 999;// Error! You can't assign a new value to a final variable!
   }
}
Bir sabitin hemen başlatılması gerekmez. Bu daha sonra yapılabilir. Ancak başlangıçta ona atanan değer sonsuza kadar aynı kalacaktır.

public static void main(String[] args) {

   final int CONSTANT_EXAMPLE;

   CONSTANT_EXAMPLE = 999;// This is allowed
}
İkinci olarak, değişkenimizin adını not edin. Java'nın sabitler için farklı bir adlandırma kuralı vardır. Her zamanki camelCase gösterimi değil . Sıradan bir değişken olsaydı, onu sabitÖrnek olarak adlandırırdık.. Ancak, sabitlerin adları, sözcükler arasında alt çizgi olacak şekilde (birden fazla sözcük varsa), örneğin "CONSTANT_EXAMPLE", tümü büyük harfle yazılır. Neden sabitlere ihtiyacımız var? Örneğin, bir programda düzenli olarak kullandığınız sabit bir değer varsa çok faydalıdırlar. Örneğin, tarih yazmaya ve "The Witcher 4" oyununu kendi başınıza yazmaya karar verdiniz. Oyun belli ki düzenli olarak kahramanın adını kullanacak: "Geralt of Rivia". Bu dize (ve diğer kahramanların adları) en iyi şekilde bir sabit olarak bildirilir: değeri tek bir yerde saklanır ve onu milyon kez girerken kesinlikle yazım hatası yapmazsınız.

public class TheWitcher4 {

   private static final String GERALT_NAME = "Geralt of Rivia";
   private static final String YENNEFER_NAME = "Yennefer of Wengerberg";
   private static final String TRISS_NAME = "Triss Merigold";

   public static void main(String[] args) {

       System.out.println("The Witcher 4");
       System.out.println("It's already the fourth Witcher game, but " + GERALT_NAME + " still can't decide who" +
               " he likes more: " + YENNEFER_NAME + " or " + TRISS_NAME);

       System.out.println("But, if you've never played The Witcher before, we'll start from the beginning.");
       System.out.println("The protagonist's name is " + GERALT_NAME);
       System.out.println(GERALT_NAME + " is a witcher, a monster hunter");
   }
}
Çıktı: The Witcher 4 Şimdiden dördüncü Witcher oyunu, ancak Geralt of Rivia hala kimi daha çok sevdiğine karar veremiyor: Wengerberg'li Yennefer veya Triss Merigold Ancak, The Witcher'ı daha önce hiç oynamadıysanız, baştan başlayacağız. başlangıç. Kahramanın adı Rivialı Geralt Geralt of Rivia bir witcher, bir canavar avcısı Kahramanların isimlerini sabit olarak ilan ettik. Artık kesinlikle bir yazım hatası yapmayacağız ve bunları her seferinde elle yazmaya gerek yok. Başka bir artı: Değişkenin değerini programın tamamında değiştirmemiz gerekirse, bunu tüm kod tabanında manuel olarak değiştirmek yerine tek bir yerde yapabilirsiniz. :)

değişmez tipler

Java ile çalıştığınız için, muhtemelen programcıların tüm nesnelerin durumu üzerinde neredeyse tam kontrole sahip olduğu fikrine alışmışsınızdır. Bir nesne oluşturmak istiyorsanız Cat, yapabilirsiniz. Yeniden adlandırmak istersen, yapabilirsin. Yaşını veya başka bir şeyi değiştirmek istersen, yapabilirsin. Ancak Java'nın özel bir özelliği olan birkaç veri türü vardır. Onlar değişmez . Bir sınıf değişmez ise, nesnelerinin durumu değiştirilemez. Bazı örnekler ister misiniz? Sizi şaşırtabilir ama en iyi bilinen değişmez sınıf String'dir! Yani, bir String'in değerini gerçekten değiştiremez miyiz? Pekala, deneyelim:

public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1 = "I love Python";// but changing str1 has no impact on str2
   System.out.println(str2);// str2 continues to point to the "I love Java" string, but str1 now points to a different object
}
Çıktı: Java'yı seviyorum Java'yı seviyorum Yazdıktan sonra

str1 = "I love Python";
string nesnesi "I love Java"değişmedi veya hiçbir yere gitmedi. Hala mutlu bir şekilde var ve eskisi gibi aynı metne sahip. kod

str1 = "I love Python";
str1'in şimdi işaret ettiği başka bir nesne yarattı . Ancak, "Java'yı seviyorum" dize nesnesi üzerinde herhangi bir etkimiz yok gibi görünüyor. Tamam, başka bir şey deneyelim! Sınıf Stringmetotlarla dolu ve bazıları nesnenin durumunu değiştiriyor gibi görünüyor! Örneğin, bir replace()yöntem var. Dizemizdeki "Java" kelimesini "Python" olarak değiştirelim!

public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1.replace("Java", "Python");// We try to change the state of str1 by swapping the word "Java" with "Python"
   System.out.println(str2);
}
Çıktı: Java'yı seviyorum Java'yı seviyorum Yine çalışmadı! Belki replace yöntemi çalışmıyor? Başka bir şey deneyelim. Örneğin, substring(). Argüman olarak iletilen karakter dizinlerine dayalı bir alt dize döndürür. Dizimizin ilk 10 karakterini keselim:

public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1.substring(10);// Truncate the original String 
   System.out.println(str2);
}
Çıktı: Java'yı seviyorum Java'yı seviyorum Java'daki sabit değerler: final, sabitler ve değişmez - 3 Hiçbir şey değişmedi. Ve olmamalıydı. Daha önce de söylediğimiz gibi, Dizeler değişmezdir. Peki, sınıftaki tüm yöntemlerin nesi var String? Sonuçta, dizeleri kısaltabilir, karakterleri değiştirebilir ve daha fazlasını yapabilirler. Hiçbir şey olmayacaksa ne anlamı var? Aslında bunları yapabilirler! Ancak her seferinde yeni bir String döndürürler. yazmak anlamsız

str1.replace("Java", "Python");
çünkü orijinal nesneyi değiştiremezsiniz. Ancak, yöntemin sonucunu yeni bir referans değişkenine yazarsanız, farkı hemen göreceksiniz!

public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   String str1AfterReplacement =  str1.replace("Java", "Python");
   System.out.println(str2);

   System.out.println(str1AfterReplacement);
}
Tüm Stringyöntemler bu şekilde çalışır. Nesneye hiçbir şey yapılamaz "I love Java". Sadece yeni bir nesne oluşturabilir ve şunu yazabilirsiniz: "<yeni nesne> = "I love Java" object ". , , , , , , : bu sınıfların tümü nesneler oluşturur (gelecek derslerde onlar hakkında konuşacağız).Bu, ve gibi büyük sayılar oluşturmak için kullanılan sınıfları içerir.Son zamanlarda istisnaları ele aldık ve yığın izlemesine değindik . , tahmin et, java.lang.StackTraceElementIntegerByteCharacterShortBooleanLongDoubleFloatimmutableBigIntegerBigDecimalnesneler de değişmezdir. Bu mantıklı: Birisi yığınımızın verilerini değiştirebilseydi, bu her şeyi anlamsız hale getirirdi. Birinin yığın izinden geçtiğini ve bir OutOfMemoryError öğesini FileNotFoundException olarak değiştirdiğini hayal edin . Sonra hatanın nedenini bulmak için bu yığını kullanırsınız. Ancak program dosyaları bile kullanmaz. :) Yani, her ihtimale karşı bu nesneleri değişmez hale getirdiler. Tamam, StackTraceElement için aşağı yukarı mantıklı . Ancak, neden birinin Dizeleri değişmez yapması gerekiyor? Değerlerini değiştirmek neden sorun olsun? Muhtemelen daha da uygun olacaktır. :/ Bunun birkaç nedeni var. İlk olarak, hafızadan tasarruf sağlar. Değişmez diziler, dizi havuzuna yerleştirilebilir, dizelerin yenilerini oluşturmak yerine yeniden kullanılmasına izin verir. İkincisi, güvenlik için. Örneğin, hemen hemen her programda kullanıcı adları ve parolalar String'lerdir. Bunları değiştirmeyi mümkün kılmak, yetkilendirme sorunlarına neden olabilir. Başka nedenler de var, ancak Java çalışmamız henüz onları kapsamadı, bu yüzden onlara daha sonra geri döneceğiz.
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION