Чому Java не дозволяє використовувати заголовки, як у C ++


18

У мене є питання, на яке я не знайшов відповіді, за винятком наступної відповіді, яка не відповідає моїм вимогам:

"Тому що Джеймс Гослінг не хотів"

Я знаю, що Java може мати інтерфейси (лише чисті віртуальні функції, без атрибутів), але це не зовсім те саме, що визначення класів.


14
Чому ви їх хочете?

19
Щоб мати більше часу для
боїв

6
Я вважаю, що більшість розробників C ++ хотіли б позбутися 40-річного механізму заміни тексту, який дублює сотні kLoC для кожного файлу cpp, що призводить до тривалого часу компіляції C ++. Насправді належну модульну систему розглядали для C ++ 11, але її відмовили через брак часу. Я гадаю, що це знову з'явиться.
sbi

Я гадаю, що це знову з'явиться. Насправді WG21 (робоча група ISO C ++) має дослідницьку групу виключно з метою оцінки / розробки концепції «модулів» далі: SG2 «Модулі». Шкода, що поточний стан спокою .
Макс Трукса

Відповіді:


46

Наступна відповідь, яка не відповідає моїм вимогам: "Тому що Джеймс Гослінг цього не хотів".

Хоча це правильна відповідь. Команда з мовної розробки (Гослінг, Шерідан, Наутон, пізніше Білл Джой, Кен Арнольд та ін.) Вирішила, що заголовки викликали більше проблем, ніж вирішили . Тож вони розробили їх і продемонстрували, що вони можуть створити ідеально корисну мову без потреби в них.

З розділу 2.2.1 білої книги "Мова Java" :

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

Надмірні визначення, зберігання файлів синхронізовано, суперечливі визначення, приховані визначення - жодне з них не відбувається в Java, оскільки у вас немає заголовків. Якщо ви хочете побачити чітке визначення класу, ви можете генерувати його безпосередньо з файлу .java - наприклад, більшість IDE покажуть вам структуру класу на бічній панелі, що означає те саме.


6
Дякуємо за вашу відповідь, тоді заголовки викликали більше проблем через це: надлишкові визначення, синхронізація файлів, суперечливі визначення, приховані визначення. Це тому не було дозволено?
Etienne Noël

2
Зауважте, що про наступні засідання комітетів C ++ багато розмовляють, оскільки вони розглядають нову систему "Модуль", яка була б простішою та ефективнішою системою, ніж включаючи (з деякою схожістю з пакетами java, C # тощо), але все одно ретро -сумісний з включає. Це означає, що кращу систему компіляції можна, принаймні, теоретично використовувати, щоб зробити компіляцію C ++ кращою / ефективнішою. Думаю, Gosling мав рацію, і C ++ повинен знайти спосіб виправити систему включення.
Клаїм

5
Це не зовсім доцільно використовувати. Системи збірки Java не можуть визначити, які файли потрібно перекомпілювати після зміни коду. IDE визначатиме, які файли потребують зміни коду, а не які потребують перекомпіляції. Якщо підпис методу змінюється, але зміна сумісна з кодом зі старим підписом (наприклад, зміна типу аргументу з float на подвійний), для запобігання MethodNotFoundException потрібна чиста збірка.
кевін клайн

1
@kevin: Однак зазвичай можна просто відновити все без зайвих витрат. На відміну від C ++ (але, як і майже будь-яка інша мова, що складається на Землі), Java просто не займе багато часу, щоб скласти, що часткова компіляція є дуже вагомою оптимізацією вашого робочого процесу розвитку.
Стипендіати доналу

1
@Donal: Це правда, що Java збирається досить швидко, але я ненавиджу здогадуватися, чи варто мені робити повну перекомпіляцію. Збірки повинні працювати щоразу .
кевін клайн

16

В C ++ немає реальної потреби мати визначення класів та декларації в окремих файлах. Це просто означає, що ви могли, принаймні ще за C днів, провести аналіз в одному скануванні коду зверху внизу. На машинах без зберігання довільного доступу це було великою справою!

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

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


Я це знаю, але принаймні ви можете це робити на C ++, а не на Java; це був мій головний запит. Дякую за відповідь.
Етьєн Ноель

14

Через принцип DRY . У Java інформація, необхідна для використання класів у пакеті (або класі), міститься у файлі .class. Створення окремих файлів заголовків, що містять однакову інформацію, передбачає повторення її у двох місцях.


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

6

У кожній мові - два етапи створення кінцевого бінарного коду - компіляція та зв’язування (звичайно, завантаження є, але це не має великого впливу тут). На момент складання потрібно лише поставити гачки (специфікацію функцій, які будуть називатися) у відповідне місце. Linker насправді приєднується до них, коли доступні обидва реальні коди. Поки немає різниці між C ++ та Java.

Там є , однак, потреба в C ++ , щоб мати декларацію і визначення окремої. Якщо ви зберігаєте реалізацію в заголовку, і якщо файл заголовка змінюється, код, який пов'язаний з ним, потрібно перекомпілювати. Де як би дефініція знаходиться в окремому файлі, код потрібно лише повторно пов’язати.

Зрозумійте, що у C ++ є можливість мати статичне посилання, що означає, що об'єктний код фіксується разом із викликаючим додатком. Зверніть увагу, що і в C, і в C ++ не можна мати програмування в заголовковому файлі або навіть робити #include. це означає лише, що вам потрібно потурбуватися про те, як відбувається посилання з цими об’єктними файлами.

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

Дивіться це і це


4

Ефективно, інтерфейси та включення є заголовками; Отже, визначення ідентичні двійковим файлам і не можуть бути синхронізовані. Це одне з найкращих дизайнерських рішень на Java, але це незначне роздратування тим, що немає можливості поєднати ці декларації для компактності та послідовності.


1

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

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


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