Java ตัวแปรคงที่ วิธีการคงที่ใน Java, วิธีการโอเวอร์โหลด, การเรียกซ้ำ สิ่งที่โปรแกรมเมอร์ทุกคนควรรู้เกี่ยวกับ Static modifier ใน Java

อะไรเป็นแบบคงที่

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

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

วิธีการประกาศเป็นแบบคงที่อยู่ภายใต้ข้อจำกัดหลายประการ

  • พวกเขาสามารถเรียกวิธีการคงที่อื่น ๆ เท่านั้น
  • ควรเข้าถึงเฉพาะตัวแปรคงที่เท่านั้น
  • พวกเขาไม่สามารถอ้างถึงสมาชิกประเภทนี้หรือซุปเปอร์ในทางใดทางหนึ่งได้ (คำหลักขั้นสูงเกี่ยวข้องกับการสืบทอดและจะกล่าวถึงในบทถัดไป)

หากคุณต้องการคำนวณเพื่อเริ่มต้นตัวแปรคงที่ คุณสามารถประกาศบล็อกคงที่ที่จะดำเนินการเพียงครั้งเดียวเมื่อโหลดคลาสครั้งแรก ตัวอย่างต่อไปนี้แสดงคลาสที่มีวิธีการคงที่ ตัวแปรคงที่หลายตัว และบล็อกการเริ่มต้นแบบคงที่:

// การสาธิตตัวแปรคงที่ วิธีการ และบล็อก
คลาส UseStatic (
คงที่ int a = 3;
int คงที่ b;
โมฆะคงที่ meth (int x) (
System.out.println("x = " + x) ;
System.out.println("a = " + a);
System.out.println("b = " + b) ;
}
คงที่ (
System.out.println("บล็อกแบบคงที่เตรียมใช้งานแล้ว");
ข = ก * 4;
}

ยาบ้า (42);
}
}

ทันทีหลังจากโหลดคลาส UseStatic โปรแกรมจะรันคำสั่งคงที่ทั้งหมด ขั้นแรก ค่าของ a ถูกตั้งค่าเป็น 3 จากนั้นโปรแกรมจะดำเนินการบล็อกคงที่ที่พิมพ์ข้อความ จากนั้นเริ่มต้นตัวแปร b ด้วยค่า a*4 หรือ 12 จากนั้นโปรแกรมจะเรียกใช้เมธอด main() ซึ่งเรียกเมธอด meth() โดยส่งผ่านค่า x 42 คำสั่ง println() สามคำสั่งอ้างอิงตัวแปรคงที่สองตัว a และ b ไปยังตัวแปรท้องถิ่น x

ผลลัพธ์ของโปรแกรมนี้มีลักษณะดังนี้:

เริ่มต้นบล็อกแบบคงที่ x = 42 a = 3 b = 12

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

class_name.method()

ในที่นี้ class_name คือชื่อของคลาสที่มีการประกาศวิธีการประเภท static อย่างที่คุณเห็น รูปแบบนี้คล้ายกับรูปแบบที่ใช้ในการเรียกเมธอดที่ไม่คงที่ผ่านตัวแปรอ้างอิงอ็อบเจ็กต์ การเข้าถึงตัวแปรแบบคงที่ในลักษณะเดียวกัน - ผ่านตัวดำเนินการจุดตามหลังชื่อคลาส นี่คือวิธีที่ Java นำเมธอดและตัวแปรโกลบอลเวอร์ชันที่ได้รับการจัดการไปใช้

ลองยกตัวอย่าง ภายในเมธอด main() เมธอดสแตติก callme() และตัวแปรสแตติก b เข้าถึงได้โดยชื่อคลาส StaticDemo

คลาส StaticDemo (
int แบบคงที่ = 42;
int คงที่ b = 99;
callme เป็นโมฆะคงที่ () (
System.out.println("a = " + a);
}
}
คลาส StaticByName(
โมฆะคงสาธารณะหลัก (String args) (
StaticDemo.callme();
System.out.println("b = " + StaticDemo.b);
}
}

ผลลัพธ์ของโปรแกรมนี้จะเป็นดังนี้

9 คำตอบ

Java มีคลาสที่ซ้อนกันแบบคงที่ แต่ดูเหมือนว่าคุณกำลังมองหาคลาสแบบคงที่ ระดับบนสุด- Java ไม่มีวิธีสร้างคลาสระดับบนสุดแบบคงที่ แต่คุณสามารถจำลองคลาสแบบคงที่ได้ดังนี้:

  • ประกาศชั้นเรียนของคุณเป็นครั้งสุดท้าย - ป้องกันการขยายชั้นเรียนเนื่องจากการขยายคลาสแบบคงที่นั้นไม่สมเหตุสมผล
  • ทำให้คอนสตรัคเตอร์เป็นแบบส่วนตัว - ป้องกันการสร้างอินสแตนซ์ด้วยโค้ดไคลเอ็นต์ เนื่องจากไม่มีประโยชน์ในการสร้างคลาสแบบคงที่
  • สร้าง ทั้งหมดองค์ประกอบและฟังก์ชันของคลาสสแตติก เนื่องจากคลาสไม่สามารถสร้างอินสแตนซ์ได้ จึงไม่สามารถเรียกใช้วิธีการอินสแตนซ์หรือสามารถเข้าถึงฟิลด์อินสแตนซ์ได้
  • โปรดทราบว่าคอมไพเลอร์จะไม่ป้องกันคุณจากการประกาศอินสแตนซ์ (ไม่คงที่) ปัญหาจะปรากฏขึ้นเฉพาะเมื่อคุณพยายามโทรหาสมาชิกของอินสแตนซ์เท่านั้น

ตัวอย่างง่ายๆ จากประโยคข้างต้น:

คลาสสาธารณะ TestMyStaticClass ( โมฆะสาธารณะคงที่ main (Args สตริง) ( MyStaticClass.setMyStaticMember (5); System.out.println ("ค่าคงที่: " + MyStaticClass.getMyStaticMember()); System.out.println ("ค่ากำลังสอง: " + MyStaticClass.squareMyStaticMember()); // MyStaticClass x = new MyStaticClass(); // ส่งผลให้เกิดข้อผิดพลาดเวลาคอมไพล์ ) ) // A ระดับบนสุด คลาสจาวาการเลียนแบบพฤติกรรมคลาสคงที่ คลาสสุดท้ายสาธารณะ MyStaticClass (ส่วนตัว MyStaticClass () ( // ตัวสร้างส่วนตัว myStaticMember = 1; ) ส่วนตัวคงที่ int myStaticMember; โมฆะสาธารณะคงที่ setMyStaticMember(int val) ( myStaticMember = val; ) สาธารณะคงที่ int getMyStaticMember() ( กลับ myStaticMember; ) สาธารณะ int squareMyStaticMember() ( ส่งคืน myStaticMember * myStaticMember; ) )

มีอะไรดีเกี่ยวกับคลาสแบบคงที่? ใช้งานได้ดีคลาสแบบคงที่คือการกำหนดคลาสที่ใช้แล้วทิ้ง ยูทิลิตี้ และ/หรือไลบรารีที่การสร้างอินสแตนซ์ไม่สมเหตุสมผล ตัวอย่างที่ดีก็คือ ชั้นเรียนคณิตศาสตร์ซึ่งมีค่าคงที่ทางคณิตศาสตร์บางอย่าง เช่น PI และ E และระบุเพียงค่าเดียว การคำนวณทางคณิตศาสตร์- การจำเป็นต้องมีการสร้างอินสแตนซ์ในกรณีเช่นนี้จะไม่จำเป็นและน่าสับสน ดูชั้นเรียนคณิตศาสตร์ Java โปรดทราบว่าถือเป็นที่สิ้นสุดและสมาชิกทั้งหมดจะคงที่ หาก Java อนุญาตให้คลาสระดับบนสุดถูกประกาศแบบคงที่ ดังนั้นคลาส Math จะเป็นแบบคงที่อย่างแน่นอน

Java มี "คลาสที่ซ้อนกันแบบคงที่" แต่คลาสเหล่านั้นไม่เหมือนกับคลาสแบบคงที่ของ C# เลยหากนั่นคือสิ่งที่คุณมา คลาสที่ซ้อนกันแบบสแตติกเป็นเพียงคลาสที่ไม่ได้หมายความถึงการอ้างอิงถึงอินสแตนซ์ของคลาสภายนอก

คลาสที่ซ้อนกันแบบคงที่สามารถมีวิธีการเช่นและวิธีการคงที่

ไม่มีสิ่งที่เรียกว่าคลาสคงที่ระดับบนสุดใน Java

ใช่ มีคลาสที่ซ้อนกันแบบคงที่ใน java เมื่อคุณประกาศคลาสที่ซ้อนกันแบบสแตติก มันจะกลายเป็นคลาสในสิทธิ์ของตัวเองโดยอัตโนมัติซึ่งสามารถสร้างอินสแตนซ์ได้โดยไม่ต้องสร้างอินสแตนซ์ให้กับคลาสภายนอกที่เป็นของคลาสนั้น

ตัวอย่าง:

คลาสสาธารณะ A (คลาสคงที่สาธารณะ B ())

เนื่องจากคลาส B ถูกประกาศให้เป็นแบบคงที่ คุณจึงสามารถยกตัวอย่างได้อย่างชัดเจนดังนี้:

B b = ใหม่ B();

โปรดทราบว่าหากคลาส B ไม่ได้ถูกประกาศให้คงที่เพื่อให้เป็นแบบสแตนด์อโลน การเรียกอ็อบเจ็กต์อินสแตนซ์จะมีลักษณะดังนี้:

A a= ใหม่ A(); B b = a.ใหม่ B();

จะเกิดอะไรขึ้นเมื่อสมาชิกในคลาสถูกประกาศว่าเป็นแบบคงที่..? องค์ประกอบเหล่านี้สามารถเข้าถึงได้โดยไม่ต้องสร้างอินสแตนซ์ของคลาส ดังนั้นการทำให้คลาสภายนอก (คลาสระดับบนสุด) คงที่จึงไม่สมเหตุสมผล ดังนั้นจึงไม่ได้รับอนุญาต

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

คลาสสาธารณะ A (คลาสคงที่สาธารณะ B ())

ในตอนนี้ ในคลาส C อื่น คุณสามารถเข้าถึงคลาส B ได้โดยไม่ต้องสร้างอินสแตนซ์ของคลาส A

คลาสสาธารณะ C ( A.B ab = ใหม่ A.B(); )

คลาสแบบสแตติกสามารถมีสมาชิกที่ไม่คงที่ได้ เฉพาะคลาสเท่านั้นที่จะคงที่

แต่ถ้าคีย์เวิร์ดแบบสแตติกถูกลบออกจากคลาส B จะไม่สามารถเข้าถึงได้โดยตรงโดยไม่ต้องสร้างอินสแตนซ์ของ A

คลาสสาธารณะ C ( A a = new A(); A.B ab = a. new B(); )

แต่เราไม่สามารถมีสมาชิกแบบคงที่ภายในคลาสภายในที่ไม่คงที่ได้

มองเห็นว่ามันคืออะไร ผลลัพธ์ที่ดีที่สุด Google สำหรับ "java static class" และไม่มีคำตอบที่ดีกว่านี้ ฉันคิดว่าฉันจะเพิ่มมัน ฉันตีความคำถามของ OP เกี่ยวกับคลาสคงที่ใน C # ซึ่งเรียกว่า singletons in โลกจาวา- สำหรับผู้ที่ไม่ทราบ ใน C# คีย์เวิร์ด "static" สามารถนำไปใช้กับการประกาศคลาสได้ ซึ่งหมายความว่าคลาสผลลัพธ์จะไม่สามารถสร้างอินสแตนซ์ได้

ข้อความที่ตัดตอนมาจาก "Effective Java - Second Edition" โดย Joshua Bloch (เป็นที่รู้จักกันอย่างแพร่หลายว่าเป็นหนึ่งใน คำแนะนำที่ดีที่สุดในรูปแบบ Java):

ในเวอร์ชัน 1.5 มีแนวทางที่สามในการใช้งานซิงเกิลตัน เพียงแนะนำประเภท enum ที่มีองค์ประกอบเดียว:

// Enum singleton - วิธีที่ต้องการ public enum Elvis ( INSTANCE; public void leaveTheBuilding() ( ... ) )

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

ตัวดัดแปลงแบบคงที่ใน Java เกี่ยวข้องโดยตรงกับคลาส หากฟิลด์เป็นแบบคงที่แสดงว่าเป็นของคลาส หากวิธีการเป็นแบบคงที่ในทำนองเดียวกันก็จะเป็นของคลาส จากนี้ คุณสามารถเข้าถึงวิธีการหรือฟิลด์แบบคงที่โดยใช้ชื่อคลาสได้ ตัวอย่างเช่น หากฟิลด์การนับเป็นแบบคงที่ในคลาส Counter คุณจะสามารถเข้าถึงตัวแปรได้ด้วยการสืบค้นเช่น: Counter.count แน่นอนว่าควรคำนึงถึงตัวแก้ไขการเข้าถึงด้วย ตัวอย่างเช่น ฟิลด์ส่วนตัวจะใช้ได้เฉพาะภายในคลาสที่ประกาศไว้เท่านั้น ฟิลด์ที่มีการป้องกันพร้อมใช้งานสำหรับทุกคลาสภายในแพ็คเกจ ( บรรจุุภัณฑ์) รวมถึงคลาสสืบทอดทั้งหมดที่อยู่นอกแพ็คเกจ สำหรับข้อมูลเพิ่มเติม ข้อมูลรายละเอียดอ่านบทความ “เอกชน vs ได้รับการคุ้มครอง vs สาธารณะ” สมมติว่ามีการเพิ่มเมธอดแบบคงที่ () ในคลาส Counter ซึ่งมีหน้าที่เพิ่มจำนวนตัวนับ เพื่อโทร วิธีนี้คุณสามารถใช้การโทรเช่น Counter.increation() ไม่จำเป็นต้องสร้างอินสแตนซ์คลาส Counter เพื่อเข้าถึงฟิลด์หรือเมธอดแบบคงที่ นี่คือความแตกต่างพื้นฐานระหว่างวัตถุแบบคงที่และแบบไม่คงที่ (สมาชิกของคลาส) หมายเหตุสำคัญ โปรดจำไว้ว่าสมาชิกคลาสแบบคงที่เป็นของคลาสโดยตรง ไม่ใช่ของอินสแตนซ์ นั่นคือ ค่าของการนับตัวแปรคงที่จะเหมือนกันสำหรับออบเจ็กต์ทั้งหมดของประเภทตัวนับ ในบทความนี้ เราจะดูแง่มุมพื้นฐานของการใช้ตัวแก้ไขแบบคงที่ใน Java รวมถึงคุณสมบัติบางอย่างที่จะช่วยให้คุณเข้าใจแนวคิดการเขียนโปรแกรมหลัก

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

ในส่วนนี้ เราจะดูพื้นฐานของการใช้เมธอด ฟิลด์ และคลาสแบบคงที่ เริ่มจากตัวแปรกันก่อน

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

    เคาน์เตอร์คลาสสาธารณะ (จำนวน int ส่วนตัว; โมฆะสาธารณะหลัก (String args) ( System. out.println (นับ) ; // ข้อผิดพลาดเวลาคอมไพล์))

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

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

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

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

    คลาสยานพาหนะ ( โมฆะสาธารณะ kmToMiles (int km) ( System. out. println ( "ภายในคลาสพาเรนต์/วิธีคงที่"- ) ) ระดับรถขยายยานพาหนะ ( public static void kmToMiles (int km) ( System. out. println ( "ภายในคลาสลูก/วิธีคงที่"- ) ) การสาธิตคลาสสาธารณะ ( โมฆะสาธารณะหลัก ( String args ) ( ยานพาหนะ v = รถใหม่ () ; v. kmToMiles ( 10 ) ; ) )

    เอาต์พุตคอนโซล:

    ภายในคลาสพาเรนต์/เมธอดแบบคงที่

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

    คุณยังสามารถประกาศคลาสแบบคงที่ได้ ยกเว้นคลาสระดับบนสุด คลาสดังกล่าวเรียกว่าคลาสสแตติกแบบซ้อน มีประโยชน์สำหรับการแสดงการเชื่อมต่อที่ได้รับการปรับปรุง ตัวอย่างที่สำคัญของคลาสสแตติกที่ซ้อนกันคือ HashMap.Entry ซึ่งจัดเตรียมโครงสร้างข้อมูลภายใน HashMap เป็นที่น่าสังเกตว่าเช่นเดียวกับคลาสภายในอื่น ๆ คลาสที่ซ้อนกันจะอยู่ในไฟล์ .class แยกกัน ดังนั้นหากคุณประกาศคลาสที่ซ้อนกันห้าคลาสในคลาสหลักของคุณ คุณจะมี 6 ไฟล์ที่มีนามสกุล .class อีกตัวอย่างการใช้งานคือการประกาศ Comparator ของคุณเอง เช่น AgeComparator ในคลาส Employee

    ตัวแก้ไขแบบคงที่สามารถประกาศได้ในบล็อกแบบคงที่หรือที่รู้จักกันดีในชื่อบล็อกตัวเริ่มต้นแบบคงที่ซึ่งจะถูกดำเนินการเมื่อมีการโหลดคลาส หากคุณไม่ประกาศบล็อกดังกล่าว Java จะรวบรวมฟิลด์คงที่ทั้งหมดไว้ในรายการเดียวและดำเนินการเมื่อมีการโหลดคลาส อย่างไรก็ตาม บล็อกแบบคงที่ไม่สามารถโยนข้อยกเว้นที่จับได้ แต่สามารถโยนข้อยกเว้นที่ไม่ถูกตรวจจับได้ ในกรณีนี้ "ข้อผิดพลาดตัวเริ่มต้นข้อยกเว้น" จะเกิดขึ้น ในทางปฏิบัติ ข้อยกเว้นใดๆ ที่เกิดขึ้นระหว่างการดำเนินการและการเริ่มต้นของฟิลด์คงที่จะรวมอยู่ในข้อผิดพลาดนี้โดย Java นี่เป็นสาเหตุที่พบบ่อยที่สุดของ “ข้อผิดพลาด No Class Def Found” เนื่องจาก... ชั้นเรียนไม่อยู่ในหน่วยความจำเมื่อมีการเข้าถึง

    การทราบว่าวิธีการแบบสแตติกถูกผูกไว้ ณ เวลาคอมไพล์นั้นมีประโยชน์ ตรงข้ามกับการผูกวิธีเสมือนหรือแบบไม่คงที่ซึ่งถูกผูกไว้ตอนรันไทม์บนออบเจ็กต์จริง ดังนั้นจึงไม่สามารถแทนที่วิธีการแบบคงที่ใน Java ได้เนื่องจาก ความหลากหลายแบบรันไทม์ใช้ไม่ได้กับสิ่งเหล่านี้ นี่เป็นข้อจำกัดที่สำคัญที่ต้องพิจารณาเมื่อประกาศวิธีการแบบคงที่ สิ่งนี้สมเหตุสมผลเฉพาะเมื่อไม่มีความเป็นไปได้หรือจำเป็นต้องแทนที่วิธีการดังกล่าวโดยคลาสที่สืบทอด วิธีการจากโรงงานและวิธีการอรรถประโยชน์เป็นตัวอย่างที่ดีของการใช้ตัวดัดแปลงแบบคงที่ Joshua Bloch ได้สรุปข้อดีหลายประการของการใช้วิธีการแบบโรงงานแบบคงที่เหนือตัวสร้างในหนังสือของเขาที่มีประสิทธิผล Java ซึ่งโปรแกรมเมอร์ทุกคนของภาษาจำเป็นต้องอ่าน

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

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

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

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

อัปเดตครั้งล่าสุด: 04/19/2018

ยกเว้น วิธีการทั่วไปและฟิลด์ คลาสสามารถมีฟิลด์คงที่ วิธีการ ค่าคงที่ และตัวเริ่มต้นได้ ตัวอย่างเช่น คลาสหลักของโปรแกรมมีเมธอด main ซึ่งเป็นสแตติก:

โมฆะสาธารณะคงหลัก (String args) ()

ในการประกาศตัวแปรคงที่ ค่าคงที่ วิธีการ และตัวเริ่มต้น ให้ใช้คีย์เวิร์ดคงที่ก่อนที่จะประกาศ

สนามคงที่

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

ตัวอย่างเช่น เรามาสร้างตัวแปรคงที่กันดีกว่า:

โปรแกรมคลาสสาธารณะ ( public static void main(String args) ( Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 1 bob.displayId(); // Id = 2 System.out.println (Person.counter); // 3 // เปลี่ยน Person.counter Person.counter = 8; Person sam = บุคคลใหม่ (); // Id = 8 ) คลาส Person (int id ส่วนตัว; int คงที่ counter=1; Person())( id = counter++; ) โมฆะสาธารณะ displayId())( System.out.printf("Id: %d \n", id); ) )

คลาส Person มีตัวนับตัวแปรคงที่ ซึ่งเพิ่มขึ้นในตัวสร้างและค่าของมันจะถูกกำหนดให้กับตัวแปร id นั่นคือ เมื่อสร้างออบเจ็กต์ Person ใหม่แต่ละรายการ ตัวแปรนี้จะเพิ่มขึ้น ดังนั้นแต่ละออบเจ็กต์ Person ใหม่จะมีค่าฟิลด์ id ที่มากกว่าค่าก่อนหน้า 1

เนื่องจากตัวแปรตัวนับเป็นแบบคงที่ เราจึงสามารถอ้างถึงตัวแปรในโปรแกรมตามชื่อคลาส:

System.out.println(บุคคล.เคาน์เตอร์); // รับค่า Person.counter = 8; // เปลี่ยนค่า

เอาต์พุตคอนโซลของโปรแกรม:

รหัส = 1 รหัส = 2 3 รหัส = 8

ค่าคงที่แบบคงที่

คงที่ยังเป็นค่าคงที่ทั่วไปสำหรับทั้งชั้นเรียน

โปรแกรมคลาสสาธารณะ ( โมฆะสาธารณะคงที่ main (String args) ( รัศมีสองเท่า = 60; System.out.printf ("Radisu: %f \n", รัศมี); // 60 System.out.printf ("Area: %f \n", Math.PI * radius); // 188.4 ) ) คลาส Math( public สุดท้ายแบบคงที่ดับเบิลพีไอ = 3.14; -

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

System.out.println("สวัสดี");

out เพียงแสดงถึงค่าคงที่คงที่ของคลาส System ดังนั้นจึงสามารถเข้าถึงได้โดยไม่ต้องสร้างอ็อบเจ็กต์ของคลาส System

ตัวเริ่มต้นแบบคงที่

ตัวเริ่มต้นแบบคงที่ได้รับการออกแบบมาเพื่อเริ่มต้นตัวแปรแบบคงที่หรือเพื่อดำเนินการที่เกิดขึ้นเมื่อสร้างวัตถุแรกสุด ตัวอย่างเช่น ลองกำหนดตัวเริ่มต้นแบบคงที่:

โปรแกรมคลาสสาธารณะ ( public static void main(String args) ( Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 105 bob.displayId(); // Id = 106 ) ) คลาสบุคคล (int id ส่วนตัว; เคาน์เตอร์ int แบบคงที่; คงที่ (เคาน์เตอร์ = 105; System.out.println ("ตัวเริ่มต้นแบบคงที่"); ) บุคคล ()) ( id = เคาน์เตอร์ ++; System.out.println ("ตัวสร้าง " ); ) โมฆะสาธารณะ displayId())( System.out.printf("Id: %d \n", id); ) )

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

ในโปรแกรมเอง สองอ็อบเจ็กต์ของคลาส Person จะถูกสร้างขึ้น ดังนั้นเอาต์พุตคอนโซลจะมีลักษณะดังนี้:

ตัวสร้างเริ่มต้นแบบคงที่ รหัสตัวสร้างตัวสร้าง: 105 Id: 106

ควรพิจารณาว่าตัวเริ่มต้นแบบคงที่จะถูกเรียกก่อนที่จะสร้างอ็อบเจ็กต์คลาสแรกเท่านั้น

วิธีการคงที่

วิธีการแบบคงที่ยังใช้กับทั้งชั้นเรียนโดยรวมด้วย ตัวอย่างเช่น ในตัวอย่างข้างต้น ตัวนับตัวแปรคงที่สามารถเข้าถึงได้จากภายนอก และเราสามารถเปลี่ยนค่าของมันนอกคลาส Person ได้ มาทำให้ไม่สามารถเปลี่ยนแปลงจากภายนอกได้ แต่สามารถเข้าถึงได้เพื่อการอ่าน ในการทำเช่นนี้เราใช้วิธีคงที่:

โปรแกรมคลาสสาธารณะ ( public static void main(String args) ( Person.displayCounter(); // Counter: 1 Person tom = new Person(); Person bob = new Person(); Person.displayCounter(); // Counter: 3 ) ) คลาส Person( private int id; private static int counter = 1; Person())( id = counter++; ) // static method public static void displayCounter())( System.out.printf("Counter: %d \n ", ตัวนับ); ) โมฆะสาธารณะ displayId())( System.out.printf("Id: %d \n", id); ) )

ขณะนี้ไม่สามารถเข้าถึงตัวแปรคงที่จากภายนอกได้ แต่เป็นตัวแปรส่วนตัว และค่าของมันจะแสดงโดยใช้วิธี static displayCounter หากต้องการเรียกเมธอดแบบสแตติก ให้ใช้ชื่อคลาส: Person.displayCounter()

เมื่อใช้วิธีการคงที่ เราต้องคำนึงถึงข้อจำกัด: ในวิธีคงที่ เราสามารถเรียกเฉพาะวิธีคงที่อื่น ๆ และใช้เฉพาะตัวแปรคงที่เท่านั้น

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

โปรแกรมคลาสสาธารณะ ( โมฆะสาธารณะคงที่ main (String args) ( System.out.println (Operation.sum (45, 23)); // 68 System.out.println (Operation.subtract (45, 23)); // 22 System.out.println (Operation.multiply (4, 23)); // 92 ) การดำเนินการคลาส ( ผลรวม int แบบคงที่ (int x, int y) ( return x + y; ) ลบ int แบบคงที่ (int x, int y )( return x - y; ) คูณ int แบบคงที่(int x, int y)( return x * y; ) )

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

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

นอกจากชื่อและคำอธิบายที่กล่าวข้างต้นแล้ว วิธีการนี้ยังมีคุณลักษณะอื่นๆ อีกหลายประการ ได้แก่

  1. ชุดของตัวดัดแปลง
  2. ประเภทค่าส่งคืน
  3. ชุดของอาร์กิวเมนต์ (พารามิเตอร์)

ตัวดัดแปลงวิธีการ

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

ตัวแก้ไขสาธารณะมีหน้าที่รับผิดชอบระดับการเข้าถึงวิธีการที่อธิบายไว้ แทนที่จะเป็นแบบสาธารณะ คุณสามารถระบุระดับการเข้าถึงแบบส่วนตัวหรือการป้องกันได้ หรือไม่ระบุอะไรเลย ซึ่งในกรณีนี้จะใช้ระดับการเข้าถึงเริ่มต้น

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

วิธีการหลักต้องมีระดับ การเข้าถึงสาธารณะอย่างแน่นอนเพราะมันเข้าถึงได้โดยเสมือน เครื่องจาวาไม่ใช่ส่วนหนึ่งของแพ็คเกจใดๆ

นอกจากนี้ยังมีตัวแก้ไขอื่นๆ ที่ช่วยให้คุณควบคุมการทำงานของวิธีการต่างๆ ในระหว่างการคำนวณแบบขนาน (แบบหลายเธรด) ได้

ประเภทการส่งคืน

วิธีการใน Java สามารถแบ่งออกเป็นสองกลุ่ม: ฟังก์ชั่นและขั้นตอน กลุ่มแรกประกอบด้วยวิธีการที่คล้ายกับฟังก์ชันในแง่คณิตศาสตร์มาก จากการทำงานวิธีการดังกล่าวกลับไปยังตำแหน่งในโปรแกรมที่เรียกว่าผลลัพธ์เฉพาะของประเภทที่มีอยู่นั่นคืออาจเป็นจำนวนเต็มหรือ จำนวนจริงหรือค่าตรรกะ (int, double, boolean), อาร์เรย์ (อ้างอิงถึงมัน), อ็อบเจ็กต์ (อ้างอิงถึงมัน) ค่าส่งคืนจะต้องถูกกำหนดให้กับตัวแปรประเภทที่เหมาะสมหรือส่งผ่านไปยังวิธีอื่นเป็นอาร์กิวเมนต์

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

ดับเบิล r = Math.random(); /* Random หมายถึงฟังก์ชันต่างๆ */ System.out.println(r); /* println หมายถึงขั้นตอนการทำงาน */

หากเราสร้างวิธีการที่จะพิมพ์ข้อความลงบนหน้าจอเช่นเดียวกับ println แต่ในขณะเดียวกันก็นับจำนวนช่องว่างในข้อความและส่งกลับผลลัพธ์นี้ เราจะได้ฟังก์ชัน ในกรณีนี้ ฟังก์ชันจะยังคงดำเนินการที่เป็นประโยชน์ตามลักษณะของขั้นตอน println ดังนั้นฟังก์ชันจึงเป็นสากลมากกว่าโพรซีเดอร์ แต่ก็ไม่จำเป็นเสมอไป

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

หลังโมดิฟายเออร์ แต่ยังอยู่ทางด้านซ้ายของชื่อเมธอดด้วย ประเภทของค่าที่ส่งคืนจะถูกระบุ (หากเมธอดเป็นฟังก์ชัน เช่น int หรือ double) หรือคำว่า void (หากเมธอดนั้นเป็นโพรซีเดอร์) .

ถ้าเมธอดเป็นฟังก์ชัน จะต้องมีคำสั่ง return หลังจากนั้นจึงคั่นด้วยช่องว่าง ซึ่งเป็นนิพจน์ที่ควรส่งคืนตามผลลัพธ์ของเมธอด

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

อาร์กิวเมนต์ (พารามิเตอร์)

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

จากนั้นเมื่อเรียกใช้เมธอดจะสามารถระบุชุดค่าที่สอดคล้องกับประเภทที่อธิบายโดยอาร์กิวเมนต์ได้

ค่าที่ส่งผ่านไปยังเมธอด ณ เวลาที่โทรเรียกว่าพารามิเตอร์จริง และชื่อของอาร์กิวเมนต์ที่ปรากฏในคำอธิบายวิธีการเรียกว่าพารามิเตอร์ที่เป็นทางการ

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

โดยเฉพาะซึ่งหมายความว่าโดยการส่งผ่านตัวแปรใดๆ ประเภทพื้นฐานเนื่องจากเป็นพารามิเตอร์ของเมธอดเมื่อถูกเรียก เราจะไม่สามารถเปลี่ยนค่าของตัวแปรนี้ได้ โปรแกรมหลัก- ถ้าวัตถุหรืออาร์เรย์ใดถูกส่งผ่านไปยังวิธีการผ่านทางอาร์กิวเมนต์ เฉพาะการอ้างอิงไปยังวัตถุหรืออาร์เรย์ (เช่น ที่อยู่ในหน่วยความจำ) เท่านั้นที่จะถูกคัดลอกภายในวิธีการ การกระทำที่เราทำกับอาเรย์หรืออ็อบเจ็กต์ภายในเมธอดจะส่งผลต่อสถานะของอาเรย์หรืออ็อบเจ็กต์นี้ในโปรแกรมหลัก แม้ว่าเมธอดจะทำงานเสร็จแล้วก็ตาม ภายในวิธีการนี้ เราเข้าถึงที่อยู่เดียวกันและทำงานกับข้อมูลเดียวกันในหน่วยความจำที่มีอยู่ในโปรแกรมหลัก

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

คำอธิบายของวิธีการ

วิธีการจะต้องอธิบายภายในคลาส แต่วิธีหนึ่งไม่ได้อธิบายไว้ภายในอีกวิธีหนึ่ง นั่นคือ วิธีการนั้นจะต้องซ้อนอยู่ในคลาสบล็อกโดยตรง

รูปแบบทั่วไปสำหรับการอธิบายวิธีการ:

ตัวดัดแปลง return_value_type method_name (อาร์กิวเมนต์ที่เป็นทางการ) ( // การกระทำที่ดำเนินการโดยเมธอด // อาจเป็นไปได้ return )

ตามธรรมเนียม ชื่อวิธีการจะต้องขึ้นต้นด้วยตัวอักษรตัวเล็ก หากประกอบด้วยคำหลายคำ แต่ละคำต่อมาจะขึ้นต้นด้วย อักษรตัวใหญ่- มีการเลือกชื่อของวิธีการเพื่อให้ชัดเจนว่ามันทำอะไร

ลองดูตัวอย่างบางส่วน:

สาธารณะคง kvadk คู่ (สองเท่า) ( double t; t = Math.pow(a, 0.5); return t; )

ตอนนี้อยู่ในวิธีการหลักแล้ว เราก็สามารถใช้วิธีการของเราได้ ตัวอย่างเช่นเช่นนี้:

Int = 25; System.out.println(kvadk(a)); // 5.0 System.out.println(a) // 25

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

วิธีการโอเวอร์โหลด

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

โมฆะ pr(double a) ( System.out.println(a); ) โมฆะ pr (สตริง a) ( System.out.println(a); ) โมฆะ pr(int a) ( for (int i=0; i

ตัวอย่างการใช้วิธี

อินท์เอ = 5; int m = (1, 2, 8, 3) String s = "โลก"; pr (a) // วิธีดั้งเดิมใช้งานได้ pr (a+s); // World 5 โอเวอร์โหลดครั้งแรกกำลังทำงานอยู่ pr (m); // 1 2 8 3 ราคา (ม+ก); // ข้อผิดพลาด

ตัวแปร a ไม่ใช่ประเภท double แต่ถูกประมวลผลโดยวิธีดั้งเดิม เนื่องจากสามารถส่งอัตโนมัติจาก int เป็น double ได้ มันเป็นไปไม่ได้ในทิศทางตรงกันข้าม ถ้าเมธอดมีอาร์กิวเมนต์ประเภท int ก็จะไม่สามารถแสดงจำนวนจริงได้

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

Polymorphism: ชื่อเดียว หลายรูปแบบ

ตัวอย่างการใช้วิธีต่างๆ

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

นำเข้า java.util.Scanner; คลาสสาธารณะหลัก ( บูลีนคงที่สาธารณะ isPrime (int n) ( สำหรับ (int i = 2; i<= Math.sqrt(n) ; i++) { if(n%i == 0) { return false; } } return true; } public static void main(String args) { Scanner sc = new Scanner(System.in); System.out.print("Введите натуральное число: "); if(sc.hasNextInt()) { int u = sc.nextInt(); if(u >0) ( if(isPrime(u)) ( System.out.println("You have enter a prime number"); ) else ( System.out.print("ปัจจัยเฉพาะของตัวเลข: "); for(int i = (int) Math.sqrt(u); i >= 2 ; ) ( if(u%i == 0 && isPrime(i)) ( System.out.print(i+" "); ) ) .out.println (); ) ) else ( System.out.println("คุณไม่ได้ป้อนจำนวนบวก"); ) ) else ( System.out.println("คุณไม่ได้ป้อนจำนวนเต็ม"); ) ) )

ในตัวอย่างต่อไปนี้ จะมีการสร้างวิธีการชื่อเดียวกันหลายวิธีเนื่องจากการโอเวอร์โหลด

เวอร์ชันแรกของเมธอดจะแปลสตริงง่ายๆ กล่าวคือ จริงๆ แล้วมันจะเป็นคำพ้องความหมายที่สั้นกว่าสำหรับเมธอด System.out.println() ในตัว ตัวเลือกนี้จะไม่มีพารามิเตอร์

ตัวแปรที่สองของเมธอด (โอเวอร์โหลดครั้งแรก) ตรวจสอบว่าอาร์กิวเมนต์ตัวเลขมีหรือไม่ เศษส่วนหากไม่มีอยู่ อาร์กิวเมนต์จะถูกแปลงเป็นจำนวนเต็มและแสดงบนหน้าจอโดยไม่มีส่วนที่เป็นเศษส่วนเป็นศูนย์ (3 แทนที่จะเป็น 3.0) วิธีการนี้จะสามารถผ่านได้ไม่เพียงเท่านั้น ตัวแปรประเภท double แต่ยังรวมถึงตัวแปรประเภทอื่นๆ ที่สามารถแปลงเป็นสองเท่าโดยอัตโนมัติได้ (เช่น ตัวแปรจำนวนเต็มใดๆ)

วิธีที่สามที่มีพารามิเตอร์ตัวเดียวเพียงเรียกวิธีที่สี่ โดยส่งผ่านอาร์เรย์ผลลัพธ์เป็นพารามิเตอร์ และเว้นวรรคเป็นพารามิเตอร์ตัวที่สอง โปรดทราบว่าเรากำลังเรียกวิธีการที่จะอธิบายในภายหลังในโปรแกรม ซึ่งเป็นที่ยอมรับโดยสมบูรณ์

วิธีที่สี่ส่งออกอาร์เรย์ตัวเลข โดยประมวลผลแต่ละองค์ประกอบแล้ว วิธีการที่มีอยู่- หลังจากที่แต่ละองค์ประกอบแสดงขึ้น ตัวคั่นที่ส่งผ่านในพารามิเตอร์จะถูกเพิ่ม

คลาสสาธารณะ Main ( public static void pr() ( System.out.println(); ) public static void pr(double d) ( if((int)d == d) ( System.out.print((int)d) ) อื่น ๆ ( System.out.print(d); ) ) โมฆะสาธารณะคงที่ pr (double m) ( pr (m, " "); ) โมฆะสาธารณะคงที่ pr (double m, String s) ( สำหรับ (int i = 0;< m.length; i++) { pr(m[i]); System.out.print(s); } } public static void main(String args) { double arrn = {1, 2.71, 3.14, 15, -5, 92, 0.5}; double p = 3.0; int k = 13; pr(p); // вывод числа, без дробной части при возможности pr(); // переводит строку pr(arrn); // вывод числового массива в строку pr(); // переводит строку pr(arrn,", "); // вывод числового массива в строку через запятую pr(); // переводит строку pr(k); // вывод целого числа через автоприведение } }

ผลจากการรันโปรแกรม จะแสดงผลดังนี้:

3 1 2.71 3.14 15 -5 92 0.5 1, 2.71, 3.14, 15, -5, 92, 0.5, 1

งาน

  1. สร้างวิธีการคงที่ที่จะมีพารามิเตอร์จำนวนเต็มสองตัว a และ b และส่งกลับจำนวนเต็มสุ่มจากเซ็กเมนต์เป็นค่าของมัน ใช้วิธีการนี้กรอกอาร์เรย์จำนวนเต็ม 20 จำนวนแล้วแสดงบนหน้าจอ
  2. สร้างวิธีการที่จะแสดงอาร์เรย์ที่ระบุบนหน้าจอเป็นสตริง โดยใช้วิธีการที่สร้างขึ้นและวิธีการจากงานก่อนหน้า เติม 5 อาร์เรย์ โดยแต่ละองค์ประกอบมี 10 องค์ประกอบ ตัวเลขสุ่มและแสดงทั้ง 5 อาร์เรย์บนหน้าจอ โดยแต่ละอาร์เรย์แยกบรรทัดกัน
  3. สร้างวิธีการที่จะเรียงลำดับอาร์เรย์ที่ระบุตามลำดับจากน้อยไปหามากในแบบที่คุณทราบ
  4. อาร์เรย์จัดเก็บสตริงข้อความที่ระบุอย่างชัดเจน 7 รายการ เขียนโปรแกรมที่จะเรียงลำดับและแสดงสตริงตามลำดับตัวอักษร ตัวอย่างเช่น หากได้รับบรรทัดต่อไปนี้:
Pushkin Lermontov Nekrasov Tolstoy L. N. Tolstoy A. N. Yesenin Paustovsky

โปรแกรมควรแสดง:

Yesenin Lermontov Nekrasov Paustovsky Pushkin Tolstoy A. N. Tolstoy L. N.

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

การเรียกซ้ำ

การเรียกซ้ำเป็นวิธีการ (ฟังก์ชัน) ที่เรียกตัวเองภายในร่างกาย

ลองดูตัวอย่าง - การคำนวณแฟกทอเรียล ในการคำนวณ n! ก็เพียงพอที่จะรู้และคูณ (n-1)! และ n

มาสร้างวิธีการที่ใช้วิธีที่อธิบายไว้กันดีกว่า

ข้อเท็จจริง int แบบคงที่ (int n) ( if (n==1) ( return 1; ) else if (n==2) ( return 2; ) else ( return fact(n-1) * n; ) )

วิธีการที่ระบุจะคำนวณแฟกทอเรียลของจำนวนธรรมชาติ

ลองพิจารณาตัวอย่างที่คำนวณเลขฟีโบนักชีตัวที่ n ผ่านการเรียกซ้ำ

ให้เรานึกถึงองค์ประกอบแรกของซีรีส์นี้ว่ามีลักษณะอย่างไร: 1 1 2 3 5 8 13 ...

int fib แบบคงที่ (int n) ( ถ้า (n==1 || n == 2) ( return 1; ) return fib (n-2) + fib (n-1); )

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

การคำนวณแบบเรียกซ้ำมักส่งผลให้จำเป็นต้องทำซ้ำการกระทำเดิม ซึ่งจะทำให้โปรแกรมช้าลงอย่างมาก

งาน

  1. ค้นหาจากการทดลอง โดยเริ่มจากองค์ประกอบของลำดับฟีโบนัชชี การคำนวณโดยใช้การเรียกซ้ำกลายเป็นสิ่งที่ยอมรับไม่ได้ (ใช้เวลานานกว่าหนึ่งนาที)
  2. สร้างวิธีไฮบริดที่สำหรับ n ขนาดเล็ก จะคำนวณหมายเลขฟีโบนักชีลำดับที่ n โดยใช้การเรียกซ้ำ และสำหรับค่าที่มากกว่าเกณฑ์ n ที่คุณพบในปัญหาก่อนหน้า ให้คำนวณหมายเลขฟีโบนักชีลำดับที่ n โดยใช้อัลกอริธึมวนซ้ำ (ลูปภายในที่ ค่าของสององค์ประกอบก่อนหน้าของลำดับ)
  3. คำนวณกี่ครั้งที่จะต้องคำนวณองค์ประกอบที่สี่ของลำดับฟีโบนัชชีใหม่เพื่อคำนวณองค์ประกอบที่สิบห้า

โทรสแต็ค

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

ลำดับชั้นทั้งหมด (ผู้ที่เรียกใคร) จะถูกจัดเก็บไว้ในพื้นที่หน่วยความจำพิเศษที่เรียกว่า call stack องค์ประกอบจะถูกเพิ่มเข้าไปในส่วนของหน่วยความจำนี้ตามหลักการต่อไปนี้: ต้องดึงองค์ประกอบที่เพิ่มล่าสุดก่อน เมื่อวิธีการได้ผล ปรากฎว่ามีวิธีการอยู่ใต้สแต็ก และวิธีการ หลัก.

ด้วยเหตุนี้ จึงมีความเสี่ยงของการเรียกสแต็กล้นในระหว่างกระบวนการเรียกซ้ำ

มีสิ่งที่เรียกว่าการเรียกซ้ำเชิงซ้อนซึ่งวิธีการดังกล่าว เรียกวิธีการ , สาเหตุ กับ, ก กับสาเหตุ .

2010, Alexei Nikolaevich Kostin กรม TIDM คณะคณิตศาสตร์เอ็มพีจียู.



มีคำถามอะไรไหม?

แจ้งการพิมพ์ผิด

ข้อความที่จะส่งถึงบรรณาธิการของเรา: