Can I override a static method?
बहुत से लोग सुना है कि आप एक स्थिर विधि ओवरराइड नहीं कर सकते। यह सच है - आप नहीं कर सकते। लेकिन यह इस तरह कोड लिखने के लिए संभव है:
class Foo {
public static void method() {
System.out.println("in Foo");
}
}
class Bar extends Foo {
public static void method() {
System.out.println("in Bar");
}
}
यह संकलित करता है तथा ठीक चलाता है। क्या यह एक स्थिर विधि का एक उदाहरण है जो एक और स्थैतिक विधि को ओवरराइड कर रहा है? जवाब नहीं है - यह एक स्थिर विधि को छुपा एक स्थिर विधि का एक उदाहरण है। यदि आप एक स्थिर विधि को ओवरराइड करने का प्रयास करते हैं, तो कंपाइलर वास्तव में आपको रोक नहीं देता है - यह ऐसा नहीं करता जो आपको लगता है कि यह करता है।
तो क्या अंतर है?
संक्षेप में, जब आप किसी विधि को ओवरराइड करते हैं, तब भी आपको रन-टाइम पॉलीमोर्फिज्म का लाभ मिलता है, और जब आप छिपाते हैं, तो आप नहीं करते हैं। तो उसका क्या मतलब हुआ?इस कोड पर एक नज़र डालें:
class Foo {
public static void classMethod() {
System.out.println("classMethod() in Foo");
}
public void instanceMethod() {
System.out.println("instanceMethod() in Foo");
}
}
class Bar extends Foo {
public static void classMethod() {
System.out.println("classMethod() in Bar");
}
public void instanceMethod() {
System.out.println("instanceMethod() in Bar");
}
}
class Test {
public static void main(String[] args) {
Foo f = new Bar();
f.instanceMethod();
f.classMethod();
}
}
आप इस चलाते हैं, उत्पादन फू में
instanceMethod() बार
classMethod() में है
क्यों हम से instanceMethod मिलता है बार, लेकिन foo से classMethod()? क्या हम इन दोनों तक पहुंचने के लिए एक ही इंस्टेंस एफ का उपयोग नहीं कर रहे हैं? हां हम हैं - लेकिन चूंकि कोई ओवरराइड कर रहा है और दूसरा छुपा रहा है, हम अलग-अलग व्यवहार देखते हैं।
उदाहरण के बाद से विधि() है (ड्रम रोल कृपया ...) एक उदाहरण विधि है, जिसमें बार फू से विधि को ओवरराइड करता है, रन समय पर जेवीएम उदाहरण के वास्तविक वर्ग का उपयोग करता है यह निर्धारित करने के लिए कि कौन सी विधि चलाना है। हालांकि एफ को फू के रूप में घोषित किया गया था, लेकिन हमने बनाया वास्तविक उदाहरण एक नया बार() था। तो रनटाइम पर, JVM को पता चलता है कि f एक बार उदाहरण है, और इसलिए यह Foo में से एक के बजाय बार में instanceMethod() को कॉल करता है। इस तरह जावा सामान्य रूप से उदाहरण विधियों के लिए काम करता है।
कक्षा मोड() के साथ हालांकि। चूंकि (अहम) यह एक क्लास विधि है, संकलक और जेवीएम को विधि का आह्वान करने के लिए वास्तविक उदाहरण की आवश्यकता नहीं है। और यहां तक कि यदि आप एक प्रदान करते हैं (जो हमने किया था: एफ द्वारा संदर्भित उदाहरण) जेवीएम इसे कभी नहीं देख पाएगा। कंपाइलर केवल संदर्भ के घोषित प्रकार को देखेगा, और उस घोषित प्रकार का उपयोग करेगा, संकलित समय पर, कॉल करने के लिए कौन सी विधि। चूंकि एफ को प्रकार फू के रूप में घोषित किया गया है, इसलिए संकलक f.classMethod() को देखता है और इसका निर्णय लेता है इसका मतलब है Foo.classMethod। इससे कोई फर्क नहीं पड़ता कि एफ द्वारा reffered उदाहरण वास्तव में एक बार है - स्थैतिक तरीकों के लिए, संकलक केवल संदर्भ के घोषित प्रकार का उपयोग करता है। जब हम कहते हैं कि एक स्थिर विधि में रन-टाइम पॉलीमोर्फिज्म नहीं है तो हमारा यही मतलब है।
क्योंकि उदाहरण विधियों और वर्ग विधियों में व्यवहार में यह महत्वपूर्ण अंतर है, उदाहरण के तरीकों के लिए हम अलग-अलग शर्तों का उपयोग करते हैं - "विधियों" के लिए "ओवरराइडिंग" और कक्षा के तरीकों के लिए "छिपाने" - दो मामलों के बीच अंतर करने के लिए। और जब हम कहते हैं कि आप एक स्थैतिक विधि को ओवरराइड नहीं कर सकते हैं, तो इसका अर्थ यह है कि यदि आप कोड लिखते हैं जो ऐसा लगता है कि यह एक स्थिर विधि ओवरराइड कर रहा है (जैसे इस पृष्ठ के शीर्ष पर पहले फू और बार) - यह नहीं होगा एक ओवरराइड विधि की तरह व्यवहार करते हैं। अधिक संदर्भ के लिए this
आपको नहीं होना चाहिए किसी ऑब्जेक्ट से पहले स्थान पर स्थैतिक विधियों को कॉल करना, आपको इसे कक्षा से कॉल करना चाहिए। –