2015-05-29 18 views
11

otrzymuje następujące struktury katalogów:Jak javac automatycznie kompilacji zależności od klasy

/top 
    |--- wrk 
      |--- pkg 
        |--- A.java 
        |--- B.java 

Załóżmy, że dwa pliki A.java i B.java zawierać następujący kod odpowiednio:

// Filename: A.java 
package pkg; 
class A { B b; } 

// Filename: B.java 
package pkg; 
class B {...} 

Zakładając, że bieżący katalog to /top/wrk

Dlaczego polecenie javac -cp . pkg/A.java działa pomyślnie lly, mimo że jeszcze nie skompilowaliśmy B.java?

Również jeśli bieżącym katalogiem jest /top/wrk/pkg, działa polecenie javac A.java. Jak to?

+0

Odpowiedź leży w http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html#BHCCHDGH. Nie ma czasu na odtworzenie tego tutaj w formie odpowiedzi, krótko mówiąc, z grubsza: szuka również plików źródłowych w ścieżce klas. – Marco13

+0

Nie mogę tego odtworzyć. Nie można go skompilować na moim komputerze. Czy jesteś pewien, że B nigdy nie został skompilowany? –

+0

To sprawa Mac/Windows. Zobacz moją zredagowaną i teraz (mam nadzieję) ostateczną odpowiedź, aby uzyskać więcej szczegółów. –

Odpowiedz

7

Dlaczego polecenie javac -cp. pkg/A.java praca powodzeniem choć jeszcze nie opracowano B.java

Podczas kompilowania A.java, kompilator skompiluje B.java jak dobrze ponieważ zarówno A.java i B.java są w tym samym opakowaniu. To zadziała nawet, jeśli B.java był w innym pakiecie niż A.java (pod warunkiem, że oba pakiety są obecne w katalogu wrk, a kompilujesz A.java z katalogu.

Z Oracle documentation dla javac:

Jeśli opcja -sourcepath nie jest określony, ścieżka klasy użytkownika jest również szukał plików źródłowych.

Z Oracle document dla CLASSPATH

wartość domyślna ścieżce klasy jest ""

Jeśli nie ustawiono wartości CLASSPATH, zostanie ona domyślnie ustawiona na .. Następnie, sourcepath będzie również ., ponieważ domyślnie sourcepath jest taki sam jak CLASSPATH. Możesz potwierdzić, że domyślna ścieżka źródłowa jest ustawiona na ., kompilując A.java, używając javac -verbose -g pkg\A.java.Należy zauważyć, że kompilator szuka w bieżącym katalogu dla .java plików:

[parsing started pkg\A.java] [parsing completed 29ms] [search path for source files: [.]]

Aby potwierdzić, że sourcepath jest ustawiony na CLASSPATH, można spróbować zmienić CLASSPATH używając opcji -cp kompilując A.java użyciu javac -cp C:\ -verbose -g pkg\A.java. A.java nie skompiluje się tym razem, ponieważ nadpisałeś CLASSPATH do C:\ i domyślnie jest to również sourcepath. Jest to wyjście:

[parsing started pkg\A.java] [parsing completed 26ms] [search path for source files: [C:\]] pkg\A.java:3: cannot find symbol symbol : class B

Także jeśli bieżący katalog to/top/wrk/pkg następnie javac polecenia A.java działa. Jak to?

To nie będzie działać niezależnie od tego, czy B.class jest obecny w pkg

Uwaga: Mogę tylko potwierdzić to zachowanie w systemie Windows, ale wątpię, że powinno być inaczej w innych systemach operacyjnych.

+0

Czy możesz podać link do dokumentacji javac, która określa to zachowanie? Nie mogłem znaleźć niczego innego niż poprzez określenie -sourcepath. –

+0

@PhilAnderson Zobacz moją edycję. Prawdopodobnie masz jakąś wartość ustawioną w 'CLASSPATH', więc twoja' sourcepath' nie jest domyślna '.' – CKing

+0

Dzięki Chetan, ale nie mam nic w CLASSPATH. –

1

Kompilator musi albo znaleźć i z powodzeniem skompilować źródło dla B, albo znaleźć .class dla B, nawet jeśli jest to tylko import. W przeciwieństwie do ładowania, które odbywa się dynamicznie.

Sprawdź w swoim katalogu wyjściowym, a zobaczysz, że B został również skompilowany. Zostanie on skompilowany, nawet jeśli w innym pakiecie, ale musisz go upublicznić, aby odwołać się do niego od A.

1

Z Oracle javac docs ...

Jeśli ustawisz opcję -sourcepath, wówczas kompilator przeszukuje wskazaną ścieżkę do plików źródłowych się. W przeciwnym razie kompilator przeszukuje ścieżkę klasy użytkownika zarówno dla plików klas, jak i plików źródłowych. W systemie Windows opcja -sourcepath wydaje się być domyślnie ustawiona, a polecenie działa.

Na moim Macu jednak, że nie powiedzie się i daje następujący komunikat ...

A.java:5: error: cannot find symbol 
    B b; 
    ^
    symbol: class B 
    location: class A 
1 error 

Aby dostać to automatycznie wyszuka i kompilacji plików źródłowych zależności, trzeba by użyć opcji -sourcepath. np ...

javac -sourcepath ./* A.java
+0

Zobacz moją odpowiedź. Wierzę, że ścieżka źródłowa domyślnie "CLASSPATH" i jest szansa, że ​​masz 'CLASSPATH' ustawiony na twoim komputerze. – CKing

Powiązane problemy