जावा टाइप इंप्रेशन क्यों नहीं करता है?


44

मैंने हमेशा सोचा है कि जावा इस प्रकार का अनुमान क्यों नहीं लगाता है कि भाषा वह है जो वह है, और उसका वीएम बहुत परिपक्व है। Google का गो एक भाषा का एक उदाहरण है जिसमें उत्कृष्ट प्रकार की खोज है और यह एक टाइपिंग की मात्रा को कम करता है। क्या इस विशेषता के जावा का हिस्सा नहीं होने के पीछे कोई विशेष कारण है?


3
पुरानी और लोकप्रिय भाषा में जावा के रूप में बैकवर्ड संगतता नियम
शाफ़्ट फ्रीक

9
@ratchetfreak प्रकार का अनुमान पीछे की ओर संगत तरीके से नहीं जोड़ा जा सकता है? पुराने कार्यक्रम केवल आवश्यकता से अधिक प्रकार की जानकारी प्रदान करेंगे।

1
टाइप एरासुरे के साथ उपयोग किए जाने पर इसके कुछ अनपेक्षित प्रभाव हो सकते हैं। docs.oracle.com/javase/tutorial/java/generics/…
Zachary Yates

4
ध्यान दें कि जावा 8 लाएगा एक बहुत अपने लैम्ब्डा की सुविधा के साथ प्रकार निष्कर्ष की: आप किसी भी प्रकार का उल्लेख है और सब कुछ अनुमान लगाया जा रहा है बिना जटिल lambdas लिख सकते हैं।
जोकिम सॉरे

4
स्थानीय चर प्रकार का अनुमान जावा में आ रहा है: JEP 286: स्थानीय-परिवर्तनीय प्रकार का आविष्कार
जिमी पेज

जवाबों:


60

तकनीकी रूप से, जावा का उपयोग जेनरिक का उपयोग करते समय टाइप अवरचना है। एक साथ सामान्य विधि की तरह

public <T> T foo(T t) {
  return t;
}

कंपाइलर विश्लेषण करेगा और समझेगा कि आप कब लिखते हैं

// String
foo("bar");
// Integer
foo(new Integer(42));

पहली कॉल के लिए एक स्ट्रिंग लौटाया जा सकता है और एक तर्क के रूप में इनपुट के आधार पर दूसरी कॉल के लिए एक पूर्णांक बनाया जाएगा। परिणामस्वरूप आपको उचित संकलन-समय की जाँच मिल जाएगी। इसके अतिरिक्त, जावा 7 में, जेनरिक को इंस्टेंट करने पर कुछ अतिरिक्त प्रकार के अनुमान लगाने पड़ सकते हैं

Map<String, String> foo = new HashMap<>();

जावा हमारे लिए रिक्त कोण कोष्ठक में भरने के लिए पर्याप्त है। अब चर समर्थन के एक हिस्से के रूप में जावा समर्थन प्रकार का अनुमान क्यों नहीं लगाता है ? एक बिंदु पर, चर घोषणाओं में टाइप अवर के लिए एक RFE था , लेकिन इसे "ठीक नहीं होगा" के रूप में बंद कर दिया गया था

मनुष्य दो प्रकार से घोषणा के अतिरेक से लाभान्वित होता है। सबसे पहले, निरर्थक प्रकार मूल्यवान प्रलेखन के रूप में कार्य करता है - पाठकों को यह जानने के लिए कि यह किस प्रकार का रिटर्न मिलता है, वे गेटपैप () की घोषणा के लिए खोज न करें। दूसरा, अतिरेक प्रोग्रामर को इच्छित प्रकार घोषित करने की अनुमति देता है, और इस तरह संकलक द्वारा निष्पादित क्रॉस चेक से लाभ होता है।

इसे बंद करने वाले योगदानकर्ता ने यह भी नोट किया कि यह "अन-जावा-लाइक" महसूस करता है, जिससे मैं सहमत हूं। जावा की वाचालता एक आशीर्वाद और अभिशाप दोनों हो सकती है, लेकिन यह भाषा को वह बनाता है जो यह है।

बेशक कि विशेष रूप से RFE उस बातचीत का अंत नहीं था। जावा 7 के दौरान, इस सुविधा पर फिर से विचार किया गया था , जिसमें कुछ परीक्षण कार्यान्वित किए गए थे, जिनमें से एक जेम्स गोसलिंग ने खुद को शामिल किया था। फिर, इस सुविधा को अंततः नीचे गोली मार दी गई थी।

Java 8 की रिलीज़ के साथ, अब हमें लैम्ब्डा के एक भाग के रूप में टाइप इनफैक्शन मिलता है:

List<String> names = Arrays.asList("Tom", "Dick", "Harry");
Collections.sort(names, (first, second) -> first.compareTo(second));

जावा कंपाइलर विधि को देखने में सक्षम है Collections#sort(List<T>, Comparator<? super T>)और फिर इंटरफ़ेस Comparator#compare(T o1, T o2)और निर्धारित करता है firstऔर इस प्रकार प्रोग्रामर को लंबोदर अभिव्यक्ति में टाइप को आराम करने की अनुमति देने की अनुमति secondहोनी चाहिए String


5
First, the redundant type serves as valuable documentation - readers do not have to search for the declaration of getMap() to find out what type it returns- हाँ, अगर यह है HashMap<String, Integer> map = foo.getMap()तो मैं सहमत हूँ - सी # में मैं आमतौर पर varऐसे मामलों में उपयोग नहीं करता, भले ही मैं कर सकता था। लेकिन इस तर्क में पानी नहीं है अगर यह है HashMap<String, Integer> map = new HashMap<String, Integer>()। यह सही अतिरेक है और मुझे दो बार टाइप नाम लिखने में कोई फायदा नहीं हुआ। और मैं एक कंपाइलर क्रॉस चेक से यहां कैसे लाभान्वित होऊंगा, मुझे बिल्कुल समझ नहीं है।
कोनराड मोरावस्की

9
हाँ और यह जेनेरिक के लिए अच्छा है, लेकिन मैं अभी भी varजावा में C # के समकक्ष याद करता हूं ।
कोनराड मोरावस्की

15
यह किया जा रहा है "गैर-जावा की तरह" का सवाल है, यह (घटिया) कहानी मन में आता है;) 9gag.com/gag/2308699/-this-is-how-things-are-done-around-here
कोनराड Morawski

6
इसके अलावा, किसी फ़ंक्शन का रिटर्न प्रकार अक्सर स्पष्ट या अनावश्यक होता है, और यहां तक ​​कि ऐसे मामलों में भी जब आपका आईडीई नहीं होता है, तो आप आधे सेकंड में टाइप कर सकते हैं।
फ़ॉसी

8
मेरा मानना ​​है कि आधिकारिक उद्धरण Humans benefit from the redundancyवर्तमान प्रश्न का वास्तविक उत्तर है, क्योंकि मैंने पढ़ा हर औचित्य जावा डिजाइनरों से एक गंभीर, निराधार और हास्यास्पद बहाना लगता है: C # और C ++ दोनों की विशेषता है, C # और C ++ डिजाइनर किसी से कम सक्षम नहीं हैं। जावा का, और हर कोई इसका उपयोग करके खुश है। ऐसा क्या है जो जावा डेवलपर्स को C # या C ++ डेवलपर्स से अलग बनाता है? यही कारण है कि मैं @KonradMorawski से सहमत हूं, "यह है कि यहां चीजें कैसे की जाती हैं" फिर से लगता है कि इसके पीछे वास्तविक कारण हैं।
पियरसेबल

16

ठीक है, पहले बंद, टाइप इनफ़ेक्शन का रनटाइम की परिपक्वता से कोई लेना- देना नहीं है, चाहे वह रनटाइम 30 साल पुराना सीपीयू हो या वीएम जो इतना नया है कि बिट्स अभी भी चमकदार हैं। यह सब संकलक के बारे में है।

इसने कहा, यह जेनेरिक के लिए अनुमत है, यही कारण है कि इसे गैर-जेनेरिक प्रकारों के लिए अनुमति नहीं दी गई है, क्योंकि दर्शन के लिए ऐसा लगता है - डिजाइनरों को इसे जोड़ने से रोकने के लिए कुछ भी नहीं है।

अपडेट: ऐसा लगता है कि जावा 10 इसका समर्थन करता है- http://openjdk.java.net/jeps/286


5

जहाँ तक मुझे पता है, जब नब्बे के दशक की शुरुआत में जावा को डिज़ाइन किया गया था, तो यह अनुमान नहीं था कि मुख्यधारा की भाषाओं के बीच लोकप्रिय है (लेकिन यह पहले से ही एक बहुत अच्छी तरह से ज्ञात अवधारणा है, उदाहरण के लिए एमएल)। इसलिए, मैं कल्पना कर सकता हूं कि इस प्रकार का अनुमान शायद समर्थित नहीं था क्योंकि जावा का उद्देश्य सी ++, पास्कल, या अन्य मुख्यधारा की भाषाओं से आने वाले प्रोग्रामर थे, जिनके पास यह नहीं था (कम से कम आश्चर्य का सिद्धांत)।

साथ ही, जावा के डिजाइन सिद्धांतों में से एक यह है कि चीजों को स्पष्ट रूप से यह सुनिश्चित करने के लिए लिखा जाए कि प्रोग्रामर और कंपाइलर को कोड की समान समझ हो: जानकारी की नकल करने से त्रुटियों की संभावना कम हो जाती है। बेशक, यह स्वाद का विषय हो सकता है कि क्या कुछ और अक्षर टाइप करना अतिरिक्त सुरक्षा प्रदान करने के लायक है, लेकिन यह जावा के लिए डिजाइन दर्शन था: चीजों को स्पष्ट रूप से लिखें।

मुझे नहीं पता कि जावा को भविष्य में टाइप इंट्रेंस मिलेगा लेकिन IMO जो कि भाषा के लिए एक बड़ी क्रांति होगी (जैसा कि ग्लेन नेल्सन ने उल्लेख किया है, इसे "अन-जावा-लाइक" के रूप में वर्णित किया गया था) और फिर कोई इसे छोड़ने पर भी विचार कर सकता है एक नए नाम के नाम पर जावा।

यदि आप एक JVM भाषा का उपयोग करना चाहते हैं, तो आप किस प्रकार के Scala का उपयोग कर सकते हैं।


2

मैं कुछ संभावित कारणों के बारे में सोच सकता हूं। एक यह है कि स्पष्ट टाइपिंग स्व-दस्तावेजीकरण है। जावा आमतौर पर इसे कॉन्सेप्ट पर प्राथमिकता देता है। एक अन्य कारण उन मामलों में हो सकता है जहां प्रकार कुछ अस्पष्ट है। जब एक प्रकार या किसी भी उपप्रकार एक दिनचर्या को संतुष्ट कर सकता है। मान लीजिए कि आप एक सूची का उपयोग करना चाहते हैं, लेकिन कोई व्यक्ति आता है और ArrayList के लिए अनन्य विधि का उपयोग करता है। JIT एक ArrayList का अनुमान लगाएगा और यदि आप एक संकलन त्रुटि चाहते हैं तो भी इसे जारी रखेंगे।


8
GridBagLayout ग्रिडबैग कैसे करता है = नया GridBagLayout (); स्व दस्तावेज़ में जोड़ें? इसका शुद्ध पुनरावृत्ति।
एंडर्स लिंडेन

3
यह एक ऐसे मामले से अलग है जहां दो प्रकार समान नहीं हैं। आप बस आसानी से एक उपवर्ग का उदाहरण दे सकते हैं।
जिग्गी

Let's say you want to use a List, but someone comes along and uses a method exclusive to ArrayList. The JIT would infer an ArrayList and carry on even if you wanted a compilation error- मुझे यह समझ नहीं आ रहा है। एक चर को संस्थापित करने के क्षण में टाइप इंफ़ेक्शन होता है, न कि उस पर एक विधि को बुलाना। क्या आप शायद इसका एक उदाहरण दिखा सकते हैं कि आपका क्या मतलब है?
कोनराड मोरावस्की

2
@KonradMorawski: मेरा मानना ​​है कि उसका मतलब है कि यदि कोई विधि ArrayList को लौटाती है, तो वह प्रकार उसका अनुमान होगा। यदि आप एक प्रकार का इलाज करना चाहते हैं जो कि रिटर्न प्रकार के अलावा कुछ है, तो आप अनुमान का उपयोग नहीं कर सकते हैं। मुझे समझ में नहीं आता है कि यह कभी भी एक कोडबेस में किसी भी तरह से साने के पास कहीं भी समस्या कैसे हो सकती है।
फॉशी

JIT प्रकार की अस्वीकृति में कोई भूमिका नहीं निभाएगा। प्रकार का निष्कर्ष एक संकलन-समय की घटना है। और अगर एक चर को एक सूची के संदर्भ के रूप में घोषित किया जाता है, तो उस पर ArrayList सदस्यों को एक्सेस करने की कोशिश करना चेक नहीं करेगा और आपको एक संकलन त्रुटि मिलती है
sara

0

यह सबसे सामान्य इंटरफ़ेस का उपयोग करते हुए चर घोषित करने के लिए अच्छी तरह से स्थापित सिफारिश का खंडन करता है जो आपकी आवश्यकताओं को पूरा करेगा, और उन्हें एक उपयुक्त कार्यान्वयन वर्ग के साथ आरंभ करेगा, जैसे कि

Collection<String> names = new ArrayList<>();

प्रभावी रूप से,

var names = new ArrayList<String>();

इसके लिए सिंटैक्टिक शुगर के अलावा कुछ नहीं है

ArrayList<String> names = new ArrayList<String>();

यदि आप चाहते हैं कि, आपका IDE new ArrayList<String>()"वन क्लिक" (रिफ्लेक्टर / स्थानीय वैरिएबल बनाएं) के साथ इसे अभिव्यक्ति से उत्पन्न कर सकता है , लेकिन याद रखें कि यह "उपयोग इंटरफेस" सिफारिश का खंडन करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.