जावा अनियंत्रित: varargs पैरामीटर के लिए अनियंत्रित जेनेरिक सरणी निर्माण


111

मैंने अपने जावा कोड में अनियंत्रित चेतावनियाँ दिखाने के लिए नेटबीन्स सेट किया है, लेकिन मैं निम्नलिखित पंक्तियों पर त्रुटि को समझने में असफल रहा हूँ:

private List<String> cocNumbers;
private List<String> vatNumbers;
private List<String> ibans;
private List<String> banks;
...
List<List<String>> combinations = Utils.createCombinations(cocNumbers, vatNumbers, ibans);

देता है:

[unchecked] unchecked generic array creation for varargs parameter of type List<String>[]

विधि स्रोत:

/**
 * Returns a list of all possible combinations of the entered array of lists.
 *
 * Example: [["A", "B"], ["0", "1", "2"]]
 * Returns: [["A", "0"], ["A", "1"], ["A", "2"], ["B", "0"], ["B", "1"], ["B", "2"]]
 *
 * @param <T> The type parameter
 * @param elements An array of lists
 * @return All possible combinations of the entered lists
 */
public static <T> List<List<T>> createCombinations(List<T>... elements) {
    List<List<T>> returnLists = new ArrayList<>();

    int[] indices = new int[elements.length];
    for (int i = 0; i < indices.length; i++) {
        indices[i] = 0;
    }

    returnLists.add(generateCombination(indices, elements));
    while (returnLists.size() < countCombinations(elements)) {
        gotoNextIndex(indices, elements);
        returnLists.add(generateCombination(indices, elements));
    }

    return returnLists;
}

क्या वास्तव में गलत हो रहा है और मैं इसे कैसे ठीक करूंगा, क्योंकि मुझे लगता है कि कोड में अनियंत्रित चेतावनी छोड़ना एक अच्छा विचार नहीं है?

उल्लेख करना भूल गया, लेकिन मैं जावा 7 का उपयोग कर रहा हूं।

संपादित करें : इसके अलावा अब मैं देखता हूं कि विधि निम्नलिखित है:

[unchecked] Possible heap pollution from parameterized vararg type List<T>
  where T is a type-variable:
    T extends Object declared in method <T>createCombinations(List<T>...)

17
जो कुछ भी आप करते हैं, जावा में आपको 0 के साथ एक नए बनाए गए इंट सरणी को इनिशियलाइज़ करने की आवश्यकता नहीं है ...
थॉमस मुलर

जवाबों:


165

जैसा कि जानोह.जनोह ने उल्लेख किया है, जावा में वेरगेज केवल सरणियों के लिए एक वाक्य रचना चीनी है और साथ ही कॉलिंग साइट पर एक सरणी का निहित निर्माण। इसलिए

List<List<String>> combinations =
    Utils.createCombinations(cocNumbers, vatNumbers, ibans);

वास्तव में है

List<List<String>> combinations =
    Utils.createCombinations(new List<String>[]{cocNumbers, vatNumbers, ibans});

लेकिन जैसा कि आप जानते हैं, new List<String>[]जावा में, कई अन्य प्रश्नों में शामिल होने वाले कारणों के लिए अनुमति नहीं है, लेकिन मुख्य रूप से इस तथ्य के साथ करना है कि सरणियाँ रनटाइम पर उनके घटक प्रकार को जानती हैं, और रनटाइम पर जांच करें कि क्या तत्व इसके घटक से मेल खाते हैं प्रकार, लेकिन यह जांच पैरामीटर प्रकार के लिए संभव नहीं है।

वैसे भी, विफल होने के बजाय, कंपाइलर अभी भी सरणी बनाता है। यह ऐसा ही कुछ करता है:

List<List<String>> combinations =
    Utils.createCombinations((List<String>[])new List<?>[]{cocNumbers, vatNumbers, ibans});

यह संभावित असुरक्षित है, लेकिन जरूरी नहीं कि असुरक्षित हो। अधिकांश varargs विधियाँ बस varargs तत्वों पर पुनरावृति करती हैं और उन्हें पढ़ती हैं। इस स्थिति में, यह सरणी के रनटाइम प्रकार की परवाह नहीं करता है। यह आपकी विधि के मामले में है। चूंकि आप जावा 7 पर हैं, इसलिए आपको @SafeVarargsएनोटेशन को अपनी विधि में जोड़ना चाहिए , और आपको यह चेतावनी नहीं मिलेगी। यह एनोटेशन मूल रूप से कहता है, यह विधि केवल तत्वों के प्रकार की परवाह करती है, न कि सरणी के प्रकार की।

हालाँकि, कुछ varargs विधियाँ हैं जो रनटाइम प्रकार की सरणी का उपयोग करती हैं। इस मामले में, यह संभावित रूप से असुरक्षित है। इसलिए चेतावनी दी है।


16
न केवल सेफवर्ग्स का उल्लेख करने के लिए धन्यवाद, बल्कि यह बताने के लिए कि हम इसका उपयोग कब कर सकते हैं।
KitsuneYMG

12
यदि यह तुरंत किसी के लिए स्पष्ट नहीं था (जैसे यह मेरे लिए नहीं था), तो Javadocs के लिए @SafeVarargsएक विधि का एक उदाहरण है जो असुरक्षित docs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs है। .html
मचिआकिग

3
तो @SafeVarargsइसका उपयोग तब किया जा सकता है जब आपकी विधि केवल सरणी के तत्वों का उपभोग करती है और सरणी में डालने के लिए तत्वों का उत्पादन (और कभी नहीं) करेगी ? विशेष ध्यान रखना चाहिए यदि आप सरणी तर्क को किसी ऐसे क्षेत्र में असाइन करते हैं जिसे अन्य तरीकों से हेरफेर किया जा सकता है क्योंकि यह निर्धारित करना कि कोई असुरक्षित संचालन नहीं है, तो यह तुच्छ नहीं हो सकता है।
नेक्सस

13

क्योंकि जावा कंपाइलर varargs के लिए एक अंतर्निहित सरणी निर्माण का उपयोग करता है, और जावा एक सामान्य सरणी निर्माण की अनुमति नहीं देता है (क्योंकि प्रकार तर्क तर्क योग्य नहीं है)।

नीचे दिया गया कोड सही है (इन कार्यों को सरणियों के साथ अनुमति दी गई है), इसलिए अनियंत्रित चेतावनी की आवश्यकता है:

public static <T> List<List<T>> createCombinations(List<T> ... lists) {
    ((Object[]) lists)[0] = new ArrayList<Integer>();
    // place your code here
}

एक व्यापक विवरण यहां देखें

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