Khối khởi tạo tĩnh


265

Theo như tôi hiểu thì "khối khởi tạo tĩnh" được sử dụng để đặt giá trị của trường tĩnh nếu không thể thực hiện được trong một dòng.

Nhưng tôi không hiểu tại sao chúng ta cần một khối đặc biệt cho điều đó. Ví dụ: chúng tôi khai báo một trường là tĩnh (không có gán giá trị). Và sau đó viết một vài dòng mã tạo và gán giá trị cho trường tĩnh được khai báo ở trên.

Tại sao chúng ta cần dòng này trong một khối đặc biệt như : static {...}?


6
Phản hồi nhỏ, nhưng sẽ hữu ích nếu bạn có thể vui lòng nêu rõ các giả định của mình và từ đó làm rõ câu trả lời nào là đúng. khi tôi lần đầu tiên đọc câu hỏi của bạn, tôi mis-hiểu và nghĩ rằng bạn biết sự khác biệt giữa {...}vs static {...}. (trong trường hợp đó Jon Skeet chắc chắn đã trả lời câu hỏi của bạn tốt hơn)
David T.

1
Câu hỏi này rất không rõ ràng; bạn có những người trả lời tranh giành và đưa ra nhiều phỏng đoán dài dòng về ý của bạn. Làm thế nào về việc viết rõ ràng khối khởi tạo tĩnh ví dụ mà bạn có trong tâm trí và sự thay thế của bạn, để mọi người có một cái gì đó rõ ràng để trả lời?
Don nở

Câu trả lời:


430

Khối không tĩnh:

{
    // Do Something...
}

Được gọi mỗi khi một thể hiện của lớp được xây dựng. Khối tĩnh chỉ được gọi một lần , khi chính lớp được khởi tạo, bất kể bạn tạo bao nhiêu đối tượng của loại đó.

Thí dụ:

public class Test {

    static{
        System.out.println("Static");
    }

    {
        System.out.println("Non-static block");
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test t2 = new Test();
    }
}

Bản in này:

Static
Non-static block
Non-static block

107
Tại sao đây là câu trả lời được chấp nhận? Nó thậm chí không trả lời câu hỏi.
Paul Bellora

43
Nó trả lời câu hỏi: "Điều này được gọi mỗi khi lớp được xây dựng. Khối tĩnh chỉ được gọi một lần, bất kể bạn tạo bao nhiêu đối tượng của loại đó."
Adam Arold

83
Đối với người đọc tò mò, khối không tĩnh thực sự được trình biên dịch Java sao chép vào mọi hàm tạo mà lớp có ( nguồn ). Vì vậy, đây vẫn là công việc của nhà xây dựng để khởi tạo các trường.
Martin Andersson

2
Câu trả lời được chấp nhận nên là câu trả lời này: stackoverflow.com/a/2420404/363573 . Câu trả lời này trình bày một ví dụ thực tế trong đó bạn cần các khối tĩnh.
Stephan

16
Tại sao câu trả lời này đột nhiên bị hạ cấp? Bạn có thể không đồng ý về việc đây là câu trả lời được chấp nhận, nhưng chắc chắn nó không phải là sai hoặc sai. Nó chỉ đơn giản là cố gắng giúp sự hiểu biết về các cấu trúc ngôn ngữ này với một ví dụ đơn giản.
Frederik Wordenskjold

133

Nếu họ không ở trong một khối khởi tạo tĩnh, họ sẽ ở đâu? Làm thế nào bạn có thể khai báo một biến chỉ có nghĩa là cục bộ cho mục đích khởi tạo và phân biệt nó với một trường? Ví dụ: bạn muốn viết như thế nào :

public class Foo {
    private static final int widgets;

    static {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        widgets = first + second;
    }
}

Nếu firstsecondkhông ở trong một khối, chúng sẽ trông giống như các trường. Nếu chúng ở trong một khối mà không staticở phía trước nó, thì nó sẽ được tính là một khối khởi tạo cá thể thay vì khối khởi tạo tĩnh, do đó, nó sẽ được thực hiện một lần trên mỗi cá thể được xây dựng thay vì tổng cộng một lần.

Bây giờ trong trường hợp cụ thể này, bạn có thể sử dụng một phương thức tĩnh thay thế:

public class Foo {
    private static final int widgets = getWidgets();

    static int getWidgets() {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        return first + second;
    }
}

... nhưng điều đó không hoạt động khi có nhiều biến bạn muốn gán trong cùng một khối hoặc không có biến nào (ví dụ: nếu bạn chỉ muốn đăng nhập một cái gì đó - hoặc có thể khởi tạo một thư viện riêng).


1
Là khối tĩnh xảy ra trước khi các biến tĩnh được chỉ định hoặc sau? private static int widgets = 0; static{widgets = 2;}
Weishi Zeng

1
Đã tò mò về việc khối tĩnh xảy ra trước khi các biến tĩnh được gán hoặc sau. ví dụ: private static int widgets = 0; static{widgets = 2;}Phát hiện ra rằng phép gán '=' xảy ra theo thứ tự, có nghĩa là '=' đặt đầu tiên sẽ được gán trước. Ví dụ trên sẽ cung cấp cho 'widget' giá trị là 2. (PS không biết rằng các bình luận chỉ có thể được chỉnh sửa trong 5 phút ...)
Weishi Zeng

@WeishiZeng: Vâng, đây là tài liệu trong docs.oracle.com/javase/specs/jls/se8/html/ Kẻ - điểm 9.
Jon Skeet

Nhưng bạn cũng không thể sử dụng một phương thức tĩnh riêng có cùng mã chính xác với khối khởi tạo tĩnh và gán các widget cho phương thức tĩnh riêng?
Zachary Kraus

1
@Zachary: Bạn có nghĩa là trả về giá trị và gán kết quả của cuộc gọi phương thức? Nếu vậy, có - khi bạn đang gán chính xác một biến là kết quả của khối. Sẽ chỉnh sửa câu trả lời của tôi với các chi tiết trong khoảng 7 giờ ...
Jon Skeet

103

Đây là một ví dụ:

  private static final HashMap<String, String> MAP = new HashMap<String, String>();
  static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

Mã trong (các) phần "tĩnh" sẽ được thực thi tại thời điểm tải lớp, trước khi bất kỳ trường hợp nào của lớp được xây dựng (và trước khi bất kỳ phương thức tĩnh nào được gọi từ nơi khác). Bằng cách đó bạn có thể đảm bảo rằng tất cả các tài nguyên lớp đã sẵn sàng để sử dụng.

Cũng có thể có các khối khởi tạo không tĩnh. Chúng hoạt động như các phần mở rộng cho tập hợp các phương thức constructor được định nghĩa cho lớp. Chúng trông giống như các khối khởi tạo tĩnh, ngoại trừ từ khóa "tĩnh" bị tắt.


4
Đối với ví dụ cụ thể đó, đôi khi mẫu nẹp đôi bị "lạm dụng" :)
BalusC

Nó có thể bị lạm dụng, nhưng mặt khác, nó làm sạch một số mớ hỗn độn và làm cho một số loại mã trở nên "rắn" hơn một chút. Tôi lập trình ở Erlang cho vui, và bạn bị cuốn hút vào việc không cần các biến cục bộ :-)
Pointy

1
<< Mã trong phần "tĩnh" sẽ được thực thi tại thời điểm tải lớp, trước khi bất kỳ phiên bản nào của lớp được xây dựng (và trước khi bất kỳ phương thức tĩnh nào được gọi từ nơi khác). Bằng cách đó bạn có thể đảm bảo rằng tất cả các tài nguyên lớp đã sẵn sàng để sử dụng. >> (Mà "nhọn" được đề cập trong câu trả lời ở trên) đây là điểm rất quan trọng cần lưu ý khi thực hiện khối tĩnh.
người học

Chúng ta có thể làm điều này bằng cách sử dụng LaunchizingBean sau phương thức afterProperIESset không?
ví dụ

48

Nó cũng hữu ích khi bạn thực sự không muốn gán giá trị cho bất cứ điều gì, chẳng hạn như tải một số lớp học chỉ một lần trong thời gian chạy.

Ví dụ

static {
    try {
        Class.forName("com.example.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        throw new ExceptionInInitializerError("Cannot load JDBC driver.", e);
    }
}

Này, có một lợi ích khác, bạn có thể sử dụng nó để xử lý các trường hợp ngoại lệ. Hãy tưởng tượng rằng getStuff()ở đây ném một Exceptioncái mà thực sự thuộc về một khối bắt:

private static Object stuff = getStuff(); // Won't compile: unhandled exception.

sau đó một static khởi tạo là hữu ích ở đây. Bạn có thể xử lý ngoại lệ ở đó.

Một ví dụ khác là làm những việc sau đó không thể thực hiện được trong khi gán:

private static Properties config = new Properties();

static {
    try { 
        config.load(Thread.currentThread().getClassLoader().getResourceAsStream("config.properties");
    } catch (IOException e) {
        throw new ExceptionInInitializerError("Cannot load properties file.", e);
    }
}

Để quay lại ví dụ về trình điều khiển JDBC, bất kỳ trình điều khiển JDBC phong nha nào cũng sử dụng trình statickhởi tạo để đăng ký chính nó trong DriverManager. Cũng thấy điều này và câu trả lời này .


2
Ở đây có một voodoo nguy hiểm ... các trình khởi tạo tĩnh được chạy trong phương thức tổng hợp clinit (), được đồng bộ hóa hoàn toàn . Điều này có nghĩa là JVM sẽ có được một khóa trên tệp lớp được đề cập. Điều này có thể dẫn đến bế tắc trong môi trường đa luồng nếu hai lớp cố gắng tải lẫn nhau và mỗi lớp bắt đầu tải trong một luồng khác nhau. Xem www-01.ibm.com/support/docview.wss?uid=swg1IV48872
Ajax

@Ajax: Tôi coi đây là một lỗi trong trình điều khiển JDBC đang được đề cập hoặc trong mã ứng dụng chịu trách nhiệm tải nó. Thông thường, trong trường hợp trình điều khiển JDBC phong nha, miễn là bạn chỉ tải nó một lần trên toàn bộ ứng dụng trong quá trình khởi động ứng dụng, không có vấn đề gì.
BalusC

Tuy nhiên, đây chắc chắn sẽ là một lỗi nhưng không hoàn toàn là lỗi của trình điều khiển JDBC. Có thể trình điều khiển vô tình có các trình khởi tạo tĩnh riêng và có thể bạn vô tình khởi tạo lớp này cùng với một số người khác trong ứng dụng của bạn và, ồ không, một số lớp không mong đợi tải theo chu kỳ lẫn nhau, và bây giờ ứng dụng của bạn bị bế tắc. Tôi phát hiện ra điều này nhờ vào sự bế tắc giữa java.awt.AWTEvent và sun.util.logging.Pl platformLogger. Tôi chỉ chạm vào AWTEvent để bảo nó chạy không đầu, và một số lib khác đang tải lên PlatformLogger ... mà AWTEvent cũng tải.
Ajax

1
Cả hai lớp đều được đồng bộ hóa trên các luồng khác nhau và bản dựng của tôi bị bế tắc khoảng 1/150 lần chạy. Vì vậy, bây giờ tôi cẩn thận hơn rất nhiều khi tải lớp trong các khối tĩnh. Trong trường hợp tôi đã đề cập ở trên, sử dụng mẫu nhà cung cấp bị trì hoãn trong đó tôi có thể tạo lớp nhà cung cấp tạm thời ngay lập tức (không có cơ hội bế tắc), khởi tạo trường và sau đó khi nó thực sự được truy cập (trong truy cập trường không được đồng bộ hóa), sau đó tôi thực sự tải các lớp có thể gây ra bế tắc.
Ajax

11

Tôi muốn nói static blockchỉ là cú pháp đường. Không có gì bạn có thể làm với statickhối và không phải với bất cứ điều gì khác.

Để sử dụng lại một số ví dụ được đăng ở đây.

Đoạn mã này có thể được viết lại mà không cần sử dụng bộ statickhởi tạo.

Phương pháp # 1: Với static

private static final HashMap<String, String> MAP;
static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

Phương pháp # 2: Không có static

private static final HashMap<String, String> MAP = getMap();
private static HashMap<String, String> getMap()
{
    HashMap<String, String> ret = new HashMap<>();
    ret.put("banana", "honey");
    ret.put("peanut butter", "jelly");
    ret.put("rice", "beans");
    return ret;
}

10

Có một vài lý do thực tế mà nó bắt buộc phải tồn tại:

  1. khởi tạo static finalthành viên có khởi tạo có thể ném ngoại lệ
  2. khởi tạo static finalthành viên với các giá trị được tính toán

Mọi người có xu hướng sử dụng static {}các khối như một cách thuận tiện để khởi tạo những thứ mà lớp cũng phụ thuộc vào thời gian chạy - chẳng hạn như đảm bảo rằng lớp cụ thể được tải (ví dụ: trình điều khiển JDBC). Điều đó có thể được thực hiện theo những cách khác; tuy nhiên, hai điều mà tôi đề cập ở trên chỉ có thể được thực hiện với một cấu trúc như static {}khối.


8

Bạn có thể thực thi các bit mã một lần cho một lớp trước khi một đối tượng được xây dựng trong các khối tĩnh.

Ví dụ

class A {
  static int var1 = 6;
  static int var2 = 9;
  static int var3;
  static long var4;

  static Date date1;
  static Date date2;

  static {
    date1 = new Date();

    for(int cnt = 0; cnt < var2; cnt++){
      var3 += var1;
    }

    System.out.println("End first static init: " + new Date());
  }
}

7

Đó là một quan niệm sai lầm phổ biến khi nghĩ rằng một khối tĩnh chỉ có quyền truy cập vào các trường tĩnh. Để làm điều này, tôi muốn trình bày đoạn mã dưới đây mà tôi thường sử dụng trong các dự án thực tế (được sao chép một phần từ câu trả lời khác trong ngữ cảnh hơi khác):

public enum Language { 
  ENGLISH("eng", "en", "en_GB", "en_US"),   
  GERMAN("de", "ge"),   
  CROATIAN("hr", "cro"),   
  RUSSIAN("ru"),
  BELGIAN("be",";-)");

  static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>(); 
  static { 
    for (Language l:Language.values()) { 
      // ignoring the case by normalizing to uppercase
      ALIAS_MAP.put(l.name().toUpperCase(),l); 
      for (String alias:l.aliases) ALIAS_MAP.put(alias.toUpperCase(),l); 
    } 
  } 

  static public boolean has(String value) { 
    // ignoring the case by normalizing to uppercase
    return ALIAS_MAP.containsKey(value.toUpper()); 
  } 

  static public Language fromString(String value) { 
    if (value == null) throw new NullPointerException("alias null"); 
    Language l = ALIAS_MAP.get(value); 
    if (l == null) throw new IllegalArgumentException("Not an alias: "+value); 
    return l; 
  } 

  private List<String> aliases; 
  private Language(String... aliases) { 
    this.aliases = Arrays.asList(aliases); 
  } 
} 

Ở đây, trình khởi tạo được sử dụng để duy trì một chỉ mục ( ALIAS_MAP), để ánh xạ một tập các bí danh trở về kiểu enum ban đầu. Nó được dự định như một phần mở rộng cho phương thức valueOf tích hợp được cung cấp bởiEnum chính nó .

Như bạn có thể thấy, trình khởi tạo tĩnh truy cập ngay cả privatetrường aliases. Điều quan trọng là phải hiểu rằng statickhối đã có quyền truy cập vào các Enumtrường hợp giá trị (ví dụ ENGLISH). Điều này là do thứ tự khởi tạo và thực thi trong trường hợp các Enumloại , giống như các static privatetrường đã được khởi tạo với các thể hiện trước khi các statickhối được gọi:

  1. Các Enumhằng số là các trường tĩnh ẩn. Điều này đòi hỏi các khối xây dựng và khối đối tượng Enum và khởi tạo thể hiện cũng xảy ra trước tiên.
  2. static chặn và khởi tạo các trường tĩnh theo thứ tự xuất hiện.

Việc khởi tạo không theo thứ tự này (hàm tạo trước statickhối) rất quan trọng cần lưu ý. Nó cũng xảy ra khi chúng ta khởi tạo các trường tĩnh với các thể hiện tương tự như Singleton (đơn giản hóa được thực hiện):

public class Foo {
  static { System.out.println("Static Block 1"); }
  public static final Foo FOO = new Foo();
  static { System.out.println("Static Block 2"); }
  public Foo() { System.out.println("Constructor"); }
  static public void main(String p[]) {
    System.out.println("In Main");
    new Foo();
  }
}

Những gì chúng ta thấy là đầu ra sau đây:

Static Block 1
Constructor
Static Block 2
In Main
Constructor

Rõ ràng là việc khởi tạo tĩnh thực sự có thể xảy ra trước hàm tạo và thậm chí sau:

Chỉ cần truy cập Foo trong phương thức chính, khiến lớp được tải và khởi tạo tĩnh bắt đầu. Nhưng như là một phần của khởi tạo tĩnh, chúng ta lại gọi các hàm tạo cho các trường tĩnh, sau đó nó tiếp tục khởi tạo tĩnh và hoàn thành hàm tạo được gọi từ bên trong phương thức chính. Tình huống khá phức tạp mà tôi hy vọng rằng trong mã hóa thông thường, chúng ta sẽ không phải đối phó.

Để biết thêm thông tin về điều này, hãy xem cuốn sách " Java hiệu quả ".


1
Có quyền truy cập aliaseskhông có nghĩa là khối tĩnh có thể truy cập các thành viên không tĩnh. aliasesđược truy cập thông qua các Languagegiá trị được trả về bởi values()phương thức / static / . Như bạn đã đề cập, thực tế là các biến enum đã có sẵn tại thời điểm đó là bit bất thường - các thành viên không tĩnh của các lớp thông thường sẽ không thể truy cập được trong tình huống này.
Ignazio

Khối tĩnh vẫn chỉ truy cập các trường tĩnh (trong trường hợp enum ENGLISH, GERMAN, ...) mà trong trường hợp này là các đối tượng. Vì các trường tĩnh là chính các đối tượng, bạn có thể truy cập vào trường đối tượng của đối tượng tĩnh.
Swami PR

1
class Foo { static final Foo Inst1; static final Foo Inst2; static{ Inst1 = new Foo("Inst1"); Inst2 = new Foo("Inst2"); } static { System.out.println("Inst1: " + Inst1.member); System.out.println("Inst2: " + Inst2.member); } private final String member; private Foo(String member){ this.member = member; } } Đoạn mã trên không khác với ví dụ enum và vẫn cho phép truy cập biến thể hiện bên trong khối tĩnh
Swami PR

@SwamiPR thực sự nó biên dịch, làm tôi ngạc nhiên, và tôi phải đồng ý rằng về nguyên tắc mã không khác nhau. Tôi phải đọc lại thông số kỹ thuật Java, tôi cảm thấy rằng có một cái gì đó tôi đã bỏ lỡ. Phản hồi tốt, cảm ơn.
YoYo

@SwamiPR Vấn đề thực sự là chúng ta nên sử dụng một Enum. Đó là cách tốt nhất để đảm bảo rằng chúng tôi đang chỉ đến các trường hợp cá biệt '- xem tại đây . Và theo quan điểm của bạn, tôi đã thực hiện một số cập nhật.
YoYo

3

Nếu các biến tĩnh của bạn cần được đặt trong thời gian chạy thì một static {...}khối rất hữu ích.

Ví dụ: nếu bạn cần đặt thành viên tĩnh thành giá trị được lưu trữ trong tệp cấu hình hoặc cơ sở dữ liệu.

Cũng hữu ích khi bạn muốn thêm các giá trị cho một Mapthành viên tĩnh vì bạn không thể thêm các giá trị này vào khai báo thành viên ban đầu.


3

Vì vậy, bạn có một trường tĩnh (nó còn được gọi là "biến lớp" vì nó thuộc về lớp chứ không phải là một thể hiện của lớp; nói cách khác, nó được liên kết với lớp chứ không phải với bất kỳ đối tượng nào) và bạn muốn khởi tạo nó. Vì vậy, nếu bạn KHÔNG muốn tạo một thể hiện của lớp này và bạn muốn thao tác trường tĩnh này, bạn có thể thực hiện theo ba cách:

1- Chỉ khởi tạo nó khi bạn khai báo biến:

static int x = 3;

2- Có khối khởi tạo tĩnh:

static int x;

static {
 x=3;
}

3- Có một phương thức lớp (phương thức tĩnh) truy cập vào biến lớp và khởi tạo nó: đây là phương thức thay thế cho khối tĩnh ở trên; bạn có thể viết một phương thức tĩnh riêng:

public static int x=initializeX();

private static int initializeX(){
 return 3;
}

Bây giờ tại sao bạn sẽ sử dụng khối khởi tạo tĩnh thay vì các phương thức tĩnh?

Nó thực sự phụ thuộc vào những gì bạn cần trong chương trình của bạn. Nhưng bạn phải biết rằng khối khởi tạo tĩnh được gọi một lần và lợi thế duy nhất của phương thức lớp là chúng có thể được sử dụng lại sau này nếu bạn cần khởi tạo lại biến lớp.

giả sử bạn có một mảng phức tạp trong chương trình của bạn. Bạn khởi tạo nó (sử dụng cho vòng lặp chẳng hạn) và sau đó các giá trị trong mảng này sẽ thay đổi trong suốt chương trình nhưng sau đó tại một số điểm bạn muốn khởi tạo lại nó (trở về giá trị ban đầu). Trong trường hợp này, bạn có thể gọi phương thức tĩnh riêng. Trong trường hợp bạn không cần trong chương trình của mình để xác định lại các giá trị, bạn chỉ có thể sử dụng khối tĩnh và không cần phương thức tĩnh vì bạn sẽ không sử dụng nó sau này trong chương trình.

Lưu ý: các khối tĩnh được gọi theo thứ tự chúng xuất hiện trong mã.

Ví dụ 1:

class A{
 public static int a =f();

// this is a static method
 private static int f(){
  return 3;
 }

// this is a static block
 static {
  a=5;
 }

 public static void main(String args[]) {
// As I mentioned, you do not need to create an instance of the class to use the class variable
  System.out.print(A.a); // this will print 5
 }

}

Ví dụ 2:

class A{
 static {
  a=5;
 }
 public static int a =f();

 private static int f(){
  return 3;
 }

 public static void main(String args[]) {
  System.out.print(A.a); // this will print 3
 }

}

0

Là bổ sung, như @Pointy nói

Mã trong (các) phần "tĩnh" sẽ được thực thi tại thời điểm tải lớp, trước khi bất kỳ trường hợp nào của lớp được xây dựng (và trước khi bất kỳ phương thức tĩnh nào được gọi từ nơi khác).

Nó được cho là thêm System.loadLibrary("I_am_native_library")vào khối tĩnh.

static{
    System.loadLibrary("I_am_a_library");
}

Nó sẽ đảm bảo không có phương thức riêng nào được gọi trước khi thư viện liên quan được tải vào bộ nhớ.

Theo loadL Library từ oracle :

Nếu phương thức này được gọi nhiều lần với cùng tên thư viện, các cuộc gọi thứ hai và tiếp theo sẽ bị bỏ qua.

Vì vậy, khá bất ngờ, việc đặt System.loadL Library không được sử dụng để tránh thư viện được tải nhiều lần.


0

Trước tiên bạn cần hiểu rằng chính các lớp ứng dụng của bạn được khởi tạo cho java.class.Classcác đối tượng trong thời gian chạy. Đây là khi khối tĩnh của bạn được chạy. Vì vậy, bạn thực sự có thể làm điều này:

public class Main {

    private static int myInt;

    static {
        myInt = 1;
        System.out.println("myInt is 1");
    }

    //  needed only to run this class
    public static void main(String[] args) {
    }

}

và nó sẽ in "myInt là 1" lên bàn điều khiển. Lưu ý rằng tôi đã không khởi tạo bất kỳ lớp học.


0
static int B,H;
static boolean flag = true;
static{
    Scanner scan = new Scanner(System.in);
    B = scan.nextInt();
    scan.nextLine();
    H = scan.nextInt();

    if(B < 0 || H < 0){
        flag = false;
        System.out.println("java.lang.Exception: Breadth and height must be positive");
    } 
}

-1

Khối tĩnh được sử dụng cho bất kỳ công nghệ nào để khởi tạo thành viên dữ liệu tĩnh theo cách động hoặc chúng ta có thể nói về việc khởi tạo động của khối tĩnh thành viên dữ liệu tĩnh đang được sử dụng..Bởi vì khởi tạo thành viên dữ liệu không tĩnh chúng ta có hàm tạo nhưng chúng ta không có bất cứ nơi nào chúng ta có thể tự động khởi tạo thành viên dữ liệu tĩnh

Eg:-class Solution{
         // static int x=10;
           static int x;
       static{
        try{
          x=System.out.println();
          }
         catch(Exception e){}
        }
       }

     class Solution1{
      public static void main(String a[]){
      System.out.println(Solution.x);
        }
        }

Bây giờ int int x của tôi sẽ khởi tạo động ..Bcoz khi trình biên dịch sẽ chuyển sang Solution.x, nó sẽ tải Lớp giải pháp và tải khối tĩnh tại thời gian tải lớp..Vậy chúng ta có thể tự động khởi tạo thành viên dữ liệu tĩnh đó ..

}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.