Меню сайта

Урок 2. Отличия Java от C++

В большинстве книг по C++ вы найдете такое же описаниедостоинств объектно-ориентированного программирования и доказательства того, чтоэто — очередная ступень в развитии индустрии программирования. В чем же беда C++и почему была создана Java?

Фактически, большинство архитектурных решений, принятых присоздании Java, было продиктовано желанием предоставить синтаксис, сходный с С иC++. В Java используются практически идентичные соглашения для объявленияпеременных, передачи параметров, операторов и для управления потоком выполнениемкода. В Java добавлены все хорошие черты C++, но исключены недостаткипоследнего.

Глобальные переменные

В старые добрые времена Фортрана, когда «настоящие мужчины” писали наассемблере, а программы хранились на перфокартах, главным инструментом впрограммировании были глобальные переменные. С перенял эту особенность инесколько ее усовершенствовал — программисту приходилось по крайней мереобъявлять тип глобальной переменной. Конечно же, при использовании глобальныхпеременных проблема состояла в том, что любая функция могла привести кширокомасштабным побочным эффектам, изменив глобальное состояние системы.

В Java единственным глобальным пространством имен являетсяклассовая иерархия. В этом языке просто невозможно создать глобальнуюпеременную, не принадлежащую ни одному из классов.

Goto

Другая не слишком хорошая конструкция традиционных языковпрограммирования — оператор goto, предназначенный для передачи управления. Всемнам на первых занятиях по программированию говорили, что можно обойтись безэтого оператора, ухудшающего структуру программы иделающего ее неудобочитаемой. Дотого, как в C++ появился механизм работы с исключениями, goto активноиспользовался для выхода из циклов в исключительных ситуациях.

В Java оператора goto нет. В ней есть зарезервированноеключевое слово goto, но это сделано лишь во избежание возможной путаницы — длятого, чтобы удержать программистов от его использования. Зато в Java естьоператоры continue и break с меткой, восполняющие отсутствие goto в техединственных случаях, когда использование последнего было бы оправдано. А мощныйхорошо определенный встроенный в Java механизм исключений делает ненужнымиспользование goto во всех остальных ситуациях.

Указатели

Указатели или адреса в памяти — наиболее мощная и наиболее опасная черта C++.Причиной большинства ошибок в сегодняшнем коде является именно неправильнаяработа с указателями. Например, одна из типичных ошибок — просчитаться наединицу в размере массива и испортить содержимое ячейки памяти, расположеннойвслед за ним.

Хотя в Java дескрипторы объектов и реализованы в виде указателей, в нейотсутствуют возможности работать непосредственно с указателями. Вы не можетепреобразовать целое число в указатель, а также обратиться к произвольному адресупамяти.

Распределение памяти

В строю опасных качеств C++ рука об руку с указателями идетраспределение памяти. Распределение памяти в С, а значит и в C++, опирается наинь и янь ненадежного кода — на вызовы библиотечных функций malloc() иfree().Если вы вызовете free() с указателем на блок памяти, который вы ужеосвободили ранее, или с указателем, память для которого никогда не выделялась -готовьтесь к худшему. Обратная проблема, когда вы просто забываете вызватьfree(), чтобы освободить ненужный больше блок памяти, гораздо более коварна.»Утечка памяти” (memory leak) приводит к постепенному замедлению работыпрограммы по мере того, как системе виртуальной памяти приходится сбрасывать надиск неиспользуемые страницы с мусором. И, наконец, когда все системные ресурсыисчерпаны, программа неожиданно аварийно завершается, а вы начинаете ломатьголову над этой проблемой. В C++ добавлены два оператора — new и delete, которыеиспользуются во многом аналогично функциям malloc() и free(). Программистпо-прежнему отвечает за то, чтобы каждый неиспользуемый объект, созданный спомощью оператора new, был уничтожен оператором delete.

, Java нет функций ьфддщс() , free(). Поскольку в ней каждаясложная структура данных — это объект, память под такие структуры резервируетсяв куче (heap) с помощью оператора new. Реальные адреса памяти, выделенные этомуобъекту, могут изменяться во время работы программы, но вам не нужно об этомбеспокоиться. Вам даже не придется вызывать free() или delete, поскольку Java -система с так называемым сборщиком мусора. Сборщик мусора запускаетсякаждый раз, когда система простаивает, либо когда Java не может удовлетворитьзапрос на выделение памяти.

Хрупкие типы данных

C++ получил в наследство от С все обычные типы данных последнего. Эти типыслужат для представления целых и вещественных чисел различных размеров иточности. К несчастью, реальный диапазон и точность этих типов колеблется взависимости от конкретной реализации транслятора. Поведение кода, которыйпрекрасно транслируется и выполняется на одной машине, может радикальноотличаться при смене платформы. Различные трансляторы C++ могут резервироватьпод целый тип 16, 32 или 64 бита в зависимости от разрядности машинного слова.

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

Ненадежное приведение типов

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

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

Ненадежные списки аргументов

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

Было бы прекрасно, если бы в Java существовала безопаснаявозможность объявлять и передавать списки аргументов переменной длины, но в Java1. 0 такиесредства отсутствуют.

Раздельные файлы заголовков

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

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

Ненадежные структуры

С++ пытается предоставить программисту возможность инкапсуляцииданных посредством объявления структур (struct) и полиморфизм с помощьюобъединений (union). Эти две конструкции прикрывают критические икатастрофические машинно-зависимые ограничения по
размеру и выравниванию данных.

В Java нет конструкций struct и union, все это объединено в концепцииклассов.

Препроцессорная обработка

Работа препроцессора C++ которого заключается в поискеспециальных команд, начинающихся с символа #. Эти команды позволяютвыполнять простую условную трансляцию и расширение макроопределений.

Java управляется со своими задачами без помощи препроцессора,вместо принятого в С стиля определения констант с помощью директивы #define вней используется ключевое слово final.

QED

Quod erat demonstrandum — латинское «что и требовалосьдоказать”.

Категория: Обучение Java | Дата: 19.04.13

Меню раздела
Блок