เรียกเมธอด Java โดยไม่มีชื่อ


101

ฉันดูโค้ดด้านล่างและพบว่ามีบางอย่างแปลก ๆ :

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 ");
    }
}

ฉันคาดว่าสิ่งนี้จะทำให้เกิดข้อผิดพลาดในการคอมไพล์เนื่องจากSystem.out"y" ไม่ได้เป็นของการประกาศวิธีการเพียงแค่ a { }. เหตุใดจึงใช้ได้ ฉันไม่เห็นว่ารหัสนี้จะเรียกว่าอย่างไร

เมื่อเรียกใช้สิ่งนี้จะสร้างขึ้นx y c gด้วยเหตุใดจึงถูกstatic { }เรียกก่อนตัวสร้างลำดับ

คำตอบ:


149

นี้:

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

เป็นบล็อกการเริ่มต้นแบบคงที่และถูกเรียกใช้เมื่อโหลดคลาส คุณสามารถมีได้มากเท่าที่คุณต้องการและพวกเขาจะถูกดำเนินการตามลำดับของรูปลักษณ์ (จากบนลงล่าง)

นี้:

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

เป็นบล็อกการเริ่มต้นและรหัสจะถูกคัดลอกไปยังจุดเริ่มต้นของตัวสร้างแต่ละตัวของคลาส ดังนั้นหากคุณมีคอนสตรัคเตอร์หลายตัวในคลาสของคุณและพวกเขาทั้งหมดจำเป็นต้องทำบางอย่างร่วมกันในช่วงเริ่มต้นคุณจะต้องเขียนโค้ดเพียงครั้งเดียวและวางไว้ในบล็อกการเริ่มต้นเช่นนี้

ดังนั้นผลลัพธ์ของคุณจึงเหมาะสมอย่างยิ่ง

ตามที่Stanleyแสดงความคิดเห็นด้านล่างโปรดดูส่วนในบทช่วยสอน Oracle ที่อธิบายถึงบล็อก initializaitonสำหรับข้อมูลเพิ่มเติม


12
คำตอบที่ดี ค้นหาข้อมูลเพิ่มเติมเกี่ยวกับบล็อกการเริ่มต้นได้ที่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- ไม่ถูกต้อง สมมติว่าตัวสร้างเริ่มต้นด้วยsuper("x ");ตัวสร้างขั้นสูงจะดำเนินการก่อนบล็อกการเริ่มต้นใด ๆ
RokL

3
ใช่การเรียกโดยนัยและชัดแจ้งไปยังตัวสร้างขั้นสูงจะถูกเรียกใช้ก่อนการเริ่มต้นบล็อกถัดไปและมากกว่าส่วนที่เหลือของโค้ดตัวสร้าง
jlordo

25

ไม่ได้เป็นวิธีการของ แต่บล็อกเริ่มต้น

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

มันจะถูกดำเนินการก่อนการเรียกตัวสร้าง ในขณะที่

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

เป็นบล็อกการเริ่มต้นแบบคงที่ซึ่งจะดำเนินการเมื่อคลาสถูกโหลดโดยคลาสโหลดเดอร์

ดังนั้นเมื่อคุณรันโค้ดของคุณ
1. คลาสถูกโหลดโดยคลาสโหลดเดอร์ดังนั้นบล็อกการเริ่มต้นแบบคงที่จึงถูกเรียกใช้
เอาต์พุต: x ถูกพิมพ์
2. อ็อบเจ็กต์ถูกสร้างขึ้นเพื่อให้บล็อกการเริ่มต้นถูกเรียกใช้งานจากนั้นตัวสร้างจะเรียกว่า
เอาต์พุต: y ถูกพิมพ์ตามด้วย c
3 มีการเรียกวิธีหลักซึ่งจะเรียกใช้เมธอด go
Output: g ถูกพิมพ์

ผลลัพธ์สุดท้าย: xycg
สิ่งนี้อาจช่วยได้http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/


@Cthulhu: ขอบคุณ ใช้ได้จนถึงสัปดาห์ที่แล้วฉันได้อัปเดตด้วยลิงค์ใหม่
xyz

16

นั่นคือบล็อกเช่นการเริ่มต้นตามด้วยบล็อกคงเริ่มต้น

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

ถูกเรียกเมื่อคุณสร้างอินสแตนซ์ของคลาส

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

ถูกเรียกเมื่อคลาสถูกโหลดโดยคลาสโหลดเดอร์ ดังนั้นเมื่อคุณทำ

new Sequence().go();

คลาสได้รับการโหลดดังนั้นมันจึงเรียกใช้งานstatic {}จากนั้นเรียกใช้งานบล็อกการเริ่มต้นอินสแตนซ์{}หลังจากนั้นร่างกายของตัวสร้างจะถูกเรียกใช้จากนั้นวิธีการบนอินสแตนซ์ที่สร้างขึ้นใหม่ Ergo x y c gเอาท์พุท


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

เป็นบล็อกแบบคงที่และถูกเรียกในระหว่างการโหลดคลาส

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

เป็นบล็อกการเริ่มต้น

คุณสามารถมีบล็อกการเริ่มต้นหลายบล็อกในคลาสซึ่งในกรณีนี้จะดำเนินการตามลำดับที่ปรากฏในคลาส

โปรดสังเกตว่าบล็อกการเริ่มต้นใด ๆ ที่มีอยู่ในคลาสจะถูกดำเนินการก่อนตัวสร้าง


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

เป็นบล็อกการเริ่มต้นที่ใช้ร่วมกันโดยคลาส (ตามที่ระบุโดยstatic) ซึ่งดำเนินการก่อน

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

}

เป็นบล็อกการเริ่มต้นที่ใช้ร่วมกันโดยอ็อบเจ็กต์ทั้งหมด (ตัวสร้าง) ของคลาสซึ่งตามมา

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

เป็นตัวสร้างเฉพาะสำหรับคลาสซึ่งดำเนินการครั้งที่สาม บล็อกการเริ่มต้นอินสแตนซ์จะถูกเรียกก่อนทุกครั้งที่เรียกใช้ตัวสร้าง นั่นเป็นเหตุผลที่ "y" มาก่อน "c"

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

เป็นเพียงวิธีการอินสแตนซ์ที่เชื่อมโยงกับอ็อบเจ็กต์ที่สร้างโดยใช้คอนสตรัคเตอร์ด้านบนซึ่งสุดท้าย


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

initializer blockชนิดเหล่านี้ของบล็อกนี้จะเรียกว่า จะดำเนินการทุกครั้งที่คุณสร้างอินสแตนซ์ของไฟล์class. ในขณะคอมไพล์โค้ดนี้จะถูกย้ายไปยังคอนสตรัคเตอร์ทุกคลาสของคุณ

ในกรณีของการstatic initializerบล็อก: -

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

จะดำเนินการหนึ่งครั้งเมื่อโหลดคลาส โดยทั่วไปเราใช้staticinitializer block เมื่อเริ่มต้นstaticฟิลด์ต้องใช้หลายขั้นตอน


6

มันถูกใช้เป็นบล็อก initialisationและทำงานหลังจากที่ใด ๆการประกาศคง สามารถใช้เพื่อให้แน่ใจว่าไม่มีใครสามารถสร้างอินสแตนซ์ของคลาสได้ (ในลักษณะเดียวกับที่คุณจะใช้ตัวสร้างส่วนตัว) เช่นเดียวกับรูปแบบการออกแบบSingleton


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

Static blocksจะดำเนินการเพียงครั้งเดียวเมื่อคลาสถูกโหลดและเริ่มต้นโดย JRE

และnon-staticบล็อกจะถูกเรียกทุกครั้งที่คุณสร้างอินสแตนซ์ใหม่และจะถูกเรียกก่อนคอนสตรัคเตอร์

ที่นี่คุณได้สร้างเพียง 1 อินสแตนซ์ของSequenceสิ่งที่สร้างขึ้นจึงถูกเรียกใช้หลังจากnon-staticบล็อกแล้ววิธีการที่เป็นเป้าหมายของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.