2015-05-29 11 views
11

Data la seguente struttura di directory:Come javac compilano automaticamente le dipendenze di una classe

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

Si supponga che i due file A.java e B.java contengono il codice seguente, rispettivamente:

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

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

Supponendo che il l'attuale directory è /top/wrk

Perché il comando javac -cp . pkg/A.java funziona correttamente lly anche se non abbiamo ancora compilato B.java?

Anche se la directory corrente è /top/wrk/pkg, il comando javac A.java funziona. Come mai?

+0

La risposta sta nel http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html#BHCCHDGH. Non c'è tempo per riprodurlo qui sotto forma di risposta, in breve, approssimativamente: Cerca anche i file sorgente nel classpath. – Marco13

+0

Non riesco a riprodurre questo. Non riesce a compilare sulla mia macchina. Sei sicuro che B non sia mai stato compilato? –

+0

È una cosa per Mac/Windows. Vedi la mia risposta modificata e ora (si spera) definitiva per maggiori dettagli. –

risposta

7

Perché il comando javac -cp. pkg/A.java lavoro con successo, anche se non abbiamo ancora compilato B.java

Quando si compila A.java, il compilatore compilare B.java pure poiché sia ​​A.java e B.java sono nello stesso pacchetto. Funzionerà anche se B.java era in un altro pacchetto da A.java (fornito B è pubblico) purché entrambi i pacchetti siano presenti nella directory wrk e si compili A.java dalla directory wrk.

Dal Oracle documentation per javac:

Se l'opzione -sourcepath non è specificata, il percorso di classe utente viene cercato anche per i file di origine.

Dal Oracle document per CLASSPATH

Il valore predefinito del percorso di classe è ""

Se non è stata impostata una CLASSPATH, verrà in default a .. Successivamente, lo sourcepath sarà anche . poiché il valore predefinito sourcepath è lo stesso di CLASSPATH. È possibile confermare che l'identificativo predefinito è impostato su . compilando A.java utilizzando javac -verbose -g pkg\A.java.Si noti che il compilatore è alla ricerca nella directory corrente per .java file:

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

Per verificare che l'sourcepath è impostato su CLASSPATH, si può provare a cambiare il CLASSPATH utilizzando l'opzione -cp compilando A.java utilizzando javac -cp C:\ -verbose -g pkg\A.java. A.java non verrà compilato questa volta poiché è stato sovrascritto lo CLASSPATH su C:\ ed è per questo che verrà impostato anche sourcepath. Questa è l'uscita:

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

Anche se la directory corrente è/top/wrk/pkg allora il comando javac A.java funziona. Come mai?

Questo non funziona indipendentemente dal fatto che è presente in B.classpkg

Diniego: Non posso che confermare questo comportamento su Windows, ma dubito fortemente che dovrebbe essere diverso su altri sistemi operativi.

+0

Potresti fornire un collegamento ai documenti javac che specifica questo comportamento? Non sono riuscito a trovare altro se non specificando -significativo. –

+0

@PhilAnderson Vedi la mia modifica. È probabile che tu abbia qualche valore impostato in 'CLASSPATH', quindi il tuo' sourcepath' non è impostato su '.' – CKing

+0

Grazie Chetan, ma non ho nulla nel CLASSPATH. –

1

Il compilatore deve trovare e compilare correttamente una sorgente per B, o trovare una classe .class per B anche se è solo un'importazione. Al contrario del caricamento, che viene eseguito in modo dinamico.

Cerca nella directory di output e vedrai che anche B è stato compilato. Verrà compilato anche se in un pacchetto diverso, ma sarà necessario renderlo pubblico per fare riferimento a A.

1

Dal Oracle javac docs ...

Se si imposta l'opzione -sourcepath, quindi il compilatore ricerche il percorso indicato per i file di origine. In caso contrario, il compilatore cerca il percorso della classe utente per entrambi i file di classe e i file di origine. Su Windows, l'opzione -sourcepath sembra essere impostata di default e il tuo comando funziona.

Sul mio Mac, però, non riesce e dà seguente messaggio ...

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

Per farlo sembrare automaticamente e compilare file sorgenti di dipendenze, si avrebbe bisogno di utilizzare l'opzione -sourcepath. per esempio ...

javac -sourcepath ./* A.java
+0

Vedi la mia risposta. Credo che l'accezione predefinita per 'CLASSPATH' e che sia probabile che tu abbia impostato' CLASSPATH' sul tuo computer. – CKing

Problemi correlati