Желающим выучить Java, перейдя с PHP полезно знать кардинальные отличия. Java более строгий, но благодаря развитой объектной парадигме он считается лидирующим и во многом именно он подразумевается при создании UML-диаграмм и иерархий. PHP в этом смысле шагнул не далеко, но зато более быстр в разработке. Поэтому какой язык более абстрактный и высокий - спорный вопрос.
Средства разработки
Если php-программисты используют Zend IDE или Scite, то для Java популярными стали Eclipse, JDeveloper и Netbeans. Eclipse как оказывается вовсе не такая сложная как я предполагал, а мой коллега использует его и для php. Подсказки как обычно Ctrl+пробел, автоформатирование - Ctrl+Shift+F.
Компиляция и запуск
Все java-приложения надо компилировать. При этом используются пути к корням библиотек (CLASSPATH). Благо для автоматизации есть Eclipse, но всё равно, дать на кнопку Run надо каждый раз. Компиляция позволяет избавиться от большинства синтаксических ошибок. PHP как известно компилируется на лету с прямым выводом ошибок клиенту.
Физически приложение организуется так, что каждый класс находится в одноимённом файле. Файлы в свою очередь группируются в иерархическую систему папок=пакетов (package). При компиляции и запуске файла автоматически вызываются статичные методы, как правило подобно c++ метод main(). В php как тоже всё запускается подобно c++, и если подгрузка может быть динамической черех include(), то в java используется декларирующий import.
Типы, ООП и синтаксис
В Java всё - объекты, и при их создании надо декларировать их тип, а тип объекта это класс, которые может легко создать программист. Это вызвает и гибкость и путаницу. В php как известно не обязательно указывать тип переменной, всё происходит на лету, поэтому декларирование переменной с парой-тройкой ключевых слов кажется нудным занятием.String s; //декларация, создаёт только указатель (reference) на на переменную в виртуальной памяти JVM
String s="string value"; // инициализация переменной, эквивалент new String("string value");
Конструктор в Java вызывается после создания объекта, тогда как в php во время исполнения конструктора, объект имеет тип stdObject.
Определение классов имеет свои особенности и ключевые слова:
- interface - интерфейс это абстрактные классы, в отличие от которых тут могут быть объявлены только публичные методы (а не свойства). Обозначение наследование этих классов происходит с помощью ключевого слова implements. Как известно, в java запрещено множественное наследование (в отличие от C++), но разрешено наследование нескольких интерфейсов
- extends - говорит о наследовании класса. Видимость через ключевое слово super ограничивается только одним родительским классом
Внутренние классы - в java можно легко внутри класса создать подкласс, очень полезно для группирования методов и переменных, которые используются только внутри этого класса, часто используется для обработки событий (кликов по кнопке).
class body{ class heart{}}
Видимость переменных
В Java любые фигурные скобки влияют на видимость переменных. На случай классов предусмотрены ключевые слова характеризующие видимость данных и методов:
- public - открытый доступ отовсюду
- private - доступ только изнутри класса
- protected - доступ запрещён при использовании во внешних пакетах при композиции (т.е. new myClass()), но разрешён при наследовании во внешних пакетах
- пакетный доступ - доступ запрещён во внешних пакетах, но разрешён всем в этом же пакете. Полезно при создании собственной библиотеки.
Особые ключевые слова:
- static - мгновенно инициализируемый параметр или метод - могут быть вызваны сразу после импортирования файла (подобно MyClass::myFunction()), а параметры класса ведут себя как глобальные переменные (подобно global).
Ключевое слово static дополняет остальные ключевые слова видимости и по умолчанию запускается именно static void main() как в C++. Статичные методы могут использовать только статичные переменные класса. - this - указывает на принадлежность параметра или функции данному классу. В Java по умолчанию можно опускать внутри класса, тогда как в PHP - обязательно. Бессмысленно использовать this в static-методах.
- abstract - у класса не может быть создан объект (instance),обязательно наследование, причём абтрактные методы обязательно должны быть определены в наследниках.
- super - указывает на вызов метода или параметра из наследуемого класа, используется при перегрузке. Доступен только родительский класс
- final - переменная/класс/функция не может меняться, наследоваться, перегружаться. Это ускоряет работу и обеспечивает безопасность.
- synchronized - используется при потоках, указывая на атомарность (непрерывность) всего метода
- volatile - используется при потоках как неблокируемая и некэшируемая переменная доступная всем потокам
Static initializer
В java можно вызывать участки кода как статичную переменную..
static int[] squares;
static { // a static initializer
squares = new int[count];
for (int i = 0; i < count; i++)
squares[i] = i * i;
}
Перегрузка методов (Overloading)
В Java перегрузка методов идёт по числу или типу аргументов (тн. сигнатура метода). Перегружать можно и конструктор. Метод конструктора другого типа обязательно должен быть первой строчкой.
При наследовании если конструктор базового класса нуждается в параметрах, то ключевым словом super можно инициализировать его из наследуемого класса
class Base{
Base(int k){}}
class Derived extends Base{
Derived{super(7);}} //super вызывает конструктор родителя, можно так же вызвать перегруженную функцию
Очистка мусора
Поскольку в Java можно инициализировать и декларировать переменные и это само по себе разные действия, то оказывается что можно создать переменную и тут же потерять ссылку на неё. Эта переменная становится недоступной и считается мусором. Мусор не сразу очищается, а только когда параллельно работающий сборщик мусора решит что надо очистить память.
Очистку можно "заказать" самому, используя System.gc();, а перед сбором мусора, можно указать что перед сбором собираемому объекту надо сделать. За это отвечает метод public void finalize, который по умолчанию пустой. Finalize следует особенно использовать при работе с ресурсами (чтение файлов и тп.)
Коллекции объектов
Массивы в Java - ограничены по числу элементов уже при инициализации и динамически увеличивать размер его нельзя (подобно redim в Visual Basic). Поэтому для работы с динамическими массивами существуют специализированные типы данны - контейнеры, вместо одного типа array в php:
- Коллекции. Элементы добавляются методом add, достаются методом get(индекс).
- List - элементы могут повторяться. Основаны на индексах-числах.
Не оперирует многомерными индексами, поиск логарифмической сложности.ArrayList list=new ArrayList();
list.add(C); //C автоматически переводится в базовый класс типа Object
C=(Character) list.get(0); //обратное преобразование типа в Character схоже с php- ArrayList
- LinkedList
- Set (Множество) - все элементы уникальные и не сортируются. Элементы располагаются в hash-таблице, адрес каждого элемента генерируется hash-функцией. Если hash-таблица заполнена на 75%, то поиск происходит мене чем с двумя сравнениями.
- HashSet
- TreeSet
- List - элементы могут повторяться. Основаны на индексах-числах.
- Map (Карта), аналог ассоциативного масива в php. Добавляются методом put.
- TreeMap
- HashMap
- SortedMap
- LinkedHashSet
Циклы и итераторы
Вместо привычного foreach, в java для вывода объектов можно воспользоваться конструкцией итератора вне зависимости от типа контейнера:
Iterator it=list.iterator();
while(it.hasNext()){
Mouse m=(Mouse)it.next();
System.out.println(m); //автоматом вызывается метод toString
}
Преобразование типов
Примитивные типы данных созданы из прагматических что-бы было удобней
писать код. Эти типы можно перевести в объекты при помощи "упаковочных
классов"
char c='x';
Character C = new Character(c);
float x=2.7; int n=3;
x=n; //можно, т.к. данные не теряются
n=(int)x; //надо явно указывать преобразование
В массивы по молчанию всегда сохраняются только объекты преобразованные в Object. Поэтому чтение из этих массивов может оказаться неудачным и нужно явно указывать преобразование. Начиная с Java 2 в синтаксис введено понятие генерических типов (generic classes), отмечается символами "больше" и "меньше", и благодаря этому можно опускать проверку типов вносимых в коллекцию элементов. Эта декларативность видна и в назвать Visual Basic (Dim Students(6) As Integer)
class MouseList{
private ArrayList <mouse> list = new ArrayList <mouse> (); //list.get:mouse
}
Upcasting и Late binding
Upcasting это приведения объекта чей класс насследует базовый клас к типу базового класса. При этом возникает интересная ситуация - таблица ссылок на функции не меняется, что позволяет вызывать у нового объекта "старые" функции, которые якобы должны были бы перезаписаться. Это называется late binding.
Читайте подробней в IT archiv
Исключения
Ошибки бывают всюду. Например деление на ноль:
Exception in thread "main" java.lang.ArithmeticException: / by zero
Исключения ошибок, или exception может проводится несколькими способами:
- Явно прописать проверку. В нашем случае - если ноль, то не делить.
- Словить исключение - как и в php/javascript, явно использовать try..catch блок
try{ int out=3/in; }
catch(Exception e){ System.out.println("Division by zero:"+e); }
finally{} // не обязательный блок, вызываемый независимо от наличия исключения - Передать исключение вызываемому объекту, который обязан его обработать. Для этого пишем у функции "throws Exception", и внутри функции кидаем "throw e" исключение наверх.
Для гибкости, можно наследовать существующий класс Exception и делать свои исключения. Аналогом debug_backtrace из php в java является Exception.printStackTrace()
Читайте также:
Комментарии