2015-01-27 18 views
5

Bu soru, lambda ifadelerinin işe yarayacağı görünen "gizli" veya yerel Java paketleri paketleriyle ilgilidir.Java Lambda İfadeleri "Gizli" veya Yerel Paket İthalatlarından Yararlanıyor mu?

Aşağıdaki örnek kod derler ve (bu sadece verilen dizindeki dosyaları listeler) ince çalıştırır: Değişken filePathPath örneğidir olduğunu

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(); 
     } 
    } 
} 

Not halde uygulama bence paketin içerdiği Bu paket için import olmasına rağmen java.nio.file.Path. Ben küçük bir değişiklik yapılmasını yaparsanız

Şimdi, kendi yöntemine System.out.println çağrısına üstlenmeden tarafından ki:

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); 
    } 
} 

şimdi 'ithal' import java.nio.file.Path, aksi takdirde bir derleyici hatası almak gerekir. kullanılıyorsa

  1. filePath Eğer İlk örnekte içe gerekmez yapmamaları, aslında java.nio.file.Path bir örneğidir ve

  2. :

    Yani benim sorular burada lambda ifadesi içe aktarma işlemini "kapakların altında" gerçekleştirir, o zaman neden neden import parametresini eklediğimde, bir argüman olarak Path örneğini alan bir yöntem oluşturduğumda? filePath ve passedFilePath hem çağırmak için kullanılabilir

yöntemleri aynıdır, onlar java.nio.file.Path her iki örneği olduğuna inanmaya beni neden olur.

cevap

4
(zamanında bir jenerik türü gibi) yeni bir tür olduğundan, böylece Bir içe gerekmez

import bildirimleri, kodunuzun hangi sınıfları kullandığını belirtmez; Niteliksiz tanımlayıcıları çözmek için ne kullanacaklarını bildirirler. Yani kodunuzda Path niteliksiz tanımlayıcısını kullanıyorsanız, bu nitelikli türe çözüleceğini bildirmek için import java.nio.file.Path; kullanmalısınız. Bu arada, bir adı çözmenin tek yolu bu değil. İsimler, sınıf kalıtım yoluyla da çözülebilir, ör. devralınan üye sınıfının basit adını eşleştirirlerse.

Eğer bir import deyimi gerekmez adının atıfta bulunmadan örtülü bir tür kullanıyorsanız, bu lambda ifadeleri sınırlı değil, hatta özel bir Java 8 özellik değil. Örneğin. Bu Paths.get dönüş türü ve Files.walk bir parametre türü olduğu gibi

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

ile zaten başka bir deyişle, dolaylı Path türü kullanırken, java.nio.file.Path bir örneğini almak ve söz olmadan başka bir yöntem ile de geçirerek tür adı, dolayısıyla bir import'a ihtiyacınız yoktur. Ayrıca, rasgele sayı FileVisitOption örneğini kabul eden bir varargs yöntemini çağırıyorsunuz. Bu nedenle, kodunuz sıfır uzunluktaki FileVisitOption[] dizisini oluşturacak veolmaksızın Files.walk'a iletecektir. Gelişmiş tür çıkarımı ile, ismine atıfta bulunmadan bir tür kullanma olasılığının başka bir olasılığı vardır, örn. Araman: Yalnızca ismiyle bu tip atıfta olmadan varargs parametresi için sıfır uzunluğunda FileAttribute[] dizi yaratmak değildir

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

, ayrıca adıyla tip OpenOption atıfta olmadan HashSet<OpenOption> yaratıyor. Yani bu, ne de java.nio.file.attribute.FileAttribute ya da java.nio.file.OpenOption içeri aktarılmasını gerektirmez.


Yani alt çizgi bir import tipinin kullanımı bağlı değildir gerekip gerekmediğini, ama onun basit adıyla programa başvurmak (ve olmayan bir türü kullanmak için birden fazla yolu var olup olmadığını ismine bakarak).İkinci örneğinizde, printPath(Path passedFilePath) metodunuzdaki Path ismine atıfta bulunuyorsunuz; printPath(Object passedFilePath) olarak değiştirirseniz, her şey importjava.nio.file.Path olmadan yeniden çalışır.

2

Fark, ikinci örnekte, Path passedFilePath yerel değişkenini (bir yöntem parametresi olarak) bildirmenizdir. Bunu yaptığınızda, Path türünde java derleyicisine anlatmak için bir import gerekir, çünkü birden çok paket aynı ada sahip bir sınıfa sahip olabilir. List something değişkenini oluşturduğunuzda ve IDE'nin içe aktarmayı otomatik olarak oluşturduğundan, çoğu IDE'nin genellikle java.util.List veya java.awt.List anlamına gelip gelmediğini sorduğunu fark etmiş olabilirsiniz. Ayrıca, üçüncü bir seçenek olacak bir com.myorg.myproject.List kendi sınıfını oluşturabilirsiniz.

İlk örnekte filePath kesin türü Paths.get(...).forEach gerektirdiği türüne göre belirlenir, böylece size başvurmak class Path java derleyici anlatmak gerekmez. Eğer public void printPath(java.nio.file.Path passedFilePath) olarak yöntem imzası yeniden ne zaman

arada, ikinci örnekteki ithalat ihmal olabilir. Tam olarak nitelenmiş bir sınıf adı sağladığınızda, sınıf adının belirsiz olamayacağı için artık bir içe aktarmaya ihtiyacınız yoktur.

"Standart kitaplıkta yalnızca Path adında bir sınıf olduğunda neden içe aktarma veya tam nitelikli bir adama ihtiyacım var ve neden bu adın kendi sınıfım yok?" - Java'nın yeniden kullanılabilirlik için tasarlandığını unutmayın. kodunuzu başka projede kullanıldığında, bu proje böyle bir sınıf olabilir veya sahiptir ve sonra kod belirsiz olacağını 3. taraf kitaplığı kullanıyor olabilir.

+0

'Path' türünde bir' filePath 'değişkeni bildirir, sorusunun noktası budur. 'FilePath' ile lambda tanımı bu türden, ancak içe aktarma gerektirmez. Bu, Java 8'deki isteğe bağlı bir sözdizimidir. Bu, – Alex

+0

@Alex I değişkeninin üzerine 'Path' türünü yazmanızı gerektirmez. Cevap güncellendi. – Philipp

0

Bir değişken bildirdiğinizden ikinci örnekte bir içe aktarma kullanmanız gerekir.

Bu lambda ifadeleri ile hiçbir ilgisi yoktur. Anonim bir sınıf kullandıysan, aynı şey olurdu.

0

Sana göstermek için çalışıyoruz nokta bu gibi kolaylaştırılabilir düşünüyorum: Bu lambda Bir içe gerektirmez

Bu lambda Bir içe

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

gerektirir

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

Path.forEach(...) yana

bir Consumer<? super Path> Ben ikinci vaka-the-fly ? super Path yeni bir tür yaratıyor tahmin alır ve

İlgili konular