เหตุใดฟิลด์ทั้งหมดในอินเทอร์เฟซจึงคงที่โดยปริยายและสุดท้าย


100

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

มีใครรู้บ้างว่าทำไมนักออกแบบ Java ถึงทำฟิลด์ในอินเทอร์เฟซstaticและfinal?


สำหรับหมายเหตุสำหรับตัวฉันเอง: มันคงที่เพราะช่องของอินเทอร์เฟซจะไม่กลายเป็นส่วนหนึ่งของออบเจ็กต์ที่ใช้มัน
ฝนตก

คำตอบ:


127

อินเทอร์เฟซไม่สามารถมีพฤติกรรมหรือสถานะได้เนื่องจากมีจุดประสงค์เพื่อระบุเฉพาะสัญญาการโต้ตอบไม่มีรายละเอียดการใช้งาน 'ไม่มีพฤติกรรม' ถูกบังคับใช้โดยไม่อนุญาตให้เมธอด / คอนสตรัคเตอร์บอดี้หรือสแตติก / อินสแตนซ์เริ่มต้นบล็อก 'ไม่มีสถานะ' ถูกบังคับใช้โดยอนุญาตเฉพาะฟิลด์สุดท้ายแบบคงที่ ดังนั้นคลาสสามารถมีสถานะ (สถานะคงที่) ได้ แต่สถานะอินสแตนซ์ไม่ได้อนุมานโดยอินเทอร์เฟซ

BTW: ค่าคงที่ใน Java ถูกกำหนดโดยฟิลด์สุดท้ายแบบคงที่ (และตามแบบแผนชื่อใช้ UPPER_CASE_AND_UNDERSCORES)


54
ไม่จำเป็นว่าช่องสุดท้ายจะเป็นค่าคงที่ ซึ่งรับประกันเฉพาะสำหรับประเภทดั้งเดิมเท่านั้น โดยทั่วไปคำหลักสุดท้ายหมายความว่าตำแหน่งหน่วยความจำจะไม่เปลี่ยนแปลง
ปรากฏ

8
ฉันไม่ได้บอกว่าฟิลด์สุดท้ายเป็นค่าคงที่ แต่ค่าคงที่เป็นฟิลด์สุดท้าย โปรดทราบว่าได้รับอนุญาตให้ใส่ฟิลด์สุดท้ายแบบคงที่ที่ไม่ใช่แบบดั้งเดิมในอินเทอร์เฟซ แม้ว่าเนื้อหาของฟิลด์นั้นอาจเปลี่ยนแปลงไป แต่การอ้างอิงถึงค่าคงที่
Adriaan Koster

1
@AdriaanKoster คุณบอกตามตรงว่าฟิลด์สุดท้ายเป็นค่าคงที่: ไม่มีสถานะใดบังคับโดยอนุญาตให้มีค่าคงที่เท่านั้น - ประโยคนี้หมายความว่าเขตข้อมูลสุดท้ายทั้งหมดคงที่ คุณอาจพยายามโต้แย้งเพิ่มเติมเกี่ยวกับคำที่คุณใช้ แต่เห็นได้ชัดว่าคำพูดของคุณเป็นการให้เช่าที่เข้าใจผิด
Tomáš Zato - คืนสถานะ Monica

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

อาจเป็นความตั้งใจของนักออกแบบ java ที่จะทำให้อินเทอร์เฟซไร้สถานะ แต่ล้มเหลวเนื่องจากฟิลด์อินสแตนซ์อาจเป็นคลาสที่ปรับเปลี่ยนได้ แทนที่จะยอมรับว่าล้มเหลวพวกเขาเลือกที่จะบังคับฟิลด์อินสแตนซ์static finalซึ่งใกล้เคียงกับของจริง (C / C ++ ของจริง) มากconstที่สุดเท่าที่คุณจะทำได้ใน java น่าเสียดายที่นี่เป็นนัยและอาจทำให้เกิดความสับสนสำหรับผู้ที่ไม่ใช่ผู้เชี่ยวชาญ (ฉันเพิ่งรู้ว่าพวกเขาเป็นstaticเพราะฉันสังเกตเห็นพฤติกรรมที่ไม่ได้ตั้งใจฉันเรียนรู้ว่าพวกเขาfinalมาจากคำตอบนี้เท่านั้น)
ไม่ใช่ผู้ใช้

28

เหตุผลในการเป็น final

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

เหตุผลในการเป็น static

หากเป็นแบบคงที่แสดงว่าเป็นของอินเทอร์เฟซไม่ใช่วัตถุหรือประเภทรันไทม์ของวัตถุ


18

มีจุดสองสามจุดที่อธิบายไว้ที่นี่:

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

interface I {
  String TOKEN = SomeOtherClass.heavyComputation();
  JButton BAD_IDEA = new JButton("hello");
}

(ระวังว่าการทำสิ่งนี้ภายในคำจำกัดความของคำอธิบายประกอบอาจทำให้ javac สับสนซึ่งเกี่ยวข้องกับข้อเท็จจริงที่ว่าสิ่งที่กล่าวมาข้างต้นนั้นรวบรวมไปยังตัวเริ่มต้นแบบคงที่

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


9

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

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

แค่ความคิดของฉัน


คุณ NawMan คำอธิบายของคุณเกี่ยวกับ "felds must be static ... " ไม่สมเหตุสมผลเท่าไหร่ แต่คุณพูดถูกมากว่า "The fields must be final ... "
peakit

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

หากคุณมีpublic staticเขตข้อมูลที่ไม่เป็นfinalเช่นนั้น findbugs จะบ่น (ถูกต้อง!)
Tom Hawtin - แท

2

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

public interface iMine {
    String __ImplementationConstant();
    ...
}

public class AClass implements iMine {
    public String __ImplementationConstant(){
        return "AClass value for the Implementation Constant";
    }
    ...
}

public class BClass implements iMine {
    public String __ImplementationConstant(){
        return "BClass value for the Implementation Constant";
    }
    ...
}

อย่างไรก็ตามมันจะง่ายกว่าชัดเจนและไม่ค่อยมีแนวโน้มที่จะนำไปใช้งานที่ผิดปกติในการใช้ไวยากรณ์นี้:

public interface iMine {
    String __ImplementationConstant;
    ...
}

public class AClass implements iMine {
    public static String __ImplementationConstant =
        "AClass value for the Implementation Constant";
    ...
}

public class BClass implements iMine {
    public static String __ImplementationConstant =
        "BClass value for the Implementation Constant";
    ...
}

ดูเหมือนคุณจะบ่นมากขึ้นเกี่ยวกับฟิลด์ที่คงที่มากกว่าที่จะเป็นขั้นสุดท้าย
Daniel Yankowsky

0

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

ใน scala เราสามารถมีฟิลด์ในอินเทอร์เฟซได้แม้ว่าจะมีการใช้งานภายในตามที่ฉันอธิบายไว้ข้างต้น


-1

static:

สิ่งใด ๆ (ตัวแปรหรือวิธีการ) ที่อยู่staticใน Java สามารถเรียกใช้เป็นClassname.variablenameหรือClassname.methodnameหรือโดยตรง ไม่บังคับให้เรียกใช้โดยใช้ชื่อวัตถุเท่านั้น

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

final:

ช่วยรักษาค่าคงที่สำหรับตัวแปรเนื่องจากไม่สามารถแทนที่ในคลาสย่อยได้

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