2016-03-21 6 views
15

जब आप varargs का उपयोग करते हैं, परिणामी सरणी का घटक प्रकार कैसे निर्धारित किया जाता है?varargs सरणी के लिए घटक प्रकार कैसे निर्धारित किया जाता है?

उदाहरण के लिए, क्या यह प्रोग्राम true प्रिंट करने की गारंटी है या इसका व्यवहार तकनीकी रूप से अनिर्दिष्ट है?

public static void main(String[] args) { 
    foo("", 0); 
} 

static <T> void foo(T... arr) { 
    System.out.println(arr.getClass() == Serializable[].class); 
} 
+2

मैं यहां जवाब दूंगा कि "उनके द्वारा उपयोग की जाने वाली हर संकलक के साथ हमेशा कम से कम कुछ विसंगतियां होती हैं जो" उनके द्वारा उपयोग की जाने वाली जटिल जटिलता में सभी प्रकार के अनुमान नियम हैं। " –

+1

शायद: http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html#jls-18.5.1 और निम्न। – assylias

उत्तर

1

ठीक है, मैं नहीं 100% इस बारे में निश्चित और अधिक गतिशील बंधन, जेनरिक और प्रकार विलोपन की तरह हूँ, लेकिन मैं इस varargs साथ कोई संबंध नहीं है लगता है, लेकिन।

"जावा में सरणी कॉन्वर्सेंट हैं, लेकिन जेनेरिक नहीं हैं। दूसरे शब्दों में, स्ट्रिंग [] ऑब्जेक्ट का एक उप प्रकार है [], लेकिन स्टैक स्टैक का उप-प्रकार नहीं है।"

स्रोत: http://algs4.cs.princeton.edu/13stacks/

तो अपने सवाल का जवाब देने, इस व्यवहार निर्दिष्ट दस्तावेज और उम्मीद है।

पुस्तक में: 'प्रभावी जावा' यहोशू बलोच इस तरह यह बताते हैं:

सरणी दो महत्वपूर्ण तरीकों से सामान्य प्रकार से भिन्न होते हैं। सबसे पहले, सरणी covariant हैं। यह डरावना ध्वनि शब्द का अर्थ यह है कि यदि सब सुपर का एक उप प्रकार है, तो सरणी प्रकार सब [] सुपर [] का एक उप प्रकार है। जेनेरिक, इसके विपरीत, परिवर्तनीय हैं: किसी भी दो अलग-अलग प्रकारों के लिए टाइप 1 और टाइप 2, सूची < टाइप 1 > न तो उपप्रकार है और न ही सूची < टाइप[जेएलएस, 4.10; Naftalin07, 2.5]। आपको लगता है कि इसका मतलब यह है कि जेनेरिक कम हैं, लेकिन तर्कसंगत रूप से यह सरणी है जो कम हैं।

और मैं उन सरणीओं के बारे में क्यों बात कर रहा हूं जिनसे आप पूछ सकते हैं? खैर, क्योंकि अंतराल अंततः सरणी बन जाएगा।

"पिछले रिलीज में, एक विधि जिसने मनमाने ढंग से मूल्यों को लिया है, आपको एक सरणी बनाने और विधि को आविष्कार करने से पहले मूल्यों को सरणी में रखना आवश्यक है।"

"यह अभी भी सच है कि कई तर्क एक सरणी में पारित किए जाने चाहिए, लेकिन varargs सुविधा स्वचालित हो जाती है और प्रक्रिया को छुपाती है।"

स्रोत: https://docs.oracle.com/javase/8/docs/technotes/guides/language/varargs.html

2

इस उत्तर 100% जवाब आप देख रहे हैं नहीं हो सकता है, लेकिन शायद यह मदद करता है। सामान्य रूप से arr.getClass() कुछ सरणी वर्ग (सबसे सामान्य Object[].class) लौटाएगा, लेकिन Integer[].class, Number[].class, या यहां तक ​​कि Serializable[].class - आमतौर पर सभी तत्वों का सबसे विशिष्ट प्रकार हो सकता है, लेकिन मैं इस पर भरोसा नहीं करता कि एम- szalik उत्तर)। यदि आप यह सुनिश्चित करना चाहते हैं कि सरणी में निहित सभी वर्ग Serializable का उदाहरण हैं तो आपको प्रत्येक तत्व (बीटीडब्ल्यू) की जांच करनी होगी।प्रस्तुत कार्यान्वयन null मूल्यों का समर्थन नहीं करता):

Btw:

static <T> void foo(T... arr) { 
    System.out.println(Stream.of(arr) 
      .filter(e -> !Serializable.class.isInstance(e.getClass())) 
      .findFirst() 
      .orElse(null) == null); 
} 

आप पर एक नजर है कर सकते हैं। मैं कप्तान Fogetti की राय से सहमत:

ठीक है, मैं 100% इस बारे में निश्चित नहीं हूँ, लेकिन मैं इस varargs साथ कोई संबंध नहीं है लगता है, लेकिन और अधिक गतिशील बंधन, जेनरिक और प्रकार विलोपन की तरह।

नोट:

बस अपने foo कार्यान्वयन के कुछ उदाहरण:

  • foo(1, 2) होगा Integer[].class
  • foo(1, 2.0) होगा Number[].class
  • foo ("", 1)Serializable[].class होगा
  • foo(null, 2) होगा Integer[].class
  • foo("", new Object()) होगा Object[].class
1

यह लेकिन varargs बारे में नहीं है जेनरिक के बारे में अधिक।
संकलन के दौरान सामान्य जानकारी खो जाती है। आपके varargs पैरामीटर को कंपाइलर द्वारा सरणी में परिवर्तित किया जाता है। तो JVM इस प्रकार के बारे में तय नहीं करता है लेकिन संकलक करता है।

आपका कोड folows के रूप में एक बाईटकोड को संकलित किया गया है:

public static void main(String[] args) { 
    foo(new Serializable[]{"", Integer.valueOf(0)}); 
} 

निर्णय के एल्गोरिथ्म काफी लंबा है, लेकिन आप इसके बारे में यहाँ पढ़ सकते हैं। https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

3

मैं इस कोड भाग गया और उत्पादन आपको बताता है कि कोई गारंटी है

ईमानदारी से मैं इस जादू के पीछे के कारणों को पता नहीं है (कम से कम अगर कक्षाएं अलग पदानुक्रम शाखाओं पर एक से अधिक आम पूर्वज है), लेकिन मैं सिर्फ एक टिप्पणी

import java.util.*; 
import java.lang.*; 
import java.io.*; 

class Ideone 
{ 

    interface A{} 
    interface B{} 
    class AB implements A, B {} 
    class BA implements A, B {} 

    public static void main (String[] args) throws java.lang.Exception 
    { 
     foo(new AB(), new BA()); 
     foo2(new AB(), new BA()); 
    } 

    static <T> void foo(T... arr) { 
     System.out.println(arr.getClass() == A[].class); 
    } 

    static <T> void foo2(T... arr) { 
     System.out.println(arr.getClass() == B[].class); 
    } 
} 

उत्पादन

true 
false 
के रूप में यह पोस्ट नहीं कर सके

अधिक अजीब बातें:

तो interface Binterface A से पहले घोषित किया जाता है, परिणाम विपरीत है:

false 
true 

implements ब्लॉक में विधि कॉल, विधि घोषणा आदेश और इंटरफेस के क्रम में बहस के क्रम बदलने करता है मेरे लिए प्रभाव नहीं बनाओ (1.8.0_51)।

संबंधित मुद्दे