JavaRush /จาวาบล็อก /Random-TH /10 หมายเหตุเกี่ยวกับ Static Modifier ใน Java

10 หมายเหตุเกี่ยวกับ Static Modifier ใน Java

เผยแพร่ในกลุ่ม
ตัวแก้ไข แบบคงที่ ใน Javaเชื่อมโยงโดยตรงกับคลาส หากฟิลด์เป็นแบบคงที่ แสดงว่าเป็นของคลาส ถ้าวิธีการเป็นแบบคงที่ ก็จะเหมือนกัน: เป็นของคลาส จากนี้ คุณสามารถเข้าถึงวิธีการหรือฟิลด์แบบคงที่โดยใช้ชื่อคลาสได้ ตัวอย่างเช่น หากฟิลด์การนับเป็นแบบคงที่ในคลาส Counter คุณจะสามารถเข้าถึงตัวแปรได้ด้วยการสืบค้นเช่น: Counter.count 10 หมายเหตุเกี่ยวกับ Static Modifier ใน Java - 1ก่อนที่เราจะเริ่มต้นด้วยบันทึกย่อ เรามาจำกันก่อน (และอาจค้นหาด้วย) ว่าสแตติก คืออะไร และสิ่งใดสามารถเป็นสแตติกได้ใน Java Staticคือตัวแก้ไขที่ใช้กับฟิลด์ บล็อก เมธอด หรือคลาสภายใน ตัวแก้ไขนี้บ่งชี้ว่าหัวเรื่องถูกผูกไว้กับคลาสปัจจุบัน

สนามแบบคงที่

เมื่อเราแสดงตัวแปรระดับชั้นเรียน เราระบุว่าค่านั้นเป็นของชั้นเรียน ถ้าคุณไม่ทำเช่นนี้ ค่าของตัวแปรจะถูกผูกไว้กับวัตถุที่สร้างขึ้นโดยใช้คลาสนี้ มันหมายความว่าอะไร? 10 หมายเหตุเกี่ยวกับ Static Modifier ใน Java - 2และความจริงก็คือถ้าตัวแปรไม่คงที่ แต่ละอ็อบเจ็กต์ใหม่ของคลาสนี้ก็จะมีค่าของตัวแปรนี้เอง โดยการเปลี่ยนแปลงที่เราเปลี่ยนมันในออบเจ็กต์เดียวเท่านั้น ตัวอย่างเช่น เรามีคลาส Car ที่ไม่มี -ตัวแปรคงที่:
public class Car {
  int km;
}
จากนั้นในหลัก:
Car orangeCar = new Car();
orangeCar.km = 100;

Car blueCar = new Car();
blueCar.km = 85;

System.out.println("Orange car - " + orangeCar.km);
System.out.println("Blue car - " + blueCar.km);
ผลลัพธ์ที่เราได้รับคือ:

Orange car - 100
Blue car - 85
อย่างที่คุณเห็น แต่ละวัตถุมีตัวแปรของตัวเอง ซึ่งการเปลี่ยนแปลงจะเกิดขึ้นกับวัตถุนี้เท่านั้น ถ้าเรามีตัวแปรคงที่ ค่าส่วนกลางนี้จะเหมือนกันสำหรับทุกคน ตอนนี้เรามีรถยนต์ที่มีตัวแปรคงที่:
public class Car {
  static int km;
}
จากนั้นโค้ดเดียวกันใน main จะส่งออกไปยังคอนโซล:

Orange car - 85
Blue car - 85
ท้ายที่สุดแล้ว เรามีตัวแปรหนึ่งตัวสำหรับเราทุกคน และทุกครั้งที่เราเปลี่ยนแปลงมัน โดยปกติแล้วตัวแปรคงที่จะเข้าถึงไม่ได้โดยการอ้างอิงอ็อบเจ็กต์ - orangeCar.km แต่เข้าถึงโดยชื่อคลาส - Car.km

บล็อกแบบคงที่

มีบล็อกการเริ่มต้นสองบล็อก - แบบปกติและแบบคงที่ บล็อกมีวัตถุประสงค์เพื่อเริ่มต้นตัวแปรภายใน หากบล็อกเป็นเรื่องปกติ ตัวแปรภายในของออบเจ็กต์จะถูกเตรียมใช้งานด้วยบล็อกนั้น แต่ถ้าเป็นแบบคงที่ ตัวแปรคงที่ (นั่นคือ ตัวแปรคลาส) จะถูกกำหนดให้กับบล็อกเหล่านั้น ตัวอย่างของคลาสที่มีบล็อกการเริ่มต้นแบบคงที่:
public class Car {
  static int km;

  static {
     km = 150;
  }
}

วิธีแบบคงที่

วิธีการแบบสแตติกแตกต่างจากวิธีการปกติตรงที่พวกมันยังถูกผูกไว้กับคลาสแทนที่จะเป็นอ็อบเจ็กต์ คุณสมบัติที่สำคัญของวิธีการแบบคงที่คือสามารถเข้าถึงตัวแปร/วิธีการแบบคงที่เท่านั้น ตัวอย่างเช่น ลองดูที่คลาสที่จะเป็นตัวนับที่ติดตามการเรียกใช้เมธอด:
public class Counter {
  static int count;

  public static void invokeCounter() {
     count++;
     System.out.println("Current counter value - " + count);
  }
}
เรียกมันว่าหลัก:
Counter.invokeCounter();
Counter.invokeCounter();
Counter.invokeCounter();
และเราได้รับผลลัพธ์ไปยังคอนโซล:

Текущее meaning счётчика - 1
Текущее meaning счётчика - 2
Текущее meaning счётчика - 3

คลาสคงที่ใน Java

เฉพาะคลาสภายในเท่านั้นที่สามารถเป็นคลาสคงที่ได้ อีกครั้งที่คลาสนี้เชื่อมโยงกับคลาสภายนอก และหากคลาสภายนอกได้รับการสืบทอดโดยคลาสอื่น คลาสนี้จะไม่ได้รับการสืบทอด ยิ่งไปกว่านั้น คลาสนี้สามารถสืบทอดได้ เช่นเดียวกับที่สามารถสืบทอดจากคลาสอื่น ๆ และใช้อินเทอร์เฟซได้ โดยพื้นฐานแล้ว คลาสที่ซ้อนกันแบบคงที่ไม่แตกต่างจากคลาสภายในอื่น ๆ ยกเว้นว่าออบเจ็กต์นั้นไม่มีการอ้างอิงถึงออบเจ็กต์คลาสภายนอกที่สร้างขึ้น อย่างไรก็ตาม สิ่งนี้ทำให้คลาสแบบสแตติกคล้ายกับคลาสที่ไม่ซ้อนกันทั่วไปมากที่สุด เนื่องจากความแตกต่างเพียงอย่างเดียวคือคลาสนั้นถูกรวมไว้ในคลาสอื่น ในบางกรณี นี่เป็นข้อได้เปรียบสำหรับเรา เนื่องจากจากนั้นเราจึงสามารถเข้าถึงตัวแปรสแตติกส่วนตัวของคลาสภายนอกได้ ตัวอย่างของคลาสสแตติกที่ซ้อนกัน:
public class Vehicle {

  public static class Car {
     public int km;
  }
}
การสร้างอินสแตนซ์ของคลาสนี้และการตั้งค่าของตัวแปรภายใน:
Vehicle.Car car = new Vehicle.Car();
car.km = 90;
หากต้องการใช้วิธีการ/ตัวแปร/คลาสแบบสแตติก เราไม่จำเป็นต้องสร้างอ็อบเจ็กต์ของคลาสนั้น แน่นอนว่าควรคำนึงถึงตัวแก้ไขการเข้าถึงด้วย ตัวอย่างเช่น ฟิลด์ต่างๆprivateจะสามารถเข้าถึงได้ภายในคลาสที่มีการประกาศเท่านั้น ช่องต่างๆprotectedพร้อมใช้งานสำหรับทุกคลาสภายในแพ็คเกจ ( package ) รวมถึงคลาสที่สืบทอดทั้งหมดที่อยู่นอกแพ็คเกจ สำหรับรายละเอียดเพิ่มเติม โปรดดูบทความ “ ส่วนตัว vs ได้รับการป้องกัน vs สาธารณะ ” สมมติว่ามีวิธีการคงที่increment()ในชั้นเรียนCounterที่มีหน้าที่เพิ่มตัวcountนับ หากต้องการเรียกเมธอดนี้ คุณสามารถใช้แบบฟอร์มCounter.increment()ได้ ไม่จำเป็นต้องสร้างอินสแตนซ์ของคลาสCounterเพื่อเข้าถึงฟิลด์หรือเมธอดแบบสแตติก นี่คือความแตกต่างพื้นฐานระหว่างวัตถุแบบคงที่และแบบไม่คงที่ (สมาชิกของคลาส) ฉันขอเตือนคุณอีกครั้งว่าสมาชิกคลาสแบบคงที่เป็นของคลาสโดยตรง ไม่ใช่ของอินสแตนซ์ นั่นคือค่าของตัวแปรคงcountที่จะเหมือนกันสำหรับออบเจ็กต์ทุกCounterประเภท ต่อไปในบทความนี้ เราจะดูแง่มุมพื้นฐานของการใช้ตัวแก้ไขแบบคงที่ใน Java รวมถึงคุณสมบัติบางอย่างที่จะช่วยให้คุณเข้าใจแนวคิดการเขียนโปรแกรมหลัก

สิ่งที่โปรแกรมเมอร์ทุกคนควรรู้เกี่ยวกับ Static modifier ใน Java

ในส่วนนี้ เราจะดูพื้นฐานของการใช้เมธอด ฟิลด์ และคลาสแบบคงที่ เริ่มจากตัวแปรกันก่อน
  1. คุณไม่สามารถเข้าถึงสมาชิกของคลาสที่ไม่คงที่ภายในบริบทคงที่ เช่น วิธีการหรือบล็อก การคอมไพล์โค้ดด้านล่างจะส่งผลให้เกิดข้อผิดพลาด:

    public class Counter{
    private int count;
    public static void main(String args[]){
       System.out.println(count); //compile time error
    }}

    นี่เป็นหนึ่งในข้อผิดพลาดที่พบบ่อยที่สุดที่โปรแกรมเมอร์ Java ทำ โดยเฉพาะมือใหม่ เนื่องจากวิธีการนี้mainเป็นแบบคงที่ แต่ตัวแปรcountไม่ใช่ ในกรณีนี้ วิธีการprintlnภายในวิธีการmainจะทำให้เกิด "ข้อผิดพลาดเวลาในการคอมไพล์"

  2. В отличие от локальных переменных, статические поля и методы НЕ потокобезопасны (Thread-safe) в Java. На практике это одна из наиболее частых причин возникновения проблем связанных с безопасностью мультипоточного программирования. Учитывая что каждый экземпляр класса имеет одну и ту же копию статической переменной, то такая переменная нуждается в защите — «залочивании» классом. Поэтому при использовании статических переменных, убедитесь, что они должным образом синхронизированы (synchronized), во избежание проблем, например таких How «состояние гонки» (race condition).

  3. Статические методы имеют преимущество в применении, т.к. отсутствует необходимость каждый раз создавать новый an object для доступа к таким методам. Статический метод можно вызвать, используя тип класса, в котором эти методы описаны. Именно поэтому, подобные методы How нельзя лучше подходят в качестве методов-фабрик (factory), и методов-утorт (utility). Класс java.lang.Math — замечательный пример, в котором почти все методы статичны, по этой же причине классы-утorты в Java финализированы (final).

  4. Другим важным моментом является то, что вы НЕ можете переопределять (Override) статические методы. Если вы объявите такой же метод в классе-наследнике (subclass), т.е. метод с таким же именем и сигнатурой, вы лишь «спрячете» метод суперкласса (superclass) instead of переопределения. Это явление известно How сокрытие методов (hiding methods). Это означает, что при обращении к статическому методу, который объявлен How в родительском, так и в дочернем классе, во время компиляции всегда будет вызван метод исходя из типа переменной. В отличие от переопределения, такие методы не будут выполнены во время работы программы. Рассмотрим пример:

    class Vehicle{
         public static void  kmToMiles(int km){
              System.out.println("Inside parent class/static method");
         } }
    
    class Car extends Vehicle{
         public static void  kmToMiles(int km){
              System.out.println("Inside child class/static method ");
         } }
    
    public class Demo{
       public static void main(String args[]){
          Vehicle v = new Car();
           v.kmToMiles(10);
      }}

    Вывод в консоль:

    Внутри родительского класса/статического метода

    Код наглядно демонстрирует: несмотря на то, что an object имеет тип Car, вызван статический метод из класса Vehicle, т.к. произошло обращение к методу во время компиляции. И заметьте, ошибки во время компиляции не возникло!

  5. Объявить статическим также можно и класс, за исключением классов верхнего уровня. Такие классы известны How «вложенные статические классы» (nested static class). Они бывают полезными для представления улучшенных связей. Яркий пример вложенного статического класса — HashMap.Entry, который предоставляет структуру данных внутри HashMap. Стоит заметить, также How и любой другой внутренний класс, вложенные классы находятся в отдельном файле .class. Таким образом, если вы объявor пять вложенных классов в вашем главном классе, у вас будет 6 файлов с расширением .class. Ещё одним примером использования является объявление собственного компаратора (Comparator), например компаратор по возрасту (AgeComparator) в классе сотрудники (Employee).

  6. Модификатор static также может быть объявлен в статичном блоке, более известным How «Статический блок инициализации» (Static initializer block), который будет выполнен во время загрузки класса. Если вы не объявите такой блок, то Java соберёт все статические поля в один список и выполнит его во время загрузки класса. Однако, статичный блок НЕ может пробросить перехваченные исключения, но может выбросить не перехваченные. В таком случае возникнет «Exception Initializer Error». На практике, любое исключение возникшее во время выполнения и инициализации статических полей, будет завёрнуто Java в эту ошибку. Это также самая частая причина ошибки «No Class Def Found Error», т.к. класс не находился в памяти во время обращения к нему.

  7. Полезно знать, что статические методы связываются во время компиляции, в отличие от связывания виртуальных or не статических методов, которые связываются во время исполнения на реальном an objectе. Следовательно, статические методы не могут быть переопределены в Java, т.к. полиморфизм во время выполнения не распространяется на них. Это важное ограничение, которое необходимо учитывать, объявляя метод статическим. В этом есть смысл, только тогда, когда нет возможности or необходимости переопределения такого метода классами-наследниками. Методы-фабрики и методы-утorты хорошие образцы применения модификатора static. Джошуа Блох выделил несколько преимуществ использования статичного метода-фабрики перед конструктором, в книге «Effective Java», которая является обязательной для прочтения каждым программистом данного языка.

  8. Важным свойством статического блока является инициализация. Статические поля or переменные инициализируются после загрузки класса в память. Порядок инициализации сверху вниз, в том же порядке, в Howом они описаны в исходном файле Java класса. Поскольку статические поля инициализируются на потокобезопасный манер, это свойство также используется для реализации паттерна Singleton. Если вы не используется список Enum How Singleton, по тем or иным причинам, то для вас есть хорошая альтернатива. Но в таком случае необходимо учесть, что это не «ленивая» инициализация. Это означает, что статическое поле будет проинициализировано ещё ДО того How кто-нибудь об этом «попросит». Если an object ресурсоёмкий or редко используется, то инициализация его в статическом блоке сыграет не в вашу пользу.

  9. ในระหว่างการทำให้เป็นอนุกรม เช่นเดียวกับtransientตัวแปร ฟิลด์คงที่จะไม่ถูกทำให้เป็นอนุกรม แท้จริงแล้ว หากคุณบันทึกข้อมูลใดๆ ในช่องคงที่ หลังจากดีซีเรียลไลซ์แล้ว อ็อบเจ็กต์ใหม่จะมีค่าหลัก (ค่าเริ่มต้น) ของมัน ตัวอย่างเช่น หากฟิลด์คงที่เป็นตัวแปรประเภทintดังนั้น ค่าของมันหลังจากการดีซีเรียลไลซ์จะเป็นศูนย์ ถ้า ชนิดfloatคือ 0.0 ถ้าชนิดObjectnull. จริงๆ แล้ว นี่เป็นหนึ่งในคำถามที่พบบ่อยที่สุดเกี่ยวกับการทำให้เป็นอนุกรมในการสัมภาษณ์ Java อย่าเก็บข้อมูลที่สำคัญที่สุดเกี่ยวกับวัตถุไว้ในเขตข้อมูลคงที่!

  10. และสุดท้ายเรามาพูดstatic importถึง ตัวแก้ไขนี้มีความเหมือนกันมากกับตัวดำเนินการมาตรฐานimportแต่ต่างจากตัวแก้ไขตรงที่ช่วยให้คุณสามารถนำเข้าสมาชิกแบบคงที่หนึ่งตัวหรือทั้งหมดของคลาสได้ เมื่อนำเข้าเมธอดแบบสแตติก สามารถเข้าถึงได้เสมือนว่าถูกกำหนดไว้ในคลาสเดียวกัน ในทำนองเดียวกันเมื่อนำเข้าฟิลด์ เราสามารถเข้าถึงได้โดยไม่ต้องระบุชื่อคลาส คุณลักษณะนี้เปิดตัวใน Java เวอร์ชัน 1.5 และเมื่อใช้อย่างถูกต้อง จะช่วยเพิ่มความสามารถในการอ่านโค้ด โครงสร้างนี้มักพบใน การทดสอบJUnitเนื่องจาก นักพัฒนาทดสอบเกือบทั้งหมดใช้static importวิธีการยืนยันassertEquals()และทำซ้ำมากเกินไป หากไม่มีสิ่งใดชัดเจนยินดีรับข้อมูลเพิ่มเติม

นั่นคือทั้งหมดที่ โปรแกรมเมอร์ทุกคนจะต้องรู้ประเด็นข้างต้นทั้งหมดเกี่ยวกับstatic modifier ใน Java บทความนี้ครอบคลุมข้อมูลพื้นฐานเกี่ยวกับตัวแปรคงที่ ฟิลด์ วิธีการ บล็อกการเริ่มต้น และการนำเข้า รวมถึงคุณสมบัติที่สำคัญบางประการ ความรู้ซึ่งเป็นสิ่งสำคัญในการเขียนและทำความเข้าใจโปรแกรมใน Java ฉันหวังว่านักพัฒนาทุกคนจะพัฒนาทักษะในการใช้แนวคิดคงที่เพราะ... นี่เป็นสิ่งสำคัญมากสำหรับการเขียนโปรแกรมอย่างจริงจัง"
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION