Gọi một phương thức Java không có tên


101

Tôi đang xem đoạn mã bên dưới và thấy có điều gì đó hơi lạ:

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

Tôi đã mong đợi điều này gây ra lỗi biên dịch vì System.out với "y" không thuộc về khai báo phương thức chỉ a { }. Tại sao điều này hợp lệ? Tôi không biết mã này sẽ hoặc nên được gọi như thế nào.

Khi chạy nó x y c gcũng tạo ra , tại sao static { }get được gọi trước hàm tạo chuỗi?

Câu trả lời:


149

Điều này:

static {
        System.out.print("x ");
    }

là một khối khởi tạo tĩnh và được gọi khi lớp được tải. Bạn có thể có bao nhiêu trong số chúng trong lớp tùy thích và chúng sẽ được thực thi theo thứ tự xuất hiện của chúng (từ trên xuống dưới).

Điều này:

    {
        System.out.print("y ");
    }

là một khối khởi tạo và mã được sao chép vào phần đầu của mỗi hàm tạo của lớp. Vì vậy, nếu bạn có nhiều hàm tạo trong lớp của mình và tất cả chúng đều cần thực hiện một điều gì đó chung khi bắt đầu, bạn chỉ cần viết mã một lần và đặt nó vào một khối khởi tạo như thế này.

Do đó đầu ra của bạn có ý nghĩa hoàn hảo.

Như Stanley đã nhận xét bên dưới, hãy xem phần trong hướng dẫn Oracle mô tả các khối khởi tạo để biết thêm thông tin.


12
Câu trả lời chính xác. Tìm hiểu thêm về khối khởi tạo tại http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Stanley

6
the code is copied into the beginning of each constructor of the class- điều này là không đúng. Giả sử hàm tạo bắt đầu bằng super("x ");, hàm tạo siêu sẽ thực thi trước bất kỳ khối khởi tạo nào.
RokL

3
vâng, các lệnh gọi ngầm định và rõ ràng tới siêu khối sẽ được thực hiện đầu tiên, khối khởi tạo tiếp theo và hơn phần còn lại của mã khởi tạo.
jlordo

25

Nó không phải là một phương thức mà là một khối khởi tạo .

 {
    System.out.print("y ");
 }

Nó sẽ được thực thi trước khi gọi hàm tạo. Trong khi

static {
        System.out.print("x ");
       }

khối khởi tạo tĩnh được thực thi khi lớp được tải bởi trình nạp lớp.

Vì vậy, khi bạn chạy mã của mình
1. Lớp được nạp bởi trình nạp lớp nên khối khởi tạo tĩnh được thực thi
Đầu ra: x được in ra
2. Đối tượng được tạo nên khối khởi tạo được thực thi và khi đó hằng số được gọi là
Đầu ra: y được in theo sau là c
3. Phương thức chính được gọi mà lần lượt gọi phương thức go
Đầu ra: g được in

Kết quả cuối cùng: xycg
Điều này có thể hữu ích cho http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/


@Cthulhu: Cảm ơn. Nó có hiệu lực cho đến tuần trước, tôi đã cập nhật nó với liên kết mới.
xyz

16

Đó là một khối khởi tạo phiên bản tiếp theo là một khối khởi tạo tĩnh .

{
    System.out.print("y ");
}

được gọi khi bạn tạo một thể hiện của lớp.

static {
    System.out.print("x ");
}

được gọi khi lớp được tải bởi trình tải lớp. Vì vậy, khi bạn làm

new Sequence().go();

lớp được tải, vì vậy nó thực thi static {}, sau đó nó thực thi khối khởi tạo cá thể {}, sau đó phần thân của hàm tạo được gọi và sau đó là phương thức trên cá thể mới được tạo. Ergo đầu ra x y c g.


15
static {
        System.out.print("x ");
    }

Là một khối tĩnh và được gọi trong quá trình Tải lớp

{
    System.out.print("y ");
}

Là một khối khởi tạo

Bạn có thể có nhiều khối khởi tạo trong một lớp trong trường hợp đó chúng thực thi theo trình tự xuất hiện trong lớp.

Lưu ý rằng bất kỳ khối khởi tạo nào có trong lớp đều được thực thi trước hàm tạo.


10
static {
      System.out.print("x ");
}

là một khối khởi tạo được chia sẻ bởi lớp (như được chỉ ra bởi static), khối này được thực thi đầu tiên.

{
        System.out.print("y ");

}

là một khối khởi tạo được chia sẻ bởi tất cả các đối tượng (hàm tạo) của lớp, sẽ xuất hiện tiếp theo.

Sequence() {
        System.out.print("c ");
}

là một hàm tạo cụ thể cho lớp, được thực thi thứ ba. Khối khởi tạo thể hiện được gọi đầu tiên mỗi khi phương thức khởi tạo được thực thi. Đó là lý do tại sao "y" đến ngay trước "c".

void go() {
        System.out.print("g ");
}

chỉ là một phương thức thể hiện được liên kết với các đối tượng được xây dựng bằng cách sử dụng hàm tạo ở trên, đến sau cùng.


9
{
    System.out.print("y ");
}

Các loại khối này được gọi là initializer block. Nó được thực thi mỗi khi bạn tạo một phiên bảnclass . Tại thời điểm biên dịch, mã này được chuyển vào mọi hàm tạo của lớp bạn.

Trong trường hợp của static initializerkhối: -

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

nó được thực thi một lần khi lớp được tải. Chúng tôi thường sử dụng statickhối khởi tạo khi khởi tạo một statictrường, yêu cầu nhiều bước.


6

Nó được sử dụng như một khối khởi tạo và chạy sau bất kỳ khai báo tĩnh nào . Nó có thể được sử dụng để đảm bảo rằng không ai khác có thể tạo một thể hiện của lớp (Theo cách giống như cách bạn sử dụng một phương thức khởi tạo riêng) như với mẫu thiết kế Singleton .


3
static {
    System.out.print("x ");
}

Static blockschỉ được thực thi một lần khi lớp được tải và khởi tạo bởi JRE.

non-statickhối sẽ được gọi mỗi khi bạn tạo một thể hiện mới và nó sẽ được gọi ngay trước Khối mã lệnh .

Như ở đây, bạn chỉ tạo một phiên bản được Sequencexây dựng như vậy đã được gọi sau non-staticcác khối và sau đó là phương thức thực sự là mục tiêu của bạn.

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.