JavaRush /Blog Java /Random-VI /10 lưu ý về Công cụ sửa đổi tĩnh trong Java

10 lưu ý về Công cụ sửa đổi tĩnh trong Java

Xuất bản trong nhóm
Công cụ sửa đổi tĩnh trong Java được liên kết trực tiếp với lớp. Nếu trường là tĩnh thì nó thuộc về lớp, nếu phương thức là tĩnh thì nó giống nhau: nó thuộc về lớp. Dựa vào điều này, bạn có thể truy cập một phương thức hoặc trường tĩnh bằng tên lớp. Ví dụ: nếu trường đếm là tĩnh trong lớp Counter thì bạn có thể truy cập biến bằng truy vấn như: Counter.count. 10 lưu ý về Static Modifier trong Java - 1Trước khi bắt đầu với các ghi chú, chúng ta hãy nhớ (và có thể tìm hiểu) tĩnh là gì và tĩnh có thể là gì trong Java. Tĩnh là một công cụ sửa đổi được áp dụng cho một trường, khối, phương thức hoặc lớp bên trong. Công cụ sửa đổi này chỉ ra rằng chủ đề được liên kết với lớp hiện tại.

Trường tĩnh

Khi chúng ta biểu thị một biến cấp độ lớp, chúng ta chỉ ra rằng giá trị đó thuộc về một lớp. Nếu bạn không làm điều này, giá trị của biến sẽ bị ràng buộc với một đối tượng được tạo bằng lớp này. Nó có nghĩa là gì? 10 lưu ý về Static Modifier trong Java - 2Và thực tế là nếu biến không tĩnh thì mỗi đối tượng mới của lớp này sẽ có giá trị riêng của biến này, bằng cách thay đổi mà chúng ta thay đổi nó chỉ trong một đối tượng: Ví dụ: chúng ta có một lớp Car với một không -biến tĩnh:
public class Car {
  int km;
}
Sau đó, trong chính:
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);
Đầu ra chúng tôi nhận được là:

Orange car - 100
Blue car - 85
Như bạn có thể thấy, mỗi đối tượng có một biến riêng, sự thay đổi chỉ xảy ra đối với đối tượng này. Chà, nếu chúng ta có một biến tĩnh thì giá trị toàn cục này sẽ giống nhau đối với mọi người: Bây giờ chúng ta có một chiếc Ô tô với một biến tĩnh:
public class Car {
  static int km;
}
Sau đó, mã tương tự trong main sẽ xuất ra bảng điều khiển:

Orange car - 85
Blue car - 85
Suy cho cùng, chúng ta có một biến số cho tất cả chúng ta và mỗi lần chúng ta thay đổi nó. Các biến tĩnh thường được truy cập không phải bằng tham chiếu đối tượng - orangeCar.km, mà bằng tên lớp - Car.km

Khối tĩnh

Có hai khối khởi tạo - thường xuyên và tĩnh. Khối này nhằm mục đích khởi tạo các biến nội bộ. Nếu khối bình thường, thì các biến nội bộ của đối tượng sẽ được khởi tạo cùng với nó, nhưng nếu nó là tĩnh, thì các biến tĩnh (tức là các biến lớp) sẽ được gán cho chúng. Ví dụ về một lớp có khối khởi tạo tĩnh:
public class Car {
  static int km;

  static {
     km = 150;
  }
}

Phương pháp tĩnh

Các phương thức tĩnh khác với các phương thức thông thường ở chỗ chúng cũng bị ràng buộc với một lớp chứ không phải một đối tượng. Một thuộc tính quan trọng của phương thức tĩnh là nó chỉ có thể truy cập các biến/phương thức tĩnh. Ví dụ: hãy xem một lớp sẽ là một loại bộ đếm theo dõi các lệnh gọi phương thức:
public class Counter {
  static int count;

  public static void invokeCounter() {
     count++;
     System.out.println("Current counter value - " + count);
  }
}
Hãy gọi nó là chính:
Counter.invokeCounter();
Counter.invokeCounter();
Counter.invokeCounter();
Và chúng tôi nhận được đầu ra cho bàn điều khiển:

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

Lớp tĩnh trong Java

Chỉ có lớp bên trong mới có thể là lớp tĩnh. Một lần nữa, lớp này được gắn với lớp bên ngoài, và nếu lớp bên ngoài được kế thừa bởi lớp khác thì lớp này sẽ không được kế thừa. Hơn nữa, lớp này có thể được kế thừa, giống như nó có thể được kế thừa từ bất kỳ lớp nào khác và triển khai một giao diện. Về cơ bản, một lớp lồng tĩnh không khác với bất kỳ lớp bên trong nào khác, ngoại trừ việc đối tượng của nó không chứa tham chiếu đến đối tượng lớp bên ngoài đã tạo ra nó. Tuy nhiên, điều này làm cho một lớp tĩnh giống nhất với một lớp không lồng nhau thông thường, bởi vì điểm khác biệt duy nhất là nó được bao bọc trong một lớp khác. Trong một số trường hợp, đây là một lợi thế cho chúng ta, vì từ đó chúng ta có quyền truy cập vào các biến tĩnh riêng tư của lớp bên ngoài. Ví dụ về lớp tĩnh lồng nhau:
public class Vehicle {

  public static class Car {
     public int km;
  }
}
Tạo một thể hiện của lớp này và đặt giá trị của biến nội bộ:
Vehicle.Car car = new Vehicle.Car();
car.km = 90;
Để sử dụng các phương thức/biến/lớp tĩnh, chúng ta không cần tạo một đối tượng của lớp đó. Tất nhiên, cần tính đến các công cụ sửa đổi quyền truy cập. Ví dụ: các trường privatechỉ có thể truy cập được trong lớp mà chúng được khai báo. Các trường protectedcó sẵn cho tất cả các lớp bên trong một gói ( package ), cũng như cho tất cả các lớp kế thừa bên ngoài gói. Để biết thêm chi tiết, hãy xem bài viết “ riêng tư, được bảo vệ và công khai ”. Giả sử có một phương thức tĩnh increment()trong lớp Countercó nhiệm vụ tăng bộ đếm count. Để gọi phương thức này, bạn có thể sử dụng lệnh gọi có dạng Counter.increment(). Không cần phải khởi tạo một lớp Counterđể truy cập vào trường hoặc phương thức tĩnh. Đây là điểm khác biệt cơ bản giữa các đối tượng tĩnh và KHÔNG tĩnh (thành viên lớp). Hãy để tôi nhắc bạn một lần nữa rằng các thành viên lớp tĩnh trực tiếp thuộc về lớp chứ không thuộc về thể hiện của nó. Nghĩa là, giá trị của biến tĩnh countsẽ giống nhau đối với tất cả các đối tượng thuộc loại Counter. Ở phần sau của bài viết này, chúng ta sẽ xem xét các khía cạnh cơ bản của việc sử dụng công cụ sửa đổi tĩnh trong Java, cũng như một số tính năng sẽ giúp bạn hiểu các khái niệm lập trình chính.

Những điều mọi lập trình viên nên biết về Công cụ sửa đổi tĩnh trong Java

Trong phần này, chúng ta sẽ xem xét những điều cơ bản về cách sử dụng các phương thức, trường và lớp tĩnh. Hãy bắt đầu với các biến.
  1. Bạn không thể truy cập các thành viên không tĩnh của một lớp trong ngữ cảnh tĩnh, chẳng hạn như một phương thức hoặc khối. Biên dịch mã dưới đây sẽ dẫn đến lỗi:

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

    Đây là một trong những lỗi phổ biến nhất của các lập trình viên Java, đặc biệt là những người mới. Vì phương thức này mainlà tĩnh nhưng biến countthì không, nên trong trường hợp này, phương thức printlnbên trong phương thức mainsẽ đưa ra “Lỗi thời gian biên dịch”.

  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. Trong quá trình tuần tự hóa, giống như transientcác biến, các trường tĩnh không được tuần tự hóa. Thật vậy, nếu bạn lưu bất kỳ dữ liệu nào vào một trường tĩnh, thì sau khi giải tuần tự hóa đối tượng mới sẽ chứa giá trị chính (mặc định) của nó, ví dụ: nếu trường tĩnh là một biến thuộc loại , intthì giá trị của nó sau khi giải tuần tự hóa sẽ bằng 0, nếu loại floatlà 0,0, nếu loại Objectnull. Thành thật mà nói, đây là một trong những câu hỏi thường gặp nhất liên quan đến việc tuần tự hóa trong các cuộc phỏng vấn Java. Đừng lưu trữ dữ liệu quan trọng nhất về một đối tượng trong trường tĩnh!

  10. Và cuối cùng, hãy nói về static import. Công cụ sửa đổi này có nhiều điểm chung với toán tử tiêu chuẩn import, nhưng không giống như nó, nó cho phép bạn nhập một hoặc tất cả các thành viên tĩnh của một lớp. Khi import các phương thức tĩnh, chúng ta có thể truy cập chúng như thể chúng được định nghĩa trong cùng một lớp, tương tự khi import các trường, chúng ta có thể truy cập chúng mà không cần chỉ định tên lớp. Tính năng này đã được giới thiệu trong phiên bản Java 1.5 và khi được sử dụng đúng cách sẽ cải thiện khả năng đọc mã. Cấu trúc này thường được tìm thấy nhiều nhất trong các thử nghiệm JUnit , bởi vì static importVí dụ: hầu hết tất cả các nhà phát triển thử nghiệm đều sử dụng các phương thức khẳng định assertEquals()và các phương thức trùng lặp quá tải của chúng. Nếu không có gì rõ ràng, chào mừng bạn đến để biết thêm thông tin .

Đó là tất cả. Mọi lập trình viên đều phải biết tất cả những điểm trên về công cụ sửa đổi tĩnh trong Java . Bài viết này đề cập đến thông tin cơ bản về các biến tĩnh, trường, phương thức, khối khởi tạo và nhập. Bao gồm một số thuộc tính quan trọng, kiến ​​thức về chúng rất quan trọng khi viết và hiểu các chương trình trong Java. Tôi hy vọng rằng mọi nhà phát triển sẽ hoàn thiện kỹ năng sử dụng các khái niệm tĩnh của mình vì... Điều này rất quan trọng đối với việc lập trình nghiêm túc."
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION