เหตุใดคุณจึงไม่สามารถประกาศคลาสเป็นสแตติกใน Java
static
คลาสabstract final
เช่นพวกเขาไม่สามารถยกตัวอย่างและไม่สามารถขยายได้ ซึ่งหมายความว่าพวกเขาสามารถมีสมาชิกแบบคงที่เท่านั้นซึ่งมีประโยชน์สำหรับคลาสที่มีวิธีการช่วยเหลือเท่านั้น
เหตุใดคุณจึงไม่สามารถประกาศคลาสเป็นสแตติกใน Java
static
คลาสabstract final
เช่นพวกเขาไม่สามารถยกตัวอย่างและไม่สามารถขยายได้ ซึ่งหมายความว่าพวกเขาสามารถมีสมาชิกแบบคงที่เท่านั้นซึ่งมีประโยชน์สำหรับคลาสที่มีวิธีการช่วยเหลือเท่านั้น
คำตอบ:
คลาสที่ซ้อนกันเท่านั้นที่สามารถเป็นแบบสแตติกได้ คุณสามารถใช้คลาสที่ซ้อนกันได้โดยไม่ต้องมีอินสแตนซ์ของคลาสภายนอก
class OuterClass{
public static class StaticNestedClass{
}
public class InnerClass{
}
public InnerClass getAnInnerClass(){
return new InnerClass();
}
//This method doesn't work
public static InnerClass getAnInnerClassStatically(){
return new InnerClass();
}
}
class OtherClass{
//Use of a static nested class:
private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();
//Doesn't work
private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
//Use of an inner class:
private OuterClass outerclass= new OuterClass();
private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}
แหล่งข้อมูล:
ในหัวข้อเดียวกัน:
คลาสระดับบนสุดเป็นค่าคงที่โดยค่าเริ่มต้น คลาสภายในไม่คงที่ตามค่าเริ่มต้น คุณสามารถเปลี่ยนค่าเริ่มต้นสำหรับคลาสภายในโดยทำเครื่องหมายสแตติกให้ชัดเจน คลาสระดับบนสุดโดยอาศัยระดับสูงสุดไม่สามารถมีความหมายไม่คงที่ได้เนื่องจากไม่มีคลาสพาเรนต์ที่ต้องอ้างอิง ดังนั้นจึงไม่มีวิธีเปลี่ยนค่าเริ่มต้นสำหรับคลาสระดับบนสุด
static
คำหลักในระดับบนสุดเพื่อแสดงและบังคับใช้ว่าอาจมีเพียงสมาชิกแบบคงที่เท่านั้นและไม่ได้สร้างอินสแตนซ์ ที่อาจ แต่มีคนสับสนในขณะที่static
มีความหมายที่แตกต่างกันสำหรับชั้นเรียนที่ซ้อนกัน
ดังนั้นฉันมางานปาร์ตี้ช้า แต่นี่คือสองเซ็นต์ของฉัน - เพิ่มปรัชญาในคำตอบของ Colin Hebert
ในระดับสูงคำถามของคุณเกี่ยวกับความแตกต่างระหว่างวัตถุและประเภท ในขณะที่มีรถยนต์จำนวนมาก (วัตถุ) มีคลาสรถยนต์เพียงหนึ่งประเภท (ประเภท) การประกาศบางสิ่งบางอย่างในลักษณะสแตติกหมายความว่าคุณกำลังทำงานในพื้นที่ "ประเภท" มีเพียงคนเดียวเท่านั้น คำหลักระดับบนสุดกำหนดประเภทในพื้นที่ "ประเภท" แล้ว ผลที่ตามมาก็คือ "รถคลาสคงที่สาธารณะ" ซ้ำซ้อน
คลาสที่มี Constructor ส่วนตัวเป็นแบบสแตติก
ประกาศคลาสของคุณเช่นนี้:
public class eOAuth {
private eOAuth(){}
public final static int ECodeOauthInvalidGrant = 0x1;
public final static int ECodeOauthUnknown = 0x10;
public static GetSomeStuff(){}
}
และคุณสามารถใช้โดยไม่มีการเริ่มต้น:
if (value == eOAuth.ECodeOauthInvalidGrant)
eOAuth.GetSomeStuff();
...
static class
ประกาศใน C #) คอมไพเลอร์จะไม่ยอมให้โค้ดประกาศตัวแปรประเภทนั้นหรือใช้เป็นพารามิเตอร์ประเภททั่วไป การขาดคอนสตรัคเตอร์ที่สามารถเข้าถึงได้ในชั้นเรียนซึ่งอาจเป็นอินสแตนซ์หรือรับมรดกจะไม่ขัดขวางการประกาศตัวแปรประเภทนั้นหรือใช้เป็นพารามิเตอร์ประเภททั่วไป
แน่นอนว่าพวกเขาทำได้ แต่มีเพียงคลาสซ้อนภายในเท่านั้น นั่นหมายความว่าอินสแตนซ์ของคลาสที่ซ้อนกันไม่ต้องการอินสแตนซ์ที่ล้อมรอบของคลาสภายนอก
แต่สำหรับชั้นเรียนระดับบนสุดนักออกแบบภาษาไม่สามารถคิดถึงสิ่งที่มีประโยชน์เกี่ยวกับคำหลักได้ดังนั้นจึงไม่ได้รับอนุญาต
static
แต่บางครั้งก็สมเหตุสมผล ตัวอย่างเช่นคลาสที่มีเมธอดตัวช่วยคงที่เท่านั้นที่ทำให้เข้าใจได้ง่าย แต่ภาษาจาวาไม่ได้ขัดขวางไม่ให้คุณทำเช่นนั้น คุณสามารถทำให้คลาสที่ไม่สามารถใช้งานได้ทันที (และ 'คงที่' ในทางปฏิบัติ) ไปยังคลาสอื่น ๆ โดยการประกาศตัวสร้างเริ่มต้นprivate
ซึ่งห้ามการสร้างอินสแตนซ์เนื่องจากไม่มีตัวสร้างที่มองเห็นได้
คุณสามารถสร้างคลาสยูทิลิตี้ (ซึ่งไม่สามารถสร้างอินสแตนซ์ได้) โดยการประกาศประเภท enum โดยไม่มีอินสแตนซ์ นั่นคือคุณประกาศอย่างเจาะจงว่าไม่มีกรณีใด ๆ
public enum MyUtilities {;
public static void myMethod();
}
public class Outer {
public static class Inner {}
}
... มันสามารถประกาศคงที่ - ตราบใดที่มันเป็นสมาชิกระดับ
จาก JLS:
คลาสสมาชิกอาจเป็นแบบสแตติกซึ่งในกรณีนี้พวกเขาไม่สามารถเข้าถึงตัวแปรอินสแตนซ์ของคลาสที่ล้อมรอบ หรืออาจเป็นคลาสภายใน (inner8.1.3)
และที่นี่:
คำหลักคงที่อาจแก้ไขการประกาศของสมาชิกประเภท C ภายในร่างกายของชั้นที่ไม่ใช่ด้านใน T ผลกระทบคือการประกาศว่า C ไม่ได้เป็นชั้นใน เช่นเดียวกับวิธีการคงที่ของ T ไม่มีอินสแตนซ์ปัจจุบันของ T ในร่างกายของมัน C ยังไม่มีอินสแตนซ์ปัจจุบันของ T และไม่ได้มีอินสแตนซ์ล้อมรอบคำศัพท์ใด ๆ
คำหลักแบบสแตติกจะไม่สมเหตุสมผลสำหรับคลาสระดับบนสุดเนื่องจากคลาสระดับบนไม่มีประเภทการล้อมรอบ
Inner
? Nested
คงจะเป็นทางเลือกที่สับสนน้อยกว่า
ตามที่อธิบายไว้ข้างต้นคลาสจะไม่คงที่จนกว่าจะเป็นสมาชิกของคลาสอื่น
หากคุณต้องการออกแบบคลาส "ซึ่งไม่สามารถมีได้หลายอินสแตนซ์" คุณอาจต้องการดูในรูปแบบการออกแบบ "ซิงเกิล"
ข้อมูลการเริ่มต้นซิงเกิลที่นี่
ข้อแม้:
หากคุณกำลังคิดที่จะใช้รูปแบบซิงเกิลต่อต้านด้วยพลังทั้งหมดของคุณ มันเป็นหนึ่งใน DesignPattern ที่ง่ายที่สุดที่จะเข้าใจอาจเป็นที่นิยมมากที่สุดและแน่นอนที่สุดในทางที่ผิด (ที่มา: JavaRanch ตามลิงค์ด้านบน)
นอกจากนี้วิธีการที่กำหนด Java เรียนภายในคงมีความหมายของการเรียนแบบคงที่ตามโลก C # อื่น[1] คลาสสแตติกเป็นคลาสที่มีเมธอดสแตติก (ฟังก์ชัน) เท่านั้นและมีไว้เพื่อสนับสนุนการโปรแกรมแบบโพรซีเดอร์ คลาสดังกล่าวไม่ใช่คลาสจริง ๆ ที่ผู้ใช้ของคลาสสนใจเฉพาะฟังก์ชันตัวช่วยเท่านั้นและไม่ได้สร้างอินสแตนซ์ของคลาส แม้ว่าคลาสสแตติกจะได้รับการสนับสนุนใน C # แต่ไม่มีการรองรับโดยตรงใน Java อย่างไรก็ตามคุณสามารถใช้ enums เพื่อเลียนแบบคลาส C # แบบคงที่ใน Java เพื่อให้ผู้ใช้ไม่สามารถสร้างอินสแตนซ์ของคลาสที่กำหนด (แม้จะใช้การสะท้อน) [2] :
public enum StaticClass2 {
// Empty enum trick to avoid instance creation
; // this semi-colon is important
public static boolean isEmpty(final String s) {
return s == null || s.isEmpty();
}
}
ทุกสิ่งที่เราโค้ดในจาวาจะเข้าสู่ชั้นเรียน เมื่อใดก็ตามที่เราเรียกใช้คลาส JVM อินสแตนซ์ของวัตถุ JVM สามารถสร้างวัตถุจำนวนหนึ่งโดยนิยามคงที่หมายความว่าคุณมีสำเนาชุดเดียวกันกับวัตถุทั้งหมด
ดังนั้นถ้าจาวาจะอนุญาตให้คลาสท็อปคงที่เมื่อใดก็ตามที่คุณเรียกใช้โปรแกรมมันจะสร้างออบเจ็กต์ขึ้นมาและไปยังตำแหน่งหน่วยความจำเดียวกัน
หากคุณเป็นเพียงการเปลี่ยนวัตถุทุกครั้งที่คุณเรียกใช้มันคืออะไรจุดของการสร้างมันได้หรือไม่
นั่นคือเหตุผลที่ Java กำจัดสแตติกสำหรับระดับบนสุด
อาจมีเหตุผลที่เป็นรูปธรรมมากขึ้น แต่สิ่งนี้สมเหตุสมผลมากสำหรับฉัน
คลาสเท่านั้นที่สามารถเป็นแบบสแตติกได้ รหัสต่อไปนี้ใช้งานได้ดี:
public class whatever {
static class innerclass {
}
}
จุดของคลาสภายในคงที่คือพวกเขาไม่มีการอ้างอิงไปยังวัตถุชั้นนอก
ฉันคิดว่ามันเป็นไปได้ง่ายเหมือนดื่มกาแฟสักแก้ว! เพียงแค่ดูที่นี้ เราไม่ใช้คำหลักคงที่อย่างชัดเจนในขณะที่การกำหนดชั้นเรียน
public class StaticClass {
static private int me = 3;
public static void printHelloWorld() {
System.out.println("Hello World");
}
public static void main(String[] args) {
StaticClass.printHelloWorld();
System.out.println(StaticClass.me);
}
}
นั่นไม่ใช่คำจำกัดความของคลาสสแตติกหรือไม่? เราแค่ใช้ฟังก์ชั่นที่ถูกผูกไว้กับคลาส ระวังว่าในกรณีนี้เราสามารถใช้คลาสอื่นในที่ซ้อนกันได้ ดูนี่สิ:
class StaticClass1 {
public static int yum = 4;
static void printHowAreYou() {
System.out.println("How are you?");
}
}
public class StaticClass {
static int me = 3;
public static void printHelloWorld() {
System.out.println("Hello World");
StaticClass1.printHowAreYou();
System.out.println(StaticClass1.yum);
}
public static void main(String[] args) {
StaticClass.printHelloWorld();
System.out.println(StaticClass.me);
}
}
new StaticClass()
และนั่นก็ไม่สมเหตุสมผลนัก ด้วย Constructor ส่วนตัวมันจะไม่อนุญาตอินสแตนซ์ของมัน
หนึ่งสามารถดูPlatformUI
ใน Eclipse สำหรับคลาสที่มีวิธีการคงที่และตัวสร้างส่วนตัวด้วยตัวเองเป็นที่สิ้นสุด
public final class <class name>
{
//static constants
//static memebers
}
ถ้าประโยชน์ของการใช้คลาสคงที่ไม่ใช่เพื่อสร้างอินสแตนซ์ของวัตถุและใช้เมธอดดังนั้นให้ประกาศคลาสเป็นสาธารณะและวิธีนี้เป็นแบบคงที่
static
?