2015-01-27 8 views
5

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

निम्न नमूना कोड संकलित करता है तथा ठीक चलाता है (यह सिर्फ दिया निर्देशिका में फ़ाइलों को सूचीबद्ध करता है):

package com.mbm.stockbot; 

import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Paths; 

public class Temp2 { 
    public static void main(String[] args) { 
     Temp2 t = new Temp2(); 
     t.readDir(); 
    } 

    public void readDir() { 
     try { 
      Files.walk(Paths.get("C:/Users/mbmas_000/Downloads/SEC Edgar"), 1).forEach(filePath -> { 
       if (Files.isRegularFile(filePath)) { 
        System.out.println(filePath); 
       } 
      }); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
    } 
} 

ध्यान दें कि चर filePathPath का एक उदाहरण है, जिसका कार्यान्वयन मुझे लगता है कि पैकेज में निहित है java.nio.file.Path, हालांकि उस पैकेज के लिए import नहीं है।

अब, अगर मैं एक छोटे से संशोधन करना, अपने स्वयं के विधि को System.out.println करने के लिए कॉल पुनर्रचना से कहते हैं:

package com.mbm.stockbot; 

import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 

public class Temp2 { 

    public static void main(String[] args) { 
     Temp2 t = new Temp2(); 
     t.readDir(); 
    } 

    public void readDir() { 
     try { 
      Files.walk(Paths.get("C:/Users/mbmas_000/Downloads/SEC Edgar"), 1).forEach(filePath -> { 
       if (Files.isRegularFile(filePath)) { 
        printPath(filePath); 
       } 
      }); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
    } 

    public void printPath(Path passedFilePath) { 
     System.out.println(passedFilePath); 
    } 
} 

मैं अब 'आयात' import java.nio.file.Path, अन्यथा मैं एक संकलक त्रुटि मिलती है चाहिए।

तो मेरी प्रश्न हैं:

  1. तो filePath वास्तव में java.nio.file.Path का एक उदाहरण है, क्यों नहीं मैं पहले उदाहरण में आयात करने की आवश्यकता है, और

  2. हैं का उपयोग कर लैम्ब्डा अभिव्यक्ति "कवर के तहत" आयात करती है, तो मुझे import जोड़ने की आवश्यकता है जब मैं एक विधि बनाता हूं जो Path का तर्क के रूप में उदाहरण लेता है?

तरीकों filePath और passedFilePath दोनों पर कॉल करने के लिए उपलब्ध है, समान हैं मुझे अग्रणी विश्वास करने के लिए वे java.nio.file.Path के दोनों उदाहरण हैं।

उत्तर

4
(रनटाइम पर एक सामान्य प्रकार की तरह) है इस प्रकार आप एक आयात की जरूरत नहीं है

import घोषणाएं यह घोषणा करने के लिए नहीं हैं कि आपका कोड किस कक्षा का उपयोग कर रहा है; वे सिर्फ घोषणा करते हैं कि अयोग्य पहचानकर्ताओं को हल करने के लिए क्या उपयोग करना है। इसलिए यदि आप अपने कोड में अयोग्य पहचानकर्ता Path का उपयोग कर रहे हैं तो आपको यह घोषणा करने के लिए import java.nio.file.Path; का उपयोग करना होगा कि इसे इस योग्य प्रकार के लिए हल किया जाना चाहिए। रास्ते में, नाम को हल करने का यह एकमात्र तरीका नहीं है। नाम वर्ग विरासत के माध्यम से भी हल हो सकते हैं, उदा। यदि वे विरासत सदस्य वर्ग के सरल नाम से मेल खाते हैं।

आप इसके नाम की चर्चा करते हुए आप एक import बयान की जरूरत नहीं है बिना परोक्ष एक प्रकार का उपयोग कर रहे हैं, तो यह है कि लैम्ब्डा भाव तक ही सीमित नहीं है, यह भी एक विशेष जावा 8 सुविधा नहीं है। जैसे

Files.walk(Paths.get("C:/Users/mbmas_000/Downloads/SEC Edgar"), 1) 

साथ आप पहले से ही दूसरे शब्दों में परोक्ष Path प्रकार का उपयोग कर रहे हैं क्योंकि यह Paths.get की वापसी प्रकार और Files.walk की एक पैरामीटर प्रकार है,, आप java.nio.file.Path का एक उदाहरण प्राप्त करने और का जिक्र किए बिना एक और तरीका करने के लिए इसे से गुजर रहे हैं इसका प्रकार का नाम, इसलिए आपको import की आवश्यकता नहीं है। इसके अलावा आप FileVisitOption उदाहरणों की मनमानी संख्या को स्वीकार करने वाली एक varargs विधि को कॉल कर रहे हैं। आप किसी को निर्दिष्ट नहीं कर रहे हैं, इसलिए आपका कोड शून्य-लंबाई FileVisitOption[] सरणी बनाएगा और इसे Files.walk पर फिर से import के बिना पास करेगा।

बेहतर प्रकार के अनुमान के साथ, इसके नाम का जिक्र किए बिना किसी प्रकार का उपयोग करने की एक और संभावना है, उदा। अगर आप फोन:

Files.newByteChannel(path, new HashSet<>()); 

आप केवल नाम से इस प्रकार की चर्चा करते हुए बिना varargs पैरामीटर के लिए एक शून्य लंबाई FileAttribute[] सरणी रचना नहीं करते हैं, तो आप भी नाम से प्रकार OpenOption का जिक्र किए बिना एक HashSet<OpenOption> बना रहे हैं। इसलिए इसे java.nio.file.attribute.FileAttribute आयात करने और न ही java.nio.file.OpenOption आयात करने की आवश्यकता नहीं है।


तो लब्बोलुआब यह है कि क्या आप की जरूरत है एक import प्रकार के उपयोग पर निर्भर नहीं करता, लेकिन है कि क्या आप अपने साधारण नाम से यह उल्लेख करने के लिए (और एक से अधिक तरीके के बिना एक प्रकार का उपयोग करने देखते हैं नाम से इसका जिक्र है)।आपके दूसरे उदाहरण में आप अपनी विधि printPath(Path passedFilePath) में Path नाम का जिक्र कर रहे हैं; यदि आप इसे printPath(Object passedFilePath) में बदलते हैं, तो सबकुछ java.nio.file.Path के स्पष्ट import के बिना फिर से काम करेगा।

2

अंतर यह है कि दूसरे उदाहरण में, आप स्थानीय चर Path passedFilePath (विधि पैरामीटर के रूप में) घोषित करते हैं। जब आप ऐसा करते हैं, तो आपको import की आवश्यकता होती है ताकि जावा कंपाइलर को Path टाइप करने का अर्थ हो, क्योंकि एकाधिक पैकेजों में एक ही नाम के साथ कक्षा हो सकती है। आपने देखा होगा कि जब आप एक चर List something बनाते हैं और आईडीई को आयात को स्वत: बनाने के लिए कहते हैं, तो अधिकांश आईडीई आमतौर पर आपको पूछेंगे कि क्या आपका मतलब java.util.List या java.awt.List है। आप अपनी खुद की कक्षा com.myorg.myproject.List भी बना सकते हैं जो तब तीसरा विकल्प होगा।

पहले उदाहरण में filePath का सही प्रकार प्रकार Paths.get(...).forEach के लिए आवश्यक द्वारा निर्धारित किया जाता है, तो आप जावा संकलक जो class Path आप का उल्लेख बताने की आवश्यकता नहीं है।

वैसे, आप दूसरे उदाहरण में आयात को छोड़ सकते हैं, जब आप विधि हस्ताक्षर को public void printPath(java.nio.file.Path passedFilePath) के रूप में फिर से लिखेंगे। पूरी तरह से योग्य वर्ग नाम प्रदान करते समय, आपको अब आयात की आवश्यकता नहीं है क्योंकि कक्षा का नाम संदिग्ध नहीं हो सकता है।

आप सोच सकते हैं "लेकिन मुझे पूरे मानक पुस्तकालय में Path नामक केवल एक वर्ग होने पर आयात या पूरी तरह से योग्य नाम की आवश्यकता क्यों है और मेरे पास उस नाम का एक वर्ग नहीं है?" - याद रखें कि जावा कोड पुन: प्रयोज्यता के लिए डिज़ाइन किया गया है। जब आपका कोड किसी अन्य प्रोजेक्ट में उपयोग किया जाता है, तो उस प्रोजेक्ट में ऐसी कक्षा हो सकती है या एक तृतीय-पक्ष लाइब्रेरी का उपयोग हो सकता है जिसमें आपका कोड संदिग्ध होगा।

+0

वह 'पथ' प्रकार के 'फ़ाइलपाथ' चर घोषित करता है, जो कि उनके प्रश्न का बिंदु है। 'FilePath' के साथ लैम्ब्डा परिभाषा उस प्रकार का है, लेकिन इसमें कोई आयात की आवश्यकता नहीं है। यह जावा 8 में बस एक वैकल्पिक वाक्यविन्यास है जिसे आपको 'पथ' प्रकार को चर परिभाषा – Alex

+0

@Alex I पर याद करने की आवश्यकता नहीं है। उत्तर अपडेट किया गया। – Philipp

0

आपको दूसरे उदाहरण में एक आयात का उपयोग करने की आवश्यकता है क्योंकि आप एक चर घोषित कर रहे हैं।

इसमें लैम्ब्डा अभिव्यक्तियों के साथ कुछ भी नहीं है। यदि आप एक अज्ञात वर्ग का उपयोग करते हैं तो आप वही काम करेंगे।

0

मुझे लगता है कि बिंदु आप वर्णन करने के लिए कोशिश कर रहे हैं इस तरह सरल किया जा सकता:

यह लैम्ब्डा की आवश्यकता है एक आयात

Paths.get("path").forEach((Path filePath) -> {});

यह लैम्ब्डा एक आयात की आवश्यकता नहीं है

Paths.get("path").forEach((filePath) -> {});

Path.forEach(...) के बाद से एक Consumer<? super Path> मुझे लगता है उत्तरार्द्ध मामले ऑन-द-मक्खी ? super Path के एक नए प्रकार पैदा कर रही है लगता है, और के बाद से यह एक नए प्रकार

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