Основное

» Linux Docker 0.9 - краткое практическое руководство
Установка, настройка, запуск, основные моменты работы.

» Изучаем CGroups
Практический подход к изучению подсистемы ядра Linux

» db2dhcp - DHCP сервер на SQL СУБД
Сборка из исходников, настройка БД, запуск.

Последние записи

» Отличия синтаксиса C++ & Java и некоторые особенности Java
В рамках "заметок на полях" - краткий, очень поверхностный и слабо структурированный набор различий в...

» Восстановление старых разработок
Старые проекты по которым планируется восстановить работы

» Linux Docker 0.9 - краткое практическое руководство
Установка, настройка, запуск, основные моменты работы.

Отличия синтаксиса C++ & Java и некоторые особенности Java

06 апреля 2014

В рамках "заметок на полях" - краткий, очень поверхностный и слабо структурированный набор различий в синтаксисе языков C++ и Java, а так же некоторые особенности Java.

  • Имя файла исходного кода обязательно должно совпадать с именем класса, чей метод main() вызывается при запуске Java машины.
  • Object - класс от которого наследуются все объекты в Java, включая массивы и строки (см. таблицу).
  • Спецификаторы доступа индивидуальны для каждого члена (указываются перед объявлением).
  • Все члены класса по умолчанию открыты для области видимости пакета. Область видимости "по умолчанию" - это нечто среднее между private и protected, см. таблицу.
  • Каждый *.java файл может содержать только один класс объявленный как public и доступный извне.
  • Определение и объявление класса всегда находится в одном файле, невозможно вынести прототипы в заголовки.
  • Отсутствуют указатели.
  • Все переменные классов - на самом деле ссылки на объекты а не сами объекты. Инициализация их для использования обязательно должна выполняться через new <конструктор-класса>(...).
  • Исходя из предыдущего пункта - при присвоении одной переменной-объекта другой выполняется только изменение ссылки но не копирование объекта.
  • Переменные в функции передаются по значению если это элементарные типы (int, byte, long, etc...), или по ссылке, если это объекты.
  • Доступ к публичным статическим членам класса осуществляется через оператор точки ., а не через ::, что на мой взгляд вносит некоторую внешнюю путанницу.
  • Отсутствует деструктор, но есть finalize().
  • Не стоит путать finalize() и деструктор С++. finalize() вызывается только при сборке мусора, которая никак не связана с выходом объекта из области видимости и отсутствием хотя бы одной ссылки на данный объект.
  • Сборку мусора можно форсировать вызвав метод Runtime.gc() на текущем объекте Runtime или статический метод System.gc(). Судя по проведённым опытам - освобождение памяти работает только в пределах виртуальной машины Java и однажды выделенную память в ОС не возвращает пока не завершится машина.
  • В Java-стиле написания кода функции генерируют исключения, вместо возврата кода системной ошибки или ошибки логики виртуальной машины. Потому множество функций обязательно должно выполняться внутри блока try { ... } catch (...) { ... } обрабатывающего исключения, либо метод вызывающий их должен явно указывать через throws список не обрабатываемых им исключений генерируемых этими функциями, для обработки их методами "выше" по стеку вызовов.
  • Исключения делятся на непроверяемые и проверяемые.
  • Блок try { ... } также может заканчиваться блоком finally { ... }, выполняющемся независимо от наличия/отсутствия исключений в предыдущем блоке try { ... }. Это удобно использовать для выполнения каких-либо обязательных действий независимо от результатов выполнения блока кода, например для автоматического освобождения всех выделенных в нём ресурсов.
  • char это не однобайтный тип как с С/С++, это 16-битный тип поддерживающий unicode строки.
  • bool в Java известен как boolean.
  • Условные конструкции принимают только boolean тип переменных или выражений. Это значит что код вида:
    int a; ... действия над переменной a ...; if(a) { ... }
    Не верен с точки зрения Java синтаксиса и не будет скомпилирован.
  • Константы объявляются словом final а не const.
  • Все массивы - объекты.
  • Даже строковые константы (например "any string const") являются объектами.
  • Для строк (класс String) определён только один оператор - +, конкатенация.
  • Сравнение строк выполняется через метод bool equals() класса String, например s1.equals(s2).
  • Содержимое объектов-строк (String) константно и не подразумевает изменения отдельного элемента строки, это сделано в целях повышения производительности. При необходимости подобных операций можно использовать класс StringBuffer.
  • При конкатенации не инициализированной строки с не пустой строкой получится null + не-пустая-строка, например s += "|string"; будет равно "null|string"
  • Массивы имеют переменную-член с публичным доступом length, строки не имеют, вместо этого в них используется метод length().
  • Java не поддерживает множественного наследования. Отчасти его функции выполняются через "интерфейсы" (interface). Интерфейсы поддерживают множественное "наследование"-реализацию (implements) нескольких интерфейсов в одном классе, и в целом отношения "многие (интерфейсы) ко многим (классам)" и наоборот.
  • Интерфейсы допускают создание ссылок через которые можно обращаться к объектам классов реализующих эти интерфейсы. Правда динамический поиск подходящего метода при обращении через ссылку-интерфейс требует много накладных расходов, потому не желателен.
  • Вместо перечислений enum можно использовать интерфейсы без объявлений методов в них. В таком случае все переменные интерфейса должны быть инициализированны при определении интерфейса и их значения автоматически будут константны. После этого, через implements их можно "подключать" в определяемый класс.
  • Так же, начиная с JDK 5 существуют внешне классические перечисления - enum. На самом деле это не просто список именованных констант, а специальный класс наследуемый от суперкласса Enum. Каждый элемент перечисления - объект этого класса. Числовое значение объекта перечисления можно получить встроенной функцией ordinal.
  • Пользовательсякая перегрузка операторов привычная в С++, в Java не поддерживается.
  • Для работы в объектной среде с "примитивными типами" (int, float, char, etc...) в Java используется автоупаковка/автораспаковка в типы-оболочки (Integer, Float, Character, etc...). По сути это реализация перегрузки операторов для нескольких встроенных классов реализующих функционал примитивных типов + объектные методы.
  • super - ключевое слов опозволяющее вызвать конструктор суперкласса из подкласса, либо обратиться к члену суперкласса скрытого членом подкласса.
    • В случае использования в качестве конструктора - super всегда должен быть первым оператором в конструкторе подкласса.
  • Для определения абстрактных методов используется ключевое слово abstract, класс содержащий абстрактный метод так же должен определяться как abstract class ....
  • final запрещает переопределять методы в дочерних классах. Для "коротких" методов объявленных как final, это ключевое слово оказывает эффект аналогичный inline в С++ - в подклассах вместо вызова функции может быть вставлен байт-код метода суперкласса в код метода вызывающего класса.
  • final также запрещает наследовать класс объявленный как final.
  • Пространства имён (namespace) в Java реализуются как пакеты (package).
  • Для подключения пакетов используется import, так же можно использовать import static <package-name>.<class-name>.(*|<member-name>) для импорта статических членов класса.
  • Java поддерживает потоки через встроенный класс Thread и интерфейс Runable. Для синхронизации используется спецификатор synchronized перед методом в описании класса, или synchronized(<object>) { ... } для блока кода синхронизируемого с <object>. Для сигналов между синхронизированными потоками используются методы родительского класса Object: wait()/notify()/notifyAll().
  • transient - модификатор сообщающий что значение объекта/переменной не нужно "удерживать" при сохранении объекта, например при сериализации его перед записью на диск/в БД. Логично таким образом помечать переменные содержащие уникальные идентификаторы времени выполнения и прочую подобную информацию имеющую смысл только в текущем экземпляре java-процесса.
  • <object> instanceof <type> - операция времени выполнения, возвращает true если <object> есть ссылка на класс <type>, либо может быть приведён к ссылке на этот класс, иначе false.
  • assert - утверждения в Java используются примерно так же как и в С: assert <bool expression> [: Assertion fail description], но нужно иметь ввиду что они "вшиваются" в скомпилированный байт-код, и могут быть включены при запуске java -ea.
  • this(...) - может быть использовано внутри конструктора класса для вызова другого конструктора этого же класса, подходящего по сигнатуре аргументов.
  • Вместо шаблонов используются обобщения, внешне очень похоже: class CLASS_NAME<type-name[, type-name2, ...]> { ... }. В обобщениях нельзя использовать примитивные типы (int, byte, char, etc...). В качестве параметров могут быть использованы только классы.
    Кроме того, поддерживаются ограниченные типы, через указание суперкласса для классов-параметров. Например, объявление "обобщённого класса" class CLASS_NAME<T extends Number> в котором допустимо использовать только классы-потомки общего класса числовых Number.
  • Для быстрого копирования массивов удобно применять System.arraycopy().

comments powered by Disqus