โค้ดยิม/จาวาบล็อก/สุ่ม/ค่าคงที่ใน Java: ค่าสุดท้าย ค่าคงที่ และไม่เปลี่ยนรูป
John Squirrels
ระดับ
San Francisco

ค่าคงที่ใน Java: ค่าสุดท้าย ค่าคงที่ และไม่เปลี่ยนรูป

เผยแพร่ในกลุ่ม
สวัสดี! คุณคุ้นเคยกับคำว่า "ตัวดัดแปลง" อยู่แล้ว อย่างน้อยที่สุด คุณเคยพบตัวแก้ไขการเข้าถึง (สาธารณะ ส่วนตัว) และตัวแก้ไขแบบคงที่ วันนี้เราจะพูดถึงตัวแก้ไขพิเศษที่เรียกว่าFinal คุณสามารถพูดได้ว่าส่วนปรับแต่งสุดท้าย "ประสาน" ของโปรแกรมของเราซึ่งจำเป็นต้องมีพฤติกรรมที่คงที่ ไม่กำกวม และไม่เปลี่ยนแปลง มีสามตำแหน่งในโปรแกรมของคุณที่คุณสามารถใช้ได้: คลาส เมธอด และตัวแปร ค่าคงที่ใน Java: ค่าสุดท้าย ค่าคงที่ และไม่เปลี่ยนรูป - 2 มาดูตามลำดับกัน หาก ใช้ตัวแก้ไข ขั้นสุดท้ายในการประกาศคลาส หมายความว่าคลาสนั้นไม่สามารถสืบทอดได้ ในบทที่แล้ว เราใช้ตัวอย่างการสืบทอดอย่างง่าย: เรามีAnimalคลาสพาเรนต์และคลาสรอง 2 คลาส: CatและDog
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
}
อย่างไรก็ตาม หากเราใช้ ตัวปรับแต่ง สุดท้ายในAnimalคลาส คลาสCatและDogจะไม่สามารถสืบทอดได้
public final class Animal {

}

public class Cat extends Animal {

   // Error! Cannot inherit from final Animal
}
คอมไพเลอร์สร้างข้อผิดพลาดทันที ใน Java มีการใช้งานคลาส สุดท้าย จำนวนมาก แล้ว ในบรรดาที่คุณใช้บ่อยStringเป็นที่รู้จักมากที่สุด ยิ่งกว่านั้น ถ้า class ถูกประกาศเป็นfinal เมธอดทั้งหมดของ class ก็จะกลายเป็นfinal ด้วย นั่นหมายความว่าอย่างไร? หากมีการประกาศเมธอดโดยใช้ ตัวแก้ไข ขั้นสุดท้ายคุณจะไม่สามารถแทนที่เมธอดนั้นได้ ตัวอย่างเช่น ที่นี่เรามีAnimalคลาสที่ประกาศspeak()เมธอด แต่สุนัขและแมว "พูด" ในรูปแบบที่แตกต่างกันอย่างแน่นอน ดังนั้น เราจะประกาศเมธอด speak() ทั้งในคลาสCatและDogคลาส แต่เราจะใช้มันต่างกัน
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!");
   }
}
เราทำให้คลาสCatและDogแทนที่เมธอดที่ประกาศในคลาสพาเรนต์ ตอนนี้ สัตว์จะพูดแตกต่างกันไปขึ้นอยู่กับประเภทของวัตถุ:
public class Main {

   public static void main(String[] args) {

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

       cat.speak();
       dog.speak();
   }
}
ผลลัพธ์: เมี้ยว! โฮ่ง! อย่างไรก็ตาม หากเราประกาศ เมธอด Animalของคลาสspeak()เป็นขั้นสุดท้าย เราจะไม่สามารถแทนที่เมธอดในคลาสอื่นได้:
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()วิธีการตามที่กำหนดไว้ในคลาสหลัก:
public static void main(String[] args) {

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

   cat.speak();
   dog.speak();
}
ผลลัพธ์: สวัสดี! สวัสดี! ตอนนี้เกี่ยวกับตัวแปรสุดท้าย พวกเขาเรียกอีกอย่างว่าค่าคงที่ ประการแรก (และที่สำคัญที่สุด) ค่าเริ่มต้นที่กำหนดให้กับค่าคงที่ไม่สามารถเปลี่ยนแปลงได้ มันถูกกำหนดครั้งแล้วครั้งเล่า
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!
   }
}
ค่าคงที่ไม่จำเป็นต้องเริ่มต้นทันที ที่สามารถทำได้ในภายหลัง แต่ค่าที่กำหนดในตอนแรกจะคงเดิมตลอดไป
public static void main(String[] args) {

   final int CONSTANT_EXAMPLE;

   CONSTANT_EXAMPLE = 999;// This is allowed
}
ประการที่สอง สังเกตชื่อตัวแปรของเรา Java มีหลักการตั้งชื่อที่แตกต่างกันสำหรับค่าคงที่ ไม่ใช่สัญกรณ์camelCase ตามปกติ ถ้ามันเป็นตัวแปรธรรมดา เราจะเรียกมันว่า. แต่ชื่อของค่าคงที่จะถูกเขียนเป็นตัวพิมพ์ใหญ่ทั้งหมด โดยมีขีดล่างระหว่างคำ (หากมีมากกว่าหนึ่งคำ) เช่น "CONSTANT_EXAMPLE" ทำไมเราต้องมีค่าคงที่? มีประโยชน์มาก เช่น มีค่าคงที่ที่คุณใช้ในโปรแกรมเป็นประจำ ตัวอย่างเช่น คุณตัดสินใจที่จะสร้างประวัติศาสตร์และเขียนเกม "The Witcher 4" ด้วยตัวคุณเอง เกมจะใช้ชื่อตัวเอกว่า "Geralt of Rivia" เป็นประจำ สตริงนี้ (และชื่อฮีโร่อื่นๆ) ได้รับการประกาศให้เป็นค่าคงที่อย่างดีที่สุด: ค่าของมันจะถูกเก็บไว้ในที่เดียว และคุณจะไม่พิมพ์ผิดอย่างแน่นอนเมื่อป้อนเป็นล้านครั้ง
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");
   }
}
ผลลัพธ์: The Witcher 4 เป็นเกม Witcher เกมที่สี่แล้ว แต่ Geralt of Rivia ยังตัดสินใจไม่ได้ว่าเขาชอบใครมากกว่ากัน: Yennefer จาก Wengerberg หรือ Triss Merigold แต่ถ้าคุณไม่เคยเล่น The Witcher มาก่อน เราจะเริ่มจาก จุดเริ่มต้น. ชื่อตัวเอกคือ Geralt of Rivia Geralt of Rivia เป็นแม่มด นักล่าสัตว์ประหลาด เราได้ประกาศชื่อฮีโร่เป็นค่าคงที่แล้ว ตอนนี้เราจะไม่พิมพ์ผิดอย่างแน่นอน และไม่จำเป็นต้องเขียนด้วยมือทุกครั้ง ข้อดีอีกอย่าง: หากเราจำเป็นต้องเปลี่ยนค่าของตัวแปรทั่วทั้งโปรแกรม คุณสามารถทำได้ในที่เดียว แทนที่จะแก้ไขด้วยตนเองทั่วทั้งโค้ดเบส :)

ประเภทที่ไม่เปลี่ยนรูป

ในขณะที่คุณทำงานกับ Java คุณอาจเคยชินกับแนวคิดที่ว่าโปรแกรมเมอร์สามารถควบคุมสถานะของวัตถุทั้งหมดได้เกือบทั้งหมด หากคุณต้องการสร้างCatวัตถุ คุณสามารถทำได้ หากคุณต้องการเปลี่ยนชื่อคุณสามารถทำได้ หากคุณต้องการเปลี่ยนอายุหรืออย่างอื่น คุณสามารถทำได้ แต่ Java มีข้อมูลหลายประเภทที่มีคุณสมบัติพิเศษ พวกมันไม่เปลี่ยนรูป ถ้าคลาสไม่เปลี่ยนรูป สถานะของออบเจกต์จะไม่สามารถเปลี่ยนแปลงได้ ต้องการตัวอย่างบางส่วน? อาจทำให้คุณประหลาดใจ แต่คลาสที่ไม่เปลี่ยนรูปที่รู้จักกันดีที่สุดคือ String! เราไม่สามารถเปลี่ยนค่าของ String ได้จริงหรือ? มาลองกัน:
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
}
ผลลัพธ์: ฉันรัก Java ฉันรัก Java หลังจากที่เราเขียน
str1 = "I love Python";
วัตถุ"I love Java"สตริงไม่เปลี่ยนแปลงหรือไปไหน ก็ยังดำรงอยู่อย่างเป็นสุขและมีอรรถเหมือนก่อน. รหัส
str1 = "I love Python";
เพียงแค่สร้างวัตถุอื่นซึ่ง ตอนนี้ str1ชี้ไปที่ แต่ดูเหมือนว่าเราจะไม่มีผลกระทบใดๆ กับออบเจกต์สตริง "I love Java" โอเค มาลองอย่างอื่นกันดีกว่า! คลาส นี้Stringเต็มไปด้วยเมธอด และบางเมธอดดูเหมือนจะเปลี่ยนสถานะของอ็อบเจกต์! ตัวอย่างเช่นมีreplace()วิธีการ มาเปลี่ยนคำว่า "Java" เป็น "Python" ในสตริงกันเถอะ!
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);
}
ผลลัพธ์: ฉันรัก Java ฉันรัก Java มันใช้งานไม่ได้อีกแล้ว! บางทีวิธีการแทนที่อาจใช้ไม่ได้? มาลองอย่างอื่นกัน ตัวอย่างเช่นsubstring(). ส่งคืนสตริงย่อยตามดัชนีอักขระที่ส่งผ่านเป็นอาร์กิวเมนต์ ตัดอักขระ 10 ตัวแรกของสตริงของเราออก:
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);
}
ผลลัพธ์: ฉันรัก Java ฉันรัก Java ค่าคงที่ใน Java: ค่าสุดท้าย ค่าคงที่ และไม่เปลี่ยนรูป - 3 ไม่มีอะไรเปลี่ยนแปลง และไม่ควรมี อย่างที่เราพูดไปก่อนหน้านี้ สตริงไม่เปลี่ยนรูป แล้วเมธอดทั้งหมดในStringคลาสล่ะ? ท้ายที่สุดแล้ว พวกเขาสามารถตัดทอนสตริง เปลี่ยนอักขระ และอื่นๆ จะมีประโยชน์อะไรถ้าไม่มีอะไรเกิดขึ้น? พวกเขาทำสิ่งเหล่านี้ได้จริง! แต่พวกเขาจะส่งคืนสตริงใหม่ทุกครั้ง มันไม่มีประโยชน์ที่จะเขียน
str1.replace("Java", "Python");
เพราะคุณไม่สามารถเปลี่ยนวัตถุเดิมได้ แต่ถ้าคุณเขียนผลลัพธ์ของเมธอดไปยังตัวแปรอ้างอิงใหม่ คุณจะเห็นความแตกต่างทันที!
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);
}
วิธีการ ทั้งหมดStringทำงานในลักษณะนี้ ไม่สามารถทำอะไรกับ"I love Java"วัตถุได้ คุณสามารถสร้างวัตถุใหม่และเขียน: "<new object> = the result of manipulating the "I love Java" object ". ประเภทอื่น ๆ ที่ไม่เปลี่ยนรูปคืออะไร บางอย่างที่คุณจะต้องจำทันทีคือคลาส wrapper ทั้งหมดสำหรับประเภทดั้งเดิม Integer, Byte, Character, Short, Boolean, Long, Double, Float: คลาสเหล่านี้ทั้งหมดสร้างimmutableobject (เราจะพูดถึงในบทเรียนต่อๆ ไป) ซึ่งรวมถึงคลาสที่ใช้สร้างตัวเลขจำนวนมาก เช่นBigIntegerและBigDecimalเมื่อเร็ว ๆ นี้เราได้พูดถึงข้อยกเว้นและกล่าวถึงการติดตามสแต็ก ลองเดาดูว่าjava.lang.StackTraceElementวัตถุนั้นไม่เปลี่ยนรูปเช่นกัน สิ่งนี้สมเหตุสมผล: ถ้ามีคนสามารถเปลี่ยนข้อมูลสแต็คของเราได้ มันจะทำให้เรื่องทั้งหมดไม่มีจุดหมาย ลองนึกภาพว่ามีคนกำลังติดตามสแต็กและเปลี่ยนOutOfMemoryErrorเป็นFileNotFoundException จากนั้นคุณใช้สแต็กนั้นเพื่อค้นหาสาเหตุของข้อผิดพลาด แต่โปรแกรมไม่ได้ใช้ไฟล์ด้วยซ้ำ :) ดังนั้นพวกเขาจึงสร้างวัตถุเหล่านี้ไม่เปลี่ยนรูป ในกรณีนี้ โอเค มันสมเหตุสมผลแล้วสำหรับStackTraceElement ไม่ มาก ก็น้อย แต่ทำไมทุกคนจำเป็นต้องทำให้ Strings ไม่เปลี่ยนรูป? เหตุใดการเปลี่ยนค่านิยมจึงเป็นปัญหา มันน่าจะสะดวกกว่าด้วยซ้ำ :/ มีหลายสาเหตุนี้. อย่างแรกคือบันทึกหน่วยความจำ สามารถวางสตริงที่ไม่เปลี่ยนรูปในพูลสตริง ได้ทำให้สามารถใช้สตริงซ้ำได้แทนที่จะสร้างสตริงใหม่ ประการที่สองเพื่อความปลอดภัย ตัวอย่างเช่น ชื่อผู้ใช้และรหัสผ่านเป็นสตริงในเกือบทุกโปรแกรม การทำให้สามารถเปลี่ยนแปลงได้อาจส่งผลให้เกิดปัญหาในการอนุญาต มีเหตุผลอื่นๆ แต่การศึกษา Java ของเรายังไม่ครอบคลุมถึงสาเหตุเหล่านี้ ดังนั้นเราจะกลับมาที่ประเด็นเหล่านี้ในภายหลัง
ความคิดเห็น
  • เป็นที่นิยม
  • ใหม่
  • เก่า
คุณต้องลงชื่อเข้าใช้เพื่อแสดงความคิดเห็น
หน้านี้ยังไม่มีความคิดเห็นใด ๆ