Почему Java не позволяет использовать заголовки, как в C ++


18

У меня есть вопрос, на который я не нашел ответа, кроме следующего ответа, который не соответствует моим требованиям:

«Потому что Джеймс Гослинг не хотел»

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


14
Какова причина, почему вы хотите их?

19
Чтобы было больше времени для боя на мечах;)
dan04

6
Я полагаю, что большинство разработчиков C ++ хотели бы избавиться от 40-летнего механизма замены текста, дублирующего сотни kLoC для каждого файла cpp, что привело к длительному времени компиляции C ++. Фактически для C ++ 11 была предусмотрена надлежащая модульная система, но она упала из-за нехватки времени. Я полагаю, что это придет снова, хотя.
ВОО

Я полагаю, что это придет снова, хотя. Фактически, WG21 (рабочая группа по ISO C ++) имеет исследовательскую группу исключительно с целью дальнейшей оценки / разработки концепции «модулей»: ИК2 «Модули». Жаль, что его текущий статус неактивен .
Макс Трукса

Ответы:


46

Следующий ответ, который не соответствует моим требованиям: «Потому что Джеймс Гослинг не хотел».

Это правильный ответ, хотя. Команда разработчиков языка (Гослинг, Шеридан, Нотон, позже Билл Джой, Кен Арнольд и т. Д.) Решила, что заголовки вызывают больше проблем, чем решают . Поэтому они разработали их и продемонстрировали, что могут создать совершенно полезный язык без необходимости в них.

Из Раздела 2.2.1 Технического документа Языковой Среды Java :

Исходный код, написанный на Java, прост. Здесь нет препроцессора, нет #define и связанных с ним возможностей, нет typedef и отсутствуют эти функции, больше нет необходимости в заголовочных файлах. Вместо заголовочных файлов исходные файлы языка Java предоставляют определения других классов и их методов.

Избыточные определения, синхронизация файлов, конфликтующие определения, скрытые определения - все это не происходит в Java, потому что у вас нет заголовков. Если вы хотите увидеть простое определение класса, вы можете сгенерировать его непосредственно из файла .java - например, большинство IDE покажут вам структуру класса на боковой панели, что равносильно тому же.


6
Спасибо за ваш ответ, поэтому заголовки вызвали больше проблем из-за этого: избыточные определения, синхронизация файлов, конфликтующие определения, скрытые определения. Вот почему это было запрещено?
Этьен Ноэль

2
Обратите внимание, что много разговоров о следующих собраниях C ++ Commitee, потому что они рассмотрят новую систему "Модуль", которая будет более простой и более эффективной системой, чем в том числе (с некоторыми сходствами с пакетами java, C # и т. Д.), Но все еще ретро -совместимо с включает. Это означает, что лучшая система компиляции может, по крайней мере, теоретически, быть использована для улучшения / повышения эффективности компиляции C ++. Полагаю, Гослинг был прав, и С ++ все равно должен найти способ исправить систему включения.
Klaim

5
Это не совсем удобно. Системы сборки Java не могут определить, какие файлы должны быть перекомпилированы после изменения кода. Среда IDE будет определять, какие файлы требуют изменения кода, но не какие требуют перекомпиляции. Если сигнатура метода изменяется, но это изменение совместимо по коду со старой сигнатурой (например, изменение типа аргумента с плавающего на двойной), требуется чистая сборка, чтобы предотвратить исключение MethodNotFoundException.
Кевин Клайн

1
@kevin: Однако, как правило, можно просто восстановить все без особых затрат. В отличие от C ++ (но, как и почти любой другой скомпилированный язык на земле), Java просто не занимает много времени, чтобы скомпилировать эту частичную компиляцию, что является очень полезной оптимизацией вашего рабочего процесса разработки.
Donal Fellows

1
@Donal: Это правда, что Java компилируется довольно быстро, но я ненавижу гадать, стоит ли мне делать полную перекомпиляцию. Сборки должны просто работать, каждый раз.
Кевин Клайн

16

В C ++ нет реальной необходимости иметь определения классов и объявления в отдельных файлах. Это просто означает, что вы могли бы, по крайней мере, в дни C, выполнить анализ в одном сканировании кода сверху вниз. На машинах без хранилища с произвольным доступом это было большое дело!

Наличие заголовков также позволило вам опубликовать интерфейс для вашей библиотеки кода, предоставив заголовок без необходимости раскрывать исходный код. К сожалению, в C ++ вы также должны раскрывать закрытые члены данных, что привело к таким решениям, как ужас pimpl .

Были попытки создать среду C ++, в которой все было бы сохранено в структуре типа базы данных, и там нет файлов, но она не завоевала популярность.


Я знаю это, но по крайней мере вы можете сделать это на C ++, а не на Java; это был мой главный запрос. Спасибо за ответ.
Этьен Ноэль

14

Из-за принципа СУХОЙ . В Java информация, необходимая для использования классов в пакете (или классе), содержится в файле .class. Создание отдельных заголовочных файлов, содержащих одинаковую информацию, потребует повторения этого в двух местах.


к сожалению, вы часто хотите повторить это - подумайте о файлах wsdl, idl и т. д. Один описывает интерфейс, который вы можете использовать, а другой файл содержит реализацию. Заголовки C ++ являются (плохими) определениями интерфейса.
gbjbaanb

6

На каждом языке - есть два этапа для создания окончательного двоичного кода - компиляция и компоновка (конечно, есть загрузка, но это не имеет большого влияния здесь). Во время компиляции нужно только поставить хуки (спецификацию функций, которые будут вызываться) в соответствующем месте. Линкер фактически присоединяется к ним, когда доступен как реальный код. Пока что нет никакой разницы между C ++ и Java.

Там является , однако, потребность в C ++ , чтобы иметь декларацию и определение отдельной. Если вы сохраняете реализацию в заголовке и если файл заголовка изменяется, код, связанный с ним, должен быть перекомпилирован. Где, как будто определение находится в отдельном файле, код нужно только повторно связать.

Поймите, что в C ++ есть опция статического связывания, которая подразумевает, что объектный код фиксируется вместе с вызывающим приложением. Обратите внимание, что как в C, так и в C ++, недопустимо программирование в заголовочном файле или даже #include. это только означает, что вам нужно беспокоиться о том, как происходит связывание с этими объектными файлами.

Ситуация в Java очень отличается. Каждый файл класса скомпилирован с файлом .class. Действительно, необходимость компиляции функции класса вызывающего, которая служит разделом заголовка в файле .class. Однако в Java окончательное связывание выполняется только внутри среды выполнения (виртуальной машины) только с учетом этой спецификации байтового кода файла класса.

Смотрите это и это


4

Эффективно интерфейсы и включает в себя заголовки; поэтому определения идентичны двоичным файлам и не могут быть несогласованными. Это одно из лучших проектных решений в Java, но немного досадно, что нет способа объединить эти декларации для компактности и согласованности.


1

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

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


1
Я полагаю, вы могли бы сохранить интерфейсы в общем проекте, а затем реализовать их в независимых проектах
Александр Миллс,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.