#java #cpp
Closed. This question is opinion-based. It is not currently accepting answers. Want to improve this question? Update the question so it can be answered with facts and citations by editing this post. Closed 1 год назад. В общем обрисую ситуацию. На протяжении последних восьми лет я работал с C и C++. За это время я успел поработать в нескольких компаниях, в том числе в международных. Делал много чего - начиная от встраиваемых систем, заканчивая игрульками и прошивками для IP-телефонов. Почувствовал, так сказать, на собственной шкуре все проблемы плюсов. Кто бы что не говорил и не доказывал, я абсолютно точно убедился в том, что хорошего кода на C++ не бывает, его просто не существует. Весь код - как старый, так и новый, написанный на C++14/17, - это бесконечный клубок противоречий, неопределенных поведений и костылей. С языком С проблем гораздо меньше, его я использую как основной, особенно при разработке библиотек и проектов, которые необходимо поддерживать на протяжении многих последующих лет, возможно другими людьми. Пожалуй, это лучший выбор для всего, что не содержит интерфейсов/графики. Основная проблема C - крайне малое количество библиотек для работы с GUI и графикой. Да, писать на всяких там WinAPI можно, в теории, но только под Windows. При поддержке нескольких платформ возникает боль. Знаю о существовании GTK+, имел с ним дело, надежд он не оправдал. Его проблема заключается в том, что разработчики постоянно ломают обратную совместимость, из-за чего через год-два ваш проект смело можно выкинуть в мусорное ведро, потому что пофиксить несколько сотен тысяч строк кода из-за поломанного API/ABI невозможно, не переписав все с нуля. В общем, задумался о том, что изучать дуэтом к C, чтобы заполнить дефицит возможностей. C# однозначно не подходит по целому ряду причин. Хочу кросплатформенности, адекватную объектную модель и стабильность на протяжении долгого времени, желательно - десятилетий. Меня заинтересовала Java, и у меня есть несколько вопросов к тем, кто на этом языке собаку съел. 1) Хотелось бы, чтобы знающие люди в общих чертах обрисовали то, что именно из себя представляет объектная модель Java. Да, я знаю, что такое байт-код, виртуальная машина и прочее. Но в моем мозгу очень прочно засела объектная модель С++... Да, я знаю о существовании книг, но мне бы хотелось понять общую суть не через десять лет практики, а несколько раньше. 2) Какие проблемы чаще всего возникают при разработке на Java? Я имею в виду фундаментальные проблемы, от которых никуда не деться. Например, фундаментальная проблема C++ - его внутренняя противоречивость и несогласованность, которая лишь растет с течением времени. Эту противоречивость не может устранить даже комитет по стандартизации, на протяжении вот уже двадцати лет. Потому, что даже комитет не понимает этот язык. 3) Действительно ли Java так прожорлива и медлительна, как ее рисуют, или нет? 4) Какое место в разработке на Java занимают танцы с бубном вокруг сборщика мусора и jit-компиляции? 5) Действительно ли исключения в Java - это круто, а не боль, как в C++? 6) Насколько язык страдает от неопределенного поведения? Например, в C++ разыменование нулевого указателя запросто может привести к тому, что в совсем другой части проекта шаблон развернется в код запуска ядерных ракет. Я лично несколько раз видел, как переполнение int приводит к форматированию жесткого диска, и это ни разу не шутка. Возможно ли такое в Java?
Ответы
Ответ 1
по вопросам кратко Объектная модель она и в Африке объектная модель. Три кита ООП никто не отменял. Но! В жаве все методы виртуальны в отличии от функций-членов с++. И виртуальность работает почти всегда ожидаемо (достаточно вспомнить, как в с++ в конструкторе попытаться вызвать виртуальную функцию). В конструкторах виртуальные методы работают отлично. Также в java нет множественного наследования. Поэтому, проблему ромбовидного наследования получить тяжело. Проблемы в java как и в других языках хватает. Создаешь много мелких объектов часто и густо - GC дышит в спину. Фундаментальная проблема java - это то, что все должно быть объект, но не совсем. к примеру, есть обычный int и есть Integer. И это понятно, сделано в целях оптимизации, но... они себя иногда ведут очень неожиданно для с++ разработчика. В том же ruby объектность как то лучше. Также в жава отсутствуют деструкторы (да, есть финализаторы, но это совсем другая штука). Поэтому популярная штука как RAII стает невозможной. И тут конечно же возразят - GC придет и порядок наведет. Но... если к примеру открывать много дескрипторов в цикле (краулер) и не закрывать их вручную - можно напороться на то, что дескрипторы закончатся, приложение потупит, GC почистит и снова работа. И спустя какое то время нормальное приложение превращается в с подобный код. Для плюсового разработчика это боль. 3) Действительно ли Java так прожорлива и медлительна, как ее рисуют, или нет? и да, и нет. Можно и на си написать такой код, что сожрет все и тупить будет. Поэтому, тут больше зависит от программиста. Но, у меня был случай, когда приложение на жаве выжирало 18 гигов памяти за несколько часов и не хотело отпускать. Переписав на плюсы, получил большую производительность и память не выходила и за гиг (приложение - обработка метаинформации с картинок). 4) Какое место в разработке на Java занимают танцы с бубном вокруг сборщика мусора и jit-компиляции? священное. Многие верят, что ручной запуск GC что то да сделает. 5) Действительно ли исключения в Java - это круто, а не боль, как в C++? Возможно, лет 20 назад так и было. Но сейчас точно не так. Говорят, что в жаве нет утечек памяти. Но они там есть, просто их никто не называет утечками памяти. Их называют "где то повисла ссылка". Я несколько лет программировал на java и это было тяжело. Шаблонов нет (есть дженерики, но это больше похоже на костыль, когда компилятор немного проверит, а внутрях обычный void*.), множественное наследование похоже потихонечку завозят через чудные интерфейсы, в котором могут быть дефолтные реализации...Ответ 2
1) Концептуально объектная модель Java от С++ отличается 2-мя фундаментальными вещами: В Java нет множественного наследования Все функции/методы в Java виртуальные (кроме статических конечно) 2) На вкус и цвет - товарищей нет 3) Вранье 4) Никакого места не занимают - это удел маргиналов, нормальный девелопер не концентируется на таких вещах от слова совсем 5) Ну я бы так не сказал, что это очень круто - приходится жить с этим, это не боль, это просто такие условия жизни, надо привыкать 6) Невозможно, хотя наверняка что-то подобное можно придуматьОтвет 3
Чем хорош С++ так это тем, что в нем сделано все так, как должно быть сделано. Множественное наследование например. Если теоретически множественное наследование возможно, то рано или поздно оно понадобится. Шаблоны например. Опять же рано или поздно шаблоны понадобятся. (Еще бы в С++ добавить рефлексию и совсем было бы хорошо, но это так, реплика в сторону.) Что касается форматирования винта при переполнении int, и разъименовывания нулевого указателя, то можно и нужно пользоваться умными и не очень обертками для указателей. Все остальное, что не есть С++, это, как ни крути, Бейсик. Рано или поздно перестает хватать средств языка и начинаешь думать: "вот черт, множественным наследованием это сделать в 1000 раз проще" или "вот черт, шаблонами это сделать в 1000 раз проще". Делал много чего - начиная от встраиваемых систем, заканчивая игрульками и прошивками для IP-телефонов. Кстати, на Java о встраиваемых системах и прошивках для IP-телефонов придется забыть. :-) А это значит, что придется держать в голове и Java и (о боже, какое унижение) все тот же С/С++. Знаю о существовании GTK+, имел с ним дело, надежд он не оправдал. Его проблема заключается в том, что разработчики постоянно ломают обратную совместимость, из-за чего через год-два ваш проект смело можно выкинуть в мусорное ведро, потому что пофиксить несколько сотен тысяч строк кода из-за поломанного API/ABI невозможно, не переписав все с нуля. Обратная совместимость очень важна и, тем не менее, она постоянно ломалась, ломается и будет ломаться. Выход состоит в том, что старые проекты доделываются и сопровождаются на старых версиях библиотек, а новые проекты начинаются на новых версиях библиотек. UPD1: Про ip-телефоны - в джаве в jdk есть native методы, их можно самим писать? – Anton Sorokin 5 минут назад Конечно, IP-телефоны разные бывают. Возможно, даже есть модели с линуксом внутри. Но ПРОШИВКА для IP-телефона это нечто, напоминающее БИОС для x86. Эта прошивка стартует из ROM задолго до запуска всех линуксов и тем более задолго до запуска JVM. Так что написать ПРОШИВКУ для IP-телефона на Java вряд-ли получится. UPD2: Вот достаточно подробное описание проблемы с GTK+: vasilisc.com/gtk-developers-destroying-linux-desktop В текущей ситуации с этой библиотекой нет никакой надежды на улучшение или хотя бы не ухудшение ситуации. Использование этой библиотеки даже для своих проектов - очень плохая идея. А для коммерческих решений - это просто суицид. Если разработчики какой-то библиотеки начали чудить, то надо просто перейти на другую библиотеку. Собственно язык тут не при чем. Да и где гарантия, что разработчики Java не начнут чудить? Например, по слухам, теперь для Java-9 нет версии 32 бита, а только 64 бита. Это потеря обратной совместимости? Несомненно! А разработчики говорят - "мы сосредоточены на будущем, а для 32 битных систем используйте Java-8". И никуда не дернешься, даже сменить библиотеку не получится. Так что панацеи нет, есть только более или менее рынок, в котором можно выбрать более или менее адекватное решение. И в мире Java рынка меньше, чем в мире С/С++.Ответ 4
3) Считается, что нормально написанный Java-код не уступает по скорости С++(а кто-то говорит, что даже быстрее). 4) В Enterprise приложениях вам может потребоваться настроить JVM, сборщик мусора(где-то даже была статья на хабре, как gc все ломал). Но в обычных приложениях все отлично работает на автоматике. 6) Вроде как не страдает, JVM все проверяет(отчасти благодаря этому и возникли слухи про ее медлительность), и такого не случиться. Про отличия Java от С++ - в Интернете есть куча хороших статей, разъясняющих эти отличия. Например, CodeNet. Два основных пункта: Указатели Указатели или адреса в памяти - наиболее мощная и наиболее опасная черта C++. Причиной большинства ошибок в сегодняшнем коде является именно неправильная работа с указателями. Например, одна из типичных ошибок - просчитаться на единицу в размере массива и испортить содержимое ячейки памяти, расположенной вслед за ним. Хотя в Java дескрипторы объектов и реализованы в виде указателей, в ней отсутствуют возможности работать непосредственно с указателями. Вы не можете преобразовать целое число в указатель, а также обратиться к произвольному адресу памяти. Распределение памяти В строю опасных качеств C++ рука об руку с указателями идет распределение памяти. Распределение памяти в С, а значит и в C++, опирается на инь и янь ненадежного кода - на вызовы библиотечных функций malloc() и free().Если вы вызовете free() с указателем на блок памяти, который вы уже освободили ранее, или с указателем, память для которого никогда не выделялась - готовьтесь к худшему. Обратная проблема, когда вы просто забываете вызвать free(), чтобы освободить ненужный больше блок памяти, гораздо более коварна. "Утечка памяти" (memory leak) приводит к постепенному замедлению работы программы по мере того, как системе виртуальной памяти приходится сбрасывать на диск неиспользуемые страницы с мусором. И, наконец, когда все системные ресурсы исчерпаны, программа неожиданно аварийно завершается, а вы начинаете ломать голову над этой проблемой. В C++ добавлены два оператора - new и delete, которые используются во многом аналогично функциям malloc() и free(). Программист по-прежнему отвечает за то, чтобы каждый неиспользуемый объект, созданный с помощью оператора new, был уничтожен оператором delete. в Java нет функций malloc() , free(). Поскольку в ней каждая сложная структура данных - это объект, память под такие структуры резервируется в куче (heap) с помощью оператора new. Реальные адреса памяти, выделенные этому объекту, могут изменяться во время работы программы, но вам не нужно об этом беспокоиться. Вам даже не придется вызывать free () или delete, поскольку Java - система с так называемым сборщиком мусора. Сборщик мусора запускается каждый раз, когда система простаивает, либо когда Java не может удовлетворить запрос на выделение памяти. И конечно, компиляция в байт-код: Java-код компилируется в промежуточный код, который в дальнейшем интерпретируется или компилируется, тогда как C++ изначально ориентирован на компиляцию в машинный код заданной платформы (хотя, теоретически, ничто не мешает создавать для C++ трансляторы в промежуточный код). Это уже определяет разницу в сферах применения языков: Java вряд ли может быть использована при написании таких специфических программ, как драйверы устройств или низкоуровневые системные утилиты. Механизм исполнения Java делает программы, даже откомпилированные (в байт-код) полностью переносимыми. Стандартное окружение и среда исполнения позволяют выполнять программы на Java на любой аппаратной платформе и в любой ОС, без каких-либо изменений, усилия по портированию программ минимальны (при соблюдении рекомендаций по созданию переносимых программ — и вовсе нулевые). Ценой переносимости становится потеря эффективности — работа среды исполнения приводит к дополнительным накладным расходам.
Комментариев нет:
Отправить комментарий