2013-10-10 5 views
2

Насколько я понимаю, каждый отдельный класс java скомпилирован из одного java-файла в один файл класса. (По крайней мере, пока не задействованы никакие внутренние классы.)Почему мне нужно указать classpath для компиляции java в класс?

Есть ли какая-либо техническая причина, почему javac нуждается в доступе к ссылочным классам для создания файла класса?

Действительно ли это только для проверки того, что выданные вызовы метода действительно действительны или действительно есть некоторые бит информации из ссылочных классов, которые необходимо интегрировать в сгенерированный файл класса?

Можете привести пример, в котором javac необходимо создать другой байт-код в зависимости от содержимого ссылочного класса?

Любая хорошая документация по этой теме?

+1

Это не просто проверка того, что методы invocations действительны - это знать, что такое тип возврата, и т. Д. Java - это статически типизированный язык, поэтому, когда вы ссылаетесь на тип кода, компилятор собирается проверить, что он существует и что вы используете его правильно. –

+1

И он также должен получить значения констант времени компиляции из указанных ссылочных классов. –

ответ

2

Это несколько субъективный вопрос, но мне он нравится.

Как вы писали правильно, одна большая причина заключается в раннем обнаружении ошибок. Если у компилятора нет файлов классов зависимых классов для ссылки, он должен предположить, что каждая внешняя ссылка правильная. Любые ошибки в них могут быть обнаружены только во время выполнения. Вы не хотите этого.

Здесь есть дыры. Зависимый класс может измениться позже. По этой причине и другим, доступное определение класса во время выполнения может отличаться от используемого во время компиляции, приводящего к ошибкам во время выполнения.

Но у нас лучше, чем у альтернативы.

В некоторых случаях элементы из ссылочных классов интегрированы в текущий блок компиляции, например «константы». Рассмотрим следующие два класса:

// File A1.java 
class A1 { 
    static final String s = "string"; // constant 
    static String s2 = "string2"; // not constant 
    static final int i = 5; // constant 
} 

// File A2.java 
class A2 { 
    public static void main(String args[]) { 
     System.out.println("A1.s: " + A1.s); 
     System.out.println("A1.s2: " + A1.s2); 
     System.out.println("A1.i: " + A1.i); 
    } 
} 

Обобщение этих двух, а затем изучить вывод javap -c -l -private A2 и обратите внимание на следующее:

  • Ссылки на A1.s и A1.i включают фактические значения
  • Если вы удалите ссылку на A1.s2 затем java A2 может быть выполнена даже если A1.class удален
+2

Другим случаем включения информации в класс является перегрузка метода. Перегрузка метода определяется во время компиляции и выпекается в файле класса. – Antimony

0

Я полагаю, вы ответили сам, потребности компилятора ссылку классов, чтобы проверить все ссылки методов правильно называется (с соответствующими аргументами), а также он может оптимизировать некоторые из вызовов методы, если он знает, что в этом методе

+0

Javac не делает оптимизацию. Или, по крайней мере, не так. – Antimony

+0

@ Anthimony вот почему я написал «can», также - вы уверены, что все компиляторы javac? (oracle, openjava, microsoft) –

+0

Я не знаю ни одного компилятора Java, который строит методы во время компиляции. Я предполагаю, что это будет нарушение спецификации языка, так как я уверен, что только константные выражения значений могут быть встроены (см. Ответ Miserable Variable). –

0

Вот Причина. Если вы вызываете метод x в библиотеке, как компилятор знает, что этот метод действительно существует? Как узнать тип возврата? Как узнать, сколько параметров вы проходите, правильно? Как он может знать, какие типы вы проходите, правильно?

В динамическом языке (например, javascript) это обнаружено во время выполнения, но недостатком этого является цикл обратной связи. Чем скорее вы обнаружите свою ошибку, тем лучше. Java статична, поэтому это требование к pathpath делает ваш цикл обратной связи короче.

+0

Это имеет смысл для проверки ошибок, но с единственной целью генерации байт-кода компилятору не нужно знать, действительно ли метод существует в этой библиотеке. – michas

+0

@michas, возможно, нет (я не уверен), но команда javac компилирует И обнаруживает такие ошибки. Он не мог сделать последнего без класса. –

0

Если я правильно понимаю комментарии Джона и Сурьмы в следующем случае, A2 должен компилироваться по-разному в зависимости от типа возврата в классе A1.

// File A1.java 
class A1 { 
    public ??? bar(){ 
     return null; 
    } 
} 

// File A2.java 
class A2 { 
    public static void main(String args[]) { 
     foo(A1.bar()); 
    } 
    private void foo(Integer x){ 
     System.out.println("1"); 
    } 
    private void foo(String x){ 
     System.out.println("2"); 
    } 
} 

Если я все правильно компилятор должен решить, относится ли вызов метода обув к первому или второму определению, и создавать различный байткод для класса А2 в зависимости от типа возвращаемого значения в классе А1.

Смежные вопросы