2012-08-15 7 views
15

मेरे कोड है:जावा कोड का टुकड़ा उत्पादन स्पष्टीकरण की आवश्यकता

class Foo { 
    public int a=3; 
    public void addFive() { 
    a+=5; 
    System.out.print("f "); 
    } 
} 

class Bar extends Foo { 
    public int a=8; 
    public void addFive() { 
    this.a += 5; 
    System.out.print("b "); 
    } 
} 

public class TestClass { 
    public static void main(String[]args) { 
    Foo f = new Bar(); 
    f.addFive(); 
    System.out.println(f.a); 
    } 
} 

आउटपुट:

b 3 

कृपया मुझे समझा, क्यों इस सवाल का "बी 3" और नहीं "ख 13 के लिए उत्पादन होता है "चूंकि विधि को ओवरराइड कर दिया गया है?

+0

यह वह जगह है SCJP संबंध में भी प्रश्न, है ना? –

+0

हाँ @PrakharMohan क्या आप भी इसके लिए दिखाई दिए हैं ??? मैं अभी तक ... :) –

उत्तर

14

आप जावा में चर ओवरराइड नहीं कर सकते, इसलिए आप वास्तव में दो a चर है - Foo में एक और Bar में से एक है। दूसरी ओर addFive() विधि polymorphic है, इस प्रकार Bar.a (Bar.addFive() को fFoo होने के बावजूद यह संशोधित करता है)।

लेकिन अंत में आप f.a तक पहुंचते हैं और यह संदर्भ ज्ञात प्रकार f का उपयोग करके संकलन के दौरान हल किया गया है, जो Foo है। और इसलिए Foo.a कभी छुआ नहीं था।

जावा में बीटीडब्ल्यू गैर-अंतिम चर कभी सार्वजनिक होना चाहिए।

+4

खैर तक पहुँचने के लिए 'Geta()' 'Seta()' एक्सेसर तरीकों का उपयोग करने के लिए कह रहा है, सिवाय इसके कि यदि आपके पास 'GridBagConstraints' या इसी तरह की वस्तुओं। लेकिन एक शुरुआत के लिए, ** कभी ** एक उचित सलाह नहीं है :) –

18

F प्रकार Foo के लिए एक संदर्भ है, और चर तो बहुरूपी नहीं हैं f.aFoo से चर जो 3

यह कैसे सत्यापित करने के लिए है को संदर्भित करता है? उन्हें


भी उपयोग करने के लिए मेक सदस्य चर private और उपयोग accessors:

यह परीक्षण करने के आप Foo से a चर को हटा सकते हैं, यह आप संकलन समय त्रुटि

नोट दे देंगे देखें

+10

इस जवाब थोड़ा विस्तार करने के लिए नहीं किया है, यह एक कारण है कि यह अक्सर बजाय सीधे चर तक पहुँचने का ही टिककर खेल का उपयोग करने के लिए सुरक्षित है। –

+0

@ डेव न्यूटन कृपया मुझे गेटर्स के बारे में कुछ बताएं? मैंने पहले यह नहीं सुना है। –

+2

यह समस्या चुपचाप से बचा जा सकता है अगर जावा में एक आम प्रोग्रामिंग अभ्यास प्रयोग किया है: चर निजी होने चाहिए (केवल ही वर्ग के लिए इसका इस्तेमाल कर सकते हैं)। उसके बाद, जैसा ऊपर बताया गया है, इसे प्राप्त करने/संशोधित करने के लिए गेटर्स और सेटर्स विधियों का उपयोग करना। – axcdnt

1

चूंकि आप f.a कर रहे हैं, तो आपको Foo कक्षा से a का मूल्य मिलेगा। यदि आपने मूल्य प्राप्त करने के लिए एक विधि बुलाई है, उदाहरण के लिए getA() तो आपको कक्षा Bar से मूल्य प्राप्त होगा।

11

ऐसे प्रश्न के साथ, एससीजेपी परीक्षा छिपाने के बारे में आपके ज्ञान का आकलन कर रही है। परीक्षक जानबूझकर जटिल चीजें आपको यह विश्वास करने के लिए प्रयास करते हैं कि कार्यक्रम का व्यवहार केवल बहुरूपता पर निर्भर करता है, जो ऐसा नहीं करता है।

चलिए चीजों को थोड़ा स्पष्ट बनाने की कोशिश करते हैं क्योंकि हम addFive() विधि को हटाते हैं।

class Foo { 
    public int a = 3; 
} 

class Bar extends Foo { 
    public int a = 8; 
} 

public class TestClass { 
    public static void main(String[]args) { 
    Foo f = new Bar(); 
    System.out.println(f.a); 
    } 
} 

अब चीजें थोड़ा कम भ्रमित हैं।main विधि Foo प्रकार का एक चर घोषित करता है, जिसे रनटाइम पर Bar प्रकार का ऑब्जेक्ट सौंपा गया है। यह BarFoo से विरासत के बाद से संभव है। कार्यक्रम के बाद Foo प्रकार के चर के सार्वजनिक क्षेत्र a को संदर्भित किया जाता है।

यहां त्रुटि यह माननी होगी कि ओवरराइडिंग के समान ही अवधारणा वर्ग फ़ील्ड पर लागू होती है। लेकिन वहाँ क्षेत्रों के लिए कोई इस तरह के एक अवधारणा है: सार्वजनिक क्षेत्र वर्ग Bar की a वर्ग Foo की सार्वजनिक क्षेत्र a नहीं अधिभावी है, लेकिन यह क्या छुपा कहा जाता है। जैसा कि नाम का तात्पर्य है, इसका मतलब है कि कक्षा Bar, a के दायरे में Bar का स्वयं का फ़ील्ड देखें, जिसका Foo के साथ कुछ लेना देना नहीं है। (JLS 8.4.8 - Inheritance, Overriding, and Hiding)

तो, जब हम f.a लिख रहे हैं, तो a क्या हम इसका जिक्र कर रहे हैं? याद रखें कि क्षेत्र aऑब्जेक्ट f के घोषित प्रकार का उपयोग करके Foo पर संकलित समय पर किया गया है। नतीजतन, कार्यक्रम '3' प्रिंट करता है।

अब, Foo में addFive() विधि जोड़ें और इसे परीक्षा प्रश्न के रूप में कक्षा Bar में ओवरराइड करें। यहां polymorphism लागू होता है, इसलिए कॉल f.addFive() संकलन समय का उपयोग नहीं किया जाता है लेकिन ऑब्जेक्ट f का रनटाइम प्रकार, जो Bar है, और इस प्रकार 'बी' मुद्रित किया जाता है।

लेकिन अभी भी कुछ समझना चाहिए: क्यों क्षेत्र a, जो 5 इकाइयों द्वारा बढ़ाया गया था, अभी भी मूल्य '3' पर चिपक गया है? यहां छिपा आसपास खेल रहा है। चूंकि यह वर्ग Bar की विधि है जिसे कॉल किया जाता है, और क्योंकि Bar में, प्रत्येक aBar के सार्वजनिक क्षेत्र a को संदर्भित करता है, यह वास्तव में Bar फ़ील्ड है जो वृद्धि हुई है।

1) अब, एक सहायक प्रश्न: कैसे हम Bar के सार्वजनिक क्षेत्र amain विधि से एक्सेस कर सकता है?

System.out.println(((Bar)f).a); 

जो संकलक मजबूर fBar के रूप में की a क्षेत्र के क्षेत्र सदस्य a को हल करने: हम ऐसा ही कुछ के साथ क्या कर सकते हैं।

यह हमारे उदाहरण में 'बी 13' प्रिंट करेगा।

2) फिर भी एक और सवाल: हम कैसे काम कर सकता था चारों ओर वर्ग Bar की addFive() विधि Bar के a क्षेत्र के लिए, लेकिन इसके सुपर क्लास eponimous क्षेत्र के लिए नहीं उल्लेख करने में छुपा?

public void addFive() { 
    super.a += 5; 
    System.out.print("b "); 
} 

यह हमारे उदाहरण में '8 बी' प्रिंट होगा: बस क्षेत्र संदर्भ के सामने super कीवर्ड जोड़ने काम कर देता है।

ध्यान दें कि प्रारंभिक वक्तव्य

public void addFive() { 
    this.a += 5; 
    System.out.print("b "); 
} 

को परिष्कृत किया जा सकता है क्योंकि जब संकलक क्षेत्र a को हल है, यह भीतर से निकटतम enclosing दायरे में देखने के लिए शुरू कर देंगे विधि addFive(), और Bar वर्ग उदाहरण मिल जाए, पर स्पष्ट रूप this उपयोग करने के लिए की आवश्यकता को समाप्त।

लेकिन, ठीक है, this शायद इस परीक्षा के प्रश्न हल करने के लिए परीक्षार्थी के लिए एक सुराग था!

+0

अच्छा स्पष्टीकरण एलेक्स – Pratswinz