Синтаксис Java относится к набору правил, определяющих, как программа Java написана и интерпретируется.
Синтаксис в основном унаследован от C и C ++. В отличие от C ++, в Java нет глобальных функций или переменных, но есть элементы данных, которые также считаются глобальными переменными. Весь код принадлежит классам, а все значения - объектам. Единственным исключением являются примитивные типы , которые не представляют экземпляры класса по соображениям производительности (хотя могут быть автоматически преобразованы объекты и наоборот с помощью автобокса). Некоторые функции, такие как перегрузка оператора или целочисленные типы без знака, опущены, чтобы упростить язык и избежать ошибок программирования.
Синтаксис Java постепенно расширялся в ходе многих основных JDK выпусков, и теперь поддерживает такие возможности, как общее программирование и функциональные литералы (называемые лямбда-выражениями в Java). С 2017 года новая версия JDK выпускается два раза в год, причем каждый выпуск вносит в язык дополнительные улучшения.
идентификатор - это имя элемента в коде . При выборе имен для элементов необходимо ввести стандартный соглашение об именах. Идентификаторы в Java чувствительны к регистру..
Идентификатор может содержать:
Идентификатор не может:
абстрактный | продолжить | для | новый | переключатель |
assert | по умолчанию | goto | package | synchronized |
boolean | do | if | private | этот |
break | double | реализует | protected | throw |
байт | else | import | public | выбрасывает |
case | enum | instanceof | return | transient |
catch | extends | int | short | попробуйте |
char | final | интерфейс | статический | var |
class | finally | long | strictfp | void |
const | float | родной | супер | энергозависимый |
в то время как |
Целое число | |
---|---|
двоичный (введено в Java SE 7) | 0b11110101(0bза соответствующее двоичное число) |
восьмеричное | 0365(0, за которым следует восьмеричное число) |
шестнадцатеричное | 0xF5(0x, за которым следует шестнадцатеричное число) |
десятичное | 245(десятичное число) |
значения с плавающей запятой значения | |
float | 23.5F, .5f, 1.72E3F(десятичная дробь с необязательный индикатор экспоненты, за которым следует F) |
0x. 5FP0F, 0x.5P-6f(0x, за которым следует шестнадцатеричная дробь с обязательным индикатором экспоненты и суффиксом F) | |
двойным | 23.5D, .5, 1.72E3D(десятичная дробь с необязательным индикатором экспоненты, за который следует необязательный D) |
0x.5FP0, 0x.5P-6D(0x, за которым следует шестнадцатеричная дробь с обязательным указателем степени и необязательный суффикс D) | |
Символьные литералы | |
c har | 'a', 'Z', '\ u0231'(символ или escape-символ, заключенный в одинарные кавычки) |
Логические литералы | |
логическое | true, false |
нулевой литерал | |
пустая ссылка | null |
строковые литералы | |
Строка | «Hello, World»(последовательность символов и escape-символы, заключенных в двойные кавычки) |
escape-символы в строках | |
Unicode символ | \ u3876(\u, за которым следует шестнадцатеричный код Unicode до U + FFFF) |
Octal escape | \ 352(восьмеричное число, не превышающее 377, черует предшествующая обратная косаята) |
перевод строки | \n |
возврат каретки | \r |
перевод страницы | \f |
обратная косая черта | \\ |
>Двойная косая черта | \' |
Двойные кавычки | \" |
Tab | \t |
Backspace | \b |
Целочисленные литералы по умолчанию имеют тип int
, если только тип long
не указан путем добавления L
или l
суффикс к буквальному, например 367L
. Начните с Java SE 7, можно создать новые символы между цифрами числа для повышения удобочитаемости; например, число 145608987можно записать как 145_608_987.
Переменные - это ассоциаторы, связанные со значениями. Они осуществляются путем записи типа и объектива, возможно, инициализируются в том же операторе путем введения значений.
целое число; // Объявление неинициализированной переменной с именем 'count' типа 'int' count = 35; // Инициализируем переменную int count = 35; // Объявление и инициализация одновременно
Несколько чисел одного типа могут быть объявлены и инициализированы в одном операторе, используя запятую в качестве разделителя.
int a, b; // Объявление нескольких чисел одного типа int a = 2, b = 3; // Объявление и инициализация нескольких чисел одного и того же типа
. Начиная с Java 10, стало возможным определение числа с помощью var
.
// поток будет иметь тип FileOutputStream, как выводится из его инициализатора var stream = новый FileOutputStream ("файл.txt"); // Эквивалентное объявление с явным типом FileOutputStream stream = new FileOutputStream ("file.txt");
Разделители {и }обозначают блок кода и новую область действия. Члены класса и средства метода являются примерами, которые могут находиться внутри этих фигурных скобок в различных контекстах.
Внутри метода фигурные скобки Заголовок для создания новых областей, как показано ниже:
void doSomething () {int a; {int b; а = 1; } a = 2; b = 3; // Недопустимо, потому что переменная объявлена во внутренней области видимости..}
В Java есть три вида комментариев: традиционные комментарии, комментарии в конце строки и комментарии к документации.
Традиционные комментарии, также известные как комментарии блоков, начинаются с / *
и заканчиваются * /
, они могут занимать несколько строк. Этот тип комментариев был получен из C и C ++.
/ * Это многострочный комментарий. Он может занимать более одной строки. * /
Комментарии в конце строки начинаются с //
и продолжаются до конца текущей строки. Этот тип присутствует также в C ++ и в современном C.
// Это комментарий конца строки
Комментарии документации в исходных файлах обрабатываются инструментом Javadoc для создания документа. Этот тип идентичен традиционным комментариям, за исключением того, что он начинается с / **
и начинается стандартм, определенным инструментом Javadoc. Эти особые комментарии отличаются друг от друга.
/ ** * Это комментарий документации. * * @author John Doe * /
Классы в пакете java.lang неявно импортируются в каждую программу, пока никакие явно импортированные типы не имеют одинаковых имен. Важные из них:
int
, который фактически является UTF-32.throw
и catch
.Приложения Java состоят из наборов классов. Классы существуют в пакетах, но также могут быть вложены в другие классы.
основной
методКаждое приложение Java должно иметь точку входа. Это верно как для приложений с графическим интерфейсом, так и для консольных приложений. Точкой входа является метод основной
. Может быть несколько классов с методом основной
, но основной класс всегда определяется извне (например, в файле манифеста ). Метод должен быть статический
, и ему передаются аргументы системы строки в виде массива строк. В отличие от C ++ или C #, он никогда не возвращает значение и должен возвращать void
.
public static void main (String args) {}
Пакеты являются частями класса и используются для группировки и / или отличия именованных сущностей от других. Другая цель пакетов - управлять доступом к коду вместе с модификаторами доступа. Например, java.io.InputStream
- это полное имя класса для класса InputStream
, которое находится в пакете java.io
.
Пакет объявлен в начало файла с объявлением пакет
:
пакет myapplication.mylibrary; public class MyClass {}
Классы с модификатором public
должны быть помещены в файлы с тем же именем и расширением javaи помещены во вложенные папки, соответствующие имени пакета. У нового класса myapplication.mylibrary.MyClass
будет следующий путь: myapplication / mylibrary / MyClass.java
.
Объявление импорт типа позволяет ссылаться на именованный тип по простому имени, а не по полному имени, включает пакет. Объявления могут быть объявлениями импорта типа или объявлениями импорта по запросу. Объявления импорта должны размещаться в верхней части файла кода после объявления пакета.
пакет myPackage; import java.util.Random; // Объявление единственного типа public class ImportsTest {public static void main (String args) {/ * Следующая строка эквивалентна * java.util.Random random = new java.util.Random (); * Было бы неправильно без импорта. * / Random random = новый случайный (); }}
В коде регистрируются импорт объявления по запросу. «Импорт типа» импортирует все типы пакета. «Статический импорт» импортирует элементы пакета.
импортировать java.util. *; / * Эта форма импорта делает классы в пакете java.util доступными по имени, может вместо объявления импорта в данном примере. * / import java. *; / * Этот оператор допустим, но ничего не делает, поскольку в пакете java нет классов. Все они находятся в пакетах внутри пакета java. Это не импортирует все доступные классы. * /
Этот тип объявления доступен с J2SE 5.0. Объявления статического импорта разрешают доступ к статическому члену, определенным в другом классе, интерфейсе, аннотации или перечислении; без указания имени класса:
import static java.lang.System.out; // 'out' - это статическое поле в общедоступном классе java.lang.System HelloWorld {public static void main (String args) {/ * Следующая строка эквивалентна: System.out.println ("Hi World!"); и было бы неправильно без декларации импорта. * / out.println («Привет, мир!»); }}
Объявления импорта по требованию позволяют импортировать все поля типа:
import static java.lang.System. *; / * Эта форма объявления делает все поля в классе java.lang. * /
Константы перечисления также одна со статическим импортом. Например, это перечисление находится в пакете с именем screen
:
public enum ColorName {RED, BLUE, GREEN};
Для получения константления можно использовать статические объявления импорта в другом классе:
import screen.ColorName; импортировать статический экран.ColorName. *; public class Dots {/ * Следующая строка эквивалентна 'ColorName foo = ColorName.RED', и она была бы неверной без статического импорта. * / ColorName foo = RED; void shift () {/ * Следующая строка эквивалентна: if (foo == ColorName.RED) foo = ColorName.BLUE; * / if (foo == RED) foo = СИНИЙ; }}
Операторы в Java аналогичны операторам в C ++. Однако нет оператора удалить
из-за механизмов сборки мусора в Java, а также с указателями , поскольку Java их не поддерживает. Другое отличие состоит в том, что в Java есть беззнаковый оператор сдвига вправо (>>>
), в то время как подписи оператора сдвига вправо в зависимости от типа. Операторы в Java не могут быть перегружены.
Приоритет | Оператор | Описание | Ассоциативность |
---|---|---|---|
1 | () | Вызов метода | Слева направо |
| Доступ к массиву | ||
. | Выбор элемента класса | ||
2 | ++ -- | Постфиксное увеличение и уменьшение | |
3 | ++ -- | Префиксное увеличение и уменьшение | Справа налево |
+ - | Унарный плюс и минус | ||
! ~ | Логическое НЕ и побитовое НЕ | ||
(тип) val | Приведение типа | ||
new | Создание экземпляра класса или массива | ||
4 | * / % | Умножение, деление и модуль (остаток) | Слева направо |
5 | + - | Сложение и вычитание | |
+ | Объединение строк | ||
6 | << >> >>> | Поразрядный сдвиг влево, сдвиг вправо со знаком и сдвиг вправо без знака | |
7 | < <= | Относительный «меньше» и «меньше или равно« | |
> >= | Относительное «больше» и «Больше или равно» | ||
instanceof | Сравнение типов | ||
8 | == != | Относительное «равно» и «не равно» | |
9 |
| Побитовое и логическое И | |
10 | ^ | Поразрядное и логическое ИЛИ (исключающее ИЛИ) | |
11 | | | Поразрядное и логическое ИЛИ (включая ИЛИ) | |
12 |
| Логическое условное И | |
13 | || | Логическое условное ИЛИ | |
14 | c? t: f | Тернар условный (см. ?: ) | Справа налево |
15 | = | Простое присваивание | |
+= -= | Присваивание по сумме и разнице | ||
*= /= %= | Присвоение по продукту, частному и остатку | ||
<<= >>= >>>= | Присваивание с помощью побитового сдвига влево, сдвига вправо со знаком и сдвига вправо без знака | ||
= ^= |= | Назначение с помощью побитового И, XOR и ИЛИ |
if
операторif операторы в Java аналогичны операторам в C и используют тот же синтаксис:
if (i == 3) doSomething ();
if
оператор может исходить необязательный блок else
, и в этом случае он становится оператором if-then-else:
if (i == 2) {doSomething ();} else {doSomethingElse ();}
Как и в C, конструкция else-if не включает никаких специальных ключевых слов, она формирует последовательность отдельных операторов if-then-else:
if (i == 3) {doSomething ();} else if (i == 2) {doSomethingElse ();} else {doSomethingDifferent ();}
Также об ратите внимание, что оператор ?: может приветствовать вместо si выражение mple if, например
int a = 1; int b = 2; int minVal = (оператор < b) ? a : b;
switch
операторы Switch в Java могут использовать byte
, short
, char
и int
(примечание: не long
) примитивные типы данных или соответствующие им типы оболочки. Начиная с J2SE 5.0, можно использовать типы перечислений. Начиная с Java SE 7 можно использовать Эти метки в Java могут содержать только константы (включая константы перечисления), переводчик.
Возможные значения с использованием меток case
. Может присутствовать необязательная метка default
, чтобы объявить, что если следующий за ней код будет выполнен ни одна из меток, то случай не соответствует выражению.
Код для каждой метки соединяет слово разрыв
. ующей метке, однако, предупреждение будет обычно сообщается во время компиляции.
переключатель (канал) {случай 'A': doSomething (); // Срабатывает, если ch == 'A' break; case «B»: case «C»: doSomethingElse (); // Срабатывает, если ch == 'B' или ch == 'C' break; по умолчанию: doSomethingDifferent (); // Срабатывает в любом другом случае перерыва; }
switch
выраженияНачиная с Java 14 стало возможным использовать выражение switch, в котором используется новый синтаксис стрелок:
var result = switch (ch) {case 'A' ->Result.БОЛЬШОЙ; case 'B', 'C' ->Result.FINE; по умолчанию ->бросить новое ThisIsNoGoodException (); };
В альтернативных вариантах есть возможность выразить то же самое с помощью оператора yield
, рекомендуется предпочесть синтаксис стрелки, поскольку он позволяет избежать проблемы случайного провала.
var result = switch (ch) {case 'A': yield Result.GREAT; case 'B': case 'C': yield Result.FINE; по умолчанию: выбросить новое ThisIsNoGoodException (); };
Операторы итерации - это операторы, которые многократно выполняются, когда данное условие оценивается как истинное. Начало с J2SE 5.0, в Java есть формы таких операторов.
цикл while
В цикле while
проверка выполняется перед каждой итерацией.
while (i < 10) { doSomething(); }
do... while
loopВ цикле do... while
проверка выполняется после каждой итерации. Следовательно, код всегда выполняется хотя бы один раз.
// doSomething () вызывается хотя бы один раз do {doSomething ();} while (i < 10);
for
loopfor
циклы в Java включают инициализатор, условие и выражение счетчика. Можно включить несколько выражений одного вида, используя запятую в качестве разделителя (кроме условия). Однако, в отличие от C, запятая является просто разделителем, а не оператором.
for (int i = 0; i < 10; i++) { doSomething(); } // A more complex loop using two variables for (int i = 0, j = 9; i < 10; i++, j -= 3) { doSomething(); }
Как и C, все три выражения являются необязательными. Следующий цикл бесконечен:
for (;;) {doSomething ();}
for
циклУлучшенный для
циклов был доступен начиная с J2SE 5.0.Этот тип цикла использует встроенные итераторы по типам и коллекциям для возврата каждого элемента в данной коллекции. Каждый элемент возвращается и становится доступным в контексте блока кода. Ког да блок выполняется, следующий элемент возвращается, пока не кончатся элементы. В этом цикле используется специальное особое слово, а вместо этого используется другой стиль записи.
для (int i: intArray) {doSomething (i); }
Метки - это точки в коде, используемые операторами break
и continue
. Обратите внимание, что использовать слово Java goto
нельзя использовать для перехода к определенному точному кода.
начало: someMethod ();
Оператор break
Оператор break
выходит из ближайшего цикла или оператора switch
. Выполнение продолжается в операторе после завершенного оператора, если таковой имеется.
for (int i = 0; i < 10; i++) { while (true) { break; } // Will break to this point }
Можно выйти из внешнего цикла, используя метки:
outer: for (int i = 0; i < 10; i++) { while (true) { break outer; } } // Will break to this point
continue
statementОператор continue
прерывает текущую итерацию текущего оператора управления и начинает следующую среду. Следующий цикл , в то время как
в приведенном ниже коде считывает символы путем вызова getChar ()
, пропуск операторов в теле цикла, если символы являются пробелами:
int ch; while (ch == getChar ()) {if (ch == '') {continue; // Пропускает оставшуюся часть цикла while} // Остальная часть цикла, пока не будет достигнута, если ch == '' doSomething ();}
Метки могут быть указаны в операторах continue
и break
операторы:
external: for (String str: stringsArr) {char strChars = str.toCharArray (); for (char ch: strChars) {if (ch == '') {/ * Продолжает внешний цикл, и следующая строка извлекается из stringsArr * / continue external;} doSomething (ch) ;}}
return
инструкцияОператор return
используется для выполнения задачи и возврата значения. Значение, возвращаемое методом, записывается после ключевого слова return
. Если метод возвращает что-либо, кроме void
, он должен использовать оператор return
для возврата некоторого значения.
void doSomething (boolean streamClosed) {// Если streamClosed истинно, выполняет останавливается if (streamClosed) {return; } readFromStream (); } int calculateSum (int a, int b) {int результат = a + b; вернуть результат; }
Оператор return
немедленно завершает выполнение, за исключением одного случая: если оператор встречается в блоке попробуйте
и дополняется finally
, управление передается в блоке finally
.
void doSomething (boolean streamClosed) {try {if (streamClosed) {return; } readFromStream (); } finally {/ * Будет вызываться последним, даже если readFromStream () не был вызван * / freeResources (); }}
операторы try-catch-finally
Исключения обрабатываются в блоках try
... catch
.
try {// Заявления, которые могут вызывать исключение methodThrowingExceptions (); } catch (Exception ex) {// Здесь обнаружено и обработано исключение reportException (ex); } finally {// Операторы всегда выполняются после блоков try / catch freeResources (); }
Операторы в блоке try
выполняются, и если какой-либо из них вызывает исключение, выполнение блока прекращается, и исключение обрабатывается блоком catch
. Может быть несколько блоков catch
, и в этом случае выполняется первый блок с переменной исключения, тип которой соответствует типу сгенерированного исключения.
В Java SE 7, помимо предложений монолитного улова, также были введены предложения с перехватами. Этот тип предложений catch позволяет Java обрабатывать различные типы исключений в одном блоке при условии, что они не являются подклассами друг друга.
пальчик {methodThrowingExceptions (); } catch (IOException | IllegalArgumentException ex) {// И IOException, и IllegalArgumentException будут перехвачены и обработаны здесь reportException (ex); }
Если ни один блок catch
не соответствует типу сгенерированного исключения, выполнение внешнего блока (или метода), содержащего try
... catch
прекращается, и прекращается исключение передается за пределы содержащего блока (или метода). Исключение распространяется через стек цикла до тех, пока соответствующий блок catch
не будет найден в одном из текущих активных методов. Если исключение вплоть до самого верхнего метода main
без найденного соответствующего блока catch
, текстовое исключение описание записывается в стандартный поток вывода.
Операторы в блоке наконец
всегда выполняются после блоков попробуйте
и catch
независимо от того, были созданы исключение, и даже если достигнут оператор вернуть
. Такие блоки полезны для обеспечения кода очистки, который гарантированно всегда будет продуктом.
Блоки catch
и наконец
являются одним необязательными, но по крайней мере или другой должен присутствовать после блока try
.
операторы try
-with-resourcesоператоры try
-with-resources выделить себя особый тип операторов try-catch-finally
, представленных как реализация шаблон dispose в Java SE 7. В операторе try
-with-resources за ключевые try
следует инициализация одного или нескольких ресурсов, которые автоматически освобождаются словом, когда try
выполнение блока завершено. Ресурсы должны реализовывать java.lang.AutoCloseable
. Для операторов try
-with-resources не требуется наличие блока catch
или finally
, в отличие от обычных операторов try-catch-finally
.
try (FileOutputStream fos = new FileOutputStream ("имя файла"); XMLEncoder xEnc = new XMLEncoder (fos)) {xEnc.writeObject (объект); } catch (исключение IOException) {Logger.getLogger (Serializer.class.getName ()). журнал (Level.SEVERE, null, ex); }
Начиная с Java 9, можно использовать уже объявленные переменные:
FileOutputStream fos = new FileOutputStream ("filename"); XMLEncoder xEnc = новый XMLEncoder (fos); попробуйте (fos; xEnc) {xEnc.writeObject (объект); } catch (исключение IOException) {Logger.getLogger (Serializer.class.getName ()). журнал (Level.SEVERE, null, ex); }
Оператор throw
Оператор throw
используется для создания исключения и завершения выполнения блока или метода. Созданный экземпляр исключения записывается после оператора throw
.
void methodThrowingExceptions (Object obj) {if (obj == null) {// Выбрасывает исключение типа NullPointerException throw new NullPointerException (); } // Не будет вызываться, если объект равен нулю doSomethingWithObject (obj); }
Java имеет встроенные инструменты для многопоточного программирования. Для целей потока потока в язык Java включен оператор synchronized
.
Чтобы синхронизировать слово кода, ему следует закрыть скобку синхронизировать
, за которым следует объект блокировки в скобках. Когда исполняющий поток запускает синхронизированного блока, он получает блокировку взаимного исключения, происходит блок, а затем снимает блокировку. Никакие потоки не могут войти в этот блок, пока блокировка не будет снята. В качестве блокировки может быть любой неневой ссылочный тип.
/ * Получает блокировку для некоторого объекта. Он должен быть ссылочного типа и отличаться от NULL * / synchronized (someObject) {// Синхронизированные операторы}
оператор assert
операторы assert
доступны с версией J2SE 1.4. Эти типы операторов используются для создания утверждений в исходном коде, которые можно включить и выключить во время выполнения определенных классов или пакетов. Для объявления используется используемое слово assert
, за которым следует условное выражение. Если при выполнении принимает он принимает значение false
, генерируется исключение. Этот оператор может действовать как подробное сообщение об исключении.
// Если n равно 0, выдается AssertionError assert n! = 0; / * Если n равно 0, AssertionError будет выдан с сообщением после двоеточия * / assert n! = 0: «n было равно нулю»;
Типы-примитивы в Java включают целочисленные типы, числа с плавающей запятой, кодовые единицы UTF-16 и логический тип. В Java нет беззнаковых типов, кроме типа char
, который используется для представления кода UTF-16. Отсутствие беззнаковых типов компенсируется беззнаковой операции сдвига вправо (>>>
), которой нет в C ++. Тем не менее, критика высказывалась по поводу отсутствия совместимости с C и C ++, что является причиной.
Примитивные типы | |||||
---|---|---|---|---|---|
Имя | Класс-оболочка | Значение | Диапазон | Размер | Значение по умолчанию |
байт | java.lang.Byte | целое число | от −128 до +127 | 8-бит (1 байт) | 0 |
короткий | java. lang.Short | целое число | от −32,768 до +32,767 | 16-бит (2 байта) | 0 |
int | java.lang.Integer | integer | от −2 147 483 648 до +2 147 483 647 | 32-битный (4-байтовый) | 0 |
long | java.lang.Long | целое число | от -9,223,372,036,854,775,808 до. +9,223,372,036,854,775,807 | 64-битное (8-байтовое) | 0 |
float | java.lang.Float | число с плавающей запятой | ± 1.401298E-45 до ± 3.402823E + 38 | 32-битный (4-байтовый) | 0.0f |
double | java.lang.Double | число с плавающей запятой | ± 4.94065645841246E-324 до. ± 1.79769313486232E + 308 | 64-битное (8-байтовое) | 0,0 |
логическое | java. lang.B oolean | логический | true или false | 1-бит (1-бит) | false |
char | java.lang.Character | UTF-16 кодовая единица (BMP символ. или часть суррогатной пары) от | '\ u0000' до '\ uFFFF' | 16-бит (2-байтовый) | '\ u0000' |
char
не обязательно соответствует одному символу. Он может представлять часть суррогатной пары , в этом случае кодовая точка Unicode представляет собой последовательность двух значений char
.
Эта языковая функция была представлена в J2SE 5.0. Упаковка - это операция преобразования значений примитивного типа в соответствующем ссылочном типе, которая служит оболочкой для этого конкретного примитивного типа. Распаковка - это операция, обратная преобразование значения ссылочного типа (ранее упакованного) в соответствующее примитивного типа. Ни одна из операций не требует явного преобразования.
Пример:
int foo = 42; // примитивный тип Целочисленный bar = foo; / * foo помещается в bar, bar имеет тип Integer, который служит оболочкой для int * / int foo2 = bar; // Распаковка обратно к примитивному типу
Ссылочные типы классов, включающие типы, типы интерфейсов и типы массивов. Когда вызывается конструктор, в куче создается объект. Когда переменная объекта выходит за пределы области видимости, ссылка прерывается, когда ссылок не остается, объект помечается как мусор. Затем сборщик мусора собирает и уничтожает его через некоторое время.
Ссылочная переменная имеет значение null
, когда она не ссылается ни на один объект.
Массивы в Java создаются во время выполнения, как и экземпляры классов. Длина массива определяется при создании и не может быть изменена.
числа int = новый интервал [5]; числа [0] = 2; числа [1] = 5; int x = числа [0];
// Длинный синтаксис int numbers = new int {20, 1, 42, 15, 34}; // Краткий синтаксис int numbers2 = {20, 1, 42, 15, 34};
В Java многомерные массивы представлены как массивы массивов. Технически они представлены массивами ссылок на другие массивы.
int числа = новый int [3] [3]; числа [1] [2] = 2; int numbers2 = {{2, 3, 2}, {1, 2, 6}, {2, 4, 5}};
Из-за природы многомерных массивов подмассивы могут различаться по длине, поэтому многомерные массивы не обязательно должны быть прямоугольными, в отличие от C:
int numbers = new int [2]; // Инициализация только первого измерения numbers [0] = new int [3]; числа [1] = новый int [2];
Классы являются основами объектно-ориентированного языка, такого как Java. Они содержат члены, которые хранят данные и управляют ими. Классы делятся на верхнего уровня и вложенные. Вложенные классы - это классы, помещенные внутри другого класса, которые могут иметь доступ к закрытым членам включающего класса. Вложенные классы включают классы-члены (которые могут быть определены с помощью модификатора static для простого вложения или без него для внутренних классов), локальные классы и анонимные классы.
класс верхнего уровня | класс Foo {// члены класса} |
---|---|
внутренний класс | класс Foo {// класс класса верхнего уровня Bar {// внутренний класс} } |
Вложенный класс | class Foo {// Статический класс класса верхнего уровня Bar {// Вложенный класс}} |
Локальный класс | class Foo {void bar () {class Foobar {// Local класс внутри метода}}} |
Анонимный класс | class Foo {void bar () {new Object () {// Создание нового анонимного класса, расширяющего Object}; }} |
Нестатические члены класса определяют типы переменных и методов экземпляра, которые связаны с объектами, созданными из этого класса. Чтобы создать эти объекты, необходимо создать экземпляр класса с помощью оператора new
и вызова конструктора класса.
Foo foo = новый Foo ();
Доступ к членам как экземпляров, так и статических классов осуществляется с помощью оператора .
(точка).
Доступ к члену экземпляра . Доступ к элементам экземпляра можно получить через имя переменной.
String foo = «Привет»; Строка bar = foo.toUpperCase ();
Доступ к статическому члену класса . Доступ к статическим членам осуществляется с помощью имени cl жопа или любого другого типа. Для этого не требуется создание экземпляра класса. Статические члены объявляются с использованием модификатора static
.
public class Foo {public static void doSomething () {}} // Вызов статического метода Foo.doSomething ();
Модификаторы - это ключевые слова, используемые для изменений типов и типов. В частности, есть подгруппа, содержащая модификаторы доступа.
аннотация
- указывает, что служит только базовым классом и не может быть создан.static
- используется только для классов-членов, указывает, что класс-член не принадлежат конкретному экземпляру принадлежего класса.final
- классы, отмеченные как final
, не могут быть расширены и не могут иметь никаких подклассов.strictfp
- указывает, что все операции с плавающей запятой должны быть выполнены в соответствии с IEEE 754, и запрещает использование повышенной точности для хранения промежуточных результатов.Модификаторы доступа или наследование модификаторы, устанавливают доступность классов, методов и других членов. К группе, помеченным как public
, можно получить доступ из любого места. Если класс или его член не имеет модификаторов, невозможен по умолчанию.
открытый класс Foo {int go () {return 0; } Панель частного класса {}}
Следующая таблица sh определяет, имеет ли код внутри класса доступа к классу или методу в зависимости от местоположения класса доступа и модификатора для класса или члена класса, к которому осуществляется доступ:
Модификатор | Тот же класс или вложенный класс | Другой класс внутри того же пакета | Расширенный класс внутри другого пакета | Нерасширенный внутри другого пакета |
---|---|---|---|---|
частный | да | нет | нет | нет |
по умолчанию (частный пакет) | да | да | нет | нет |
защищен | да | да | да | нет |
общедоступный | да | да | да | да |
A конструктор - это специальный метод, вызываемый при инициализации объекта. Его цель - инициализировать члены объекта. Основные различия между конструкторами и обычными заключаются в том, что конструкторы вызываются при создании экземпляров класса и никогда не возвращают. Конструкторы объявлены как общие методы, названы в честь класса, и типовые значения не указаны:
class Foo {String str; Foo () {// Конструктор без аргументов // Инициализация} Foo (String str) {// Конструктор с одним аргументом this.str = str; }}
Инициализаторы - это блоки кода, которые выполняются при создании экземпляров класса или класса. Есть два типа инициализаторов: статические инициализаторы и инициализаторы экземпляров.
Статические инициализаторы инициализируют статические поля при создании класса. Они объявляются использованием с помощью слова static
:
class Foo {static {// Initialization}}
Класс создается только один раз. Поэтому статические инициализаторы не вызываются более одного раза. Напротив, инициализаторы экземпляра автоматически вызываются перед вызовом конструктора каждый раз, когда создается экземпляр класса. В отличие от конструкторов инициализаторов, экземпляры не могут генерировать какие-либо проверенные исключения (за исключением некоторых особых случаев). Инициализаторы экземпляра объявляются в блоке без каких-либо ключевых слов:
класс Foo {{// Инициализация}}
Java имеет механизм сборки мусора, деструкторов не существует. Однако каждый объект имеет метод finalize ()
, вызываемый до сборки мусора, который может быть переопределен для реализации финализации.
Все операторы в Java должны находиться внутри методов. Методы похожи на функции, за исключением того, что они принадлежат классам. Метод имеет возвращаемое значение, имя и обычно некоторые параметры инициализируются, когда он вызывается с некоторыми аргументами. Подобно C ++, методы, не возвращающие ничего, имеют возвращаемый тип, объявленный как void
. В отличие от C ++, методы в Java не могут иметь значения аргумента по умолчанию, а вместо этих методов обычно перегружаются.
class Foo {int bar (int a, int b) {return (a * 2) + b; } / * Перегруженный метод с тем же именем, но другим набором аргументов * / int bar (int a) {return a * 2; }}
Метод вызывается с использованием нотации .
для объекта или в случае статического метода, также для имени класса.
Foo foo = новый Foo (); int результат = foo.bar (7, 2); // Нестатический метод вызывается для foo int finalResult = Math.abs (result); // Вызов статического метода
Ключевое слово throws
указывает, что метод вызывает исключение. Все отмеченные исключения должны быть в списке, разделенном запятыми.
void openStream () выбрасывает IOException, myException {// Указывает, что может быть выбрано исключение IOException}
abstract
- Абстрактные методы могут присутствовать только в абстрактных классах, такие методы не имеют тела и должны быть переопределены в подклассе, если он сам не является абстрактным.static
- делает метод статическим и доступным без создания экземпляров класса. Однако статические методы не могут получить доступ к нестатическим членам в том же классе.final
- объявляет, что метод не может быть переопределен в подклассе.родной
- указывает, что это реализуется через JNI в платформенно-зависимом коде. Фактическая реализация происходит вне кода Java, и такие методы не имеют тела.strictfp
- декларирует строгое соответствие IEEE 754 при выполнении операций с плавающей запятой.synchronized
- объявляет, что поток, выполняющий этот метод, должен получить монитор. Для синхронизированных
методов монитором является экземпляром класса или java.lang.Class
, если метод статический.Эта языковая функция была представлена в J2SE 5.0. Последний метод может быть объявлен как параметр переменной арности, в этом случае метод становится переменной переменной (в отличие от методов фиксированной арности) или просто методом varargs. Это позволяет объявить тип переменного количества значений в качестве параметра, включая отсутствие параметров. Эти значения доступны внутри метода в виде массива.
void printReport (String header, int... numbers) {// число означает varargs System.out.println (header); for (int num: число) {System.out.println (число); }} // Вызов метода varargs printReport ("Данные отчета", 74, 83, 25, 96);
Поля или переменные класса могут быть объявлены внутри тела класса для хранения данных.
класс Foo {двойная полоса; }
Поля могут быть инициализированы непосредственно при объявлении.
класс Foo {двойная полоса = 2.3; }
статические
- делает поле статическим членом.final
- позволяет инициализировать поле только один раз в конструкторе или внутри блока инициализации или во время его объявления, в зависимости от того, что наступит раньше.transient
- указывает, что это поле не будет сохранено во время serialization.volatile
- если поле объявлено volatile
, гарантируется, что все потоки видят согласованное значение.Классы в Java могут наследовать только от одного класса. Класс может быть производным от любого класса, который не отмечен как final
. Наследование объявляется с помощью ключевого слова расширяет
. Класс может ссылаться на себя с помощью ключевого слова this
, а его прямой суперкласс - с помощью ключевого слова super
.
class Foo {} class Foobar extends Foo {}
Если класс не указывает свой суперкласс, он неявно наследуется от класса java.lang.Object
. Таким образом, все классы в Java - это подклассами класса Object
.
Если у суперкласса нет конструктора без параметров, подкласс должен указать в своих конструкторах, какой конструктор суперкласса использовать. Например:
class Foo {public Foo (int n) {// Сделайте что-нибудь с n}} class Foobar расширяет Foo {private int number; // У суперкласса нет конструктора без параметров // поэтому мы должны указать, какой конструктор нашего суперкласса использовать и как public Foobar (int number) {super (number); this.number = число; }}
В отличие от C ++, все не- окончательные
методы в Java являются виртуальными и могут быть переопределены наследующими классами.
операция класса {public int doSomething () {return 0; }} класс NewOperation расширяет операцию {@Override public int doSomething () {return 1; }}
Абстрактный класс - это неполный класс или класс, который считается неполным. Нормальные классы могут иметь абстрактные методы, то есть методы, которые объявлены, но еще не реализованы, только если они абстрактными классами. Класс C имеет абстрактные методы, если выполняется одно из следующих условий:
пакет org.dwwwp.test; / ** * @author jcrypto * / public class AbstractClass {private static final String hello; static {System.out.println (AbstractClass.class.getName () + ": время выполнения статического блока"); hello = "привет от" + AbstractClass.class.getName (); } {System.out.println (AbstractClass.class.getName () + ": среда выполнения экземпляра блока"); } public AbstractClass () {System.out.println (AbstractClass.class.getName () + ": среда выполнения конструктора"); } public static void hello () {System.out.println (привет); }}
пакет org.dwwwp.test; / ** * @author jcrypto * / открытый класс CustomClass расширяет AbstractClass {static {System.out.println (CustomClass.class.getName () + ": время выполнения статического блока"); } {System.out.println (CustomClass.class.getName () + ": среда выполнения экземпляра блока"); } общедоступный CustomClass () {System.out.println (CustomClass.class.getName () + ": среда выполнения конструктора"); } public static void main (String args) {CustomClass nc = new CustomClass (); Здравствуйте (); //AbstractClass.hello();//also valid}}
Вывод:
org.dwwwp.test.AbstractClass: среда выполнения статического блока org.dwwwp.test.CustomClass: среда выполнения статического блока org.dwwwp. контрольная работа. AbstractClass: среда блока выполнения экземпляра org.dwwwp.test.AbstractClass: среда выполнения конструктора org.dwwwp.test.CustomClass: среда блока выполнения экземпляра org.dwwwp.test.CustomClass: приветствие среды выполнения конструктора от org.dwwwp.test.AbstractClass
Эта языковая функция была представлена в J2SE 5.0. Технически перечисления - это своего рода класс. Каждый константа перечисления определяет экземпляр типа перечисления. Классы перечисления не могут быть созданы нигде, кроме самого класса перечисления.
enum Season {ЗИМА, ВЕСНА, ЛЕТО, ОСЕНЬ}
Константы перечисления могут иметь конструкторы, вызываемые при загрузке класса:
public enum Season {WINTER («Холодная»), SPRING («Теплее»), ЛЕТО («Жарко»), ОСЕНЬ («Прохладнее»); Сезон (Строковое описание) {this.description = description; } закрытое финальное описание строки; общедоступная строка getDescription () {описание возврата; }}
Перечисления могут иметь классы, и в этом случае рассматриваются как анонимные классы, расширяющие классы перечисления:
public enum Season {WINTER {String getDescription () {return "cold";}}, SPRING {String getDescription () {return "теплее";}}, ЛЕТО {String getDescription () {return "hot";}}, FALL {String getDescription () {return "cooler";}}; }
Интерфейсы - это типы, которые не содержат полей и обычно определяют методы без фактической реализации. Они полезны для контракта с любым различными реализациями. Каждый интерфейс неявно абстрактен. Методы интерфейса могут иметь подмножество модификаторов доступа в зависимости от языковой версии, strictfp
, имеет тот же эффект, что и для классов, а также static
начиная с Java SE 8.
интерфейс ActionListener {int ACTION_ADD = 0; int ACTION_REMOVE = 1; void actionSelected (целое действие); }
Интерфейс реализуется классом с использованием ключевого слова реализует
. Разрешено реализовать более одного интерфейса, и в этом случае они записываются после ключевого слова реализует
в списке, разделенном запятыми. Класс, реализующий интерфейс, должен переопределять все его методы, иначе он должен быть объявлен как абстрактный.
интерфейс RequestListener {int requestReceived (); } class ActionHandler реализует ActionListener, RequestListener {public void actionSelected (int action) {} public int requestReceived () {}} // Метод вызова, определенный интерфейс RequestListener listener = new ActionHandler (); / * ActionHandler может быть представлен как RequestListener... * / listener.requestReceived (); / *... и таким образом известно, что он реализует метод requestReceived () * /
Эти функции были введены в выпуске Java SE 8. Интерфейс автоматически становится функциональным интерфейсом. если он определяет только один метод. В этом случае реализация может быть представлена как лямбда-выражение вместо того, чтобы реализовывать ее в новом классе, что упрощает написание кода в функциональном стиле . Функциональные интерфейсы могут быть аннотированы аннотацией @FunctionalInterface
, которая сообщает компилятору, что нужно проверить, действительно ли интерфейс соответствует определению функционального интерфейса.
// Функциональный интерфейс @FunctionalInterface interface Calculation {int calculate (int someNumber, int someOtherNumber); } // Метод, который принимает этот интерфейс как параметр int runCalculation (Расчет расчета) {return Расчет.calculate (1, 2); } // Использование лямбды для вызова метода runCalculation ((number, otherNumber) ->number + otherNumber); // Эквивалентный код, который использует анонимный класс вместо runCalculation (new Calculation () {@Override public int calculate (int someNumber, int someOtherNumber) {return someNumber + someOtherNumber;}})
Типы параметров Lambda не должны быть полностью определены и может быть выведен из интерфейса, который он реализует. Тело лямбды может быть написано без блока тела и оператора return
, если это всего лишь выражение. Кроме того, для тех интерфейсов, которые имеют только один параметр в методе, круглые скобки можно опустить.
// Тот же вызов, что и выше, но с полностью указанными типами и блоком тела runCalculation ((int number, int otherNumber) ->{return number + otherNumber;}); // Функциональный интерфейс с методом, который имеет только один параметр interface StringExtender {String extendString (String input); } // Инициализация модели типа с помощью лямбда-выражения StringExtender extender = input ->input + "Extended";
Нет необходимости использовать лямбда-выражения, если уже существует именованный метод, совместимый с интерфейсом. Этот метод можно передать вместо лямбды, используя ссылку на метод. Существует несколько типов ссылок на методы:
Тип ссылки | Пример | Эквивалентная лямбда |
---|---|---|
Статический | Integer :: sum | (number, otherNumber) ->number + otherNumber |
Связанная | "LongString" :: подстрока | индекс ->"LongString". Подстрока (индекс) |
Несвязанная | String :: isEmpty | строка ->string.isEmpty () |
Конструктор класса | ArrayList | capacity ->new ArrayList |
Конструктор массива | String :: new | size ->new String [size] |
Приведенный выше код, который вызывает runCalculation
, можно заменить следующим, используя ссылки на методы:
runCalculation (Integer :: sum);
Интерфейсы могут наследоваться от других интерфейсов точно так же, как классы. В отличие от классов разрешено наследование от нескольких интерфейсов. В этом случае оно становится одним неоднозначным.
/ * Класс, реализующий этот интерфейс, должен реализовывать методы как ActionListener, так и RequestListener * / interface EventListener расширяет ActionListener, RequestListener {}
Java SE 8 представила методы по умолчанию для интерфейс, что позволяет использовать инструменты новые методы к существующим интерфейсам без нарушения совместимости с классами, уже реализующими интерфейс. В отличие от обычного метода интерфейса, методы по умолчанию, которые будут вызываться в случае, если реализующий класс не переопределит его.
интерфейс StringManipulator {String extendString (строки); // Метод, который является необязательным для реализации по умолчанию String ShortString (String input) {return input.substring (1); }} // Это допустимый класс, несмотря на то, что он не реализует все методы, которые класс PartialStringManipulator реализует StringManipulator {@Override public String extendString (String input) {return input + "Extended"; }}
Статические методы - это еще одна языковая функция, представленная в Java SE 8. Они ведут себя точно так же, как и в классах.
интерфейс StringUtils {статическая строка ShortByOneSymbol (строки) {return input.substring (1); }} StringUtils.shortenByOneSymbol («Тест»);
Частные методы были добавлены в выпуск Java 9. Интерфейс может иметь метод с телом, помеченным как частный, и в этом случае он не будет видим для наследующих классов. Его можно вызвать из методов по умолчанию для повторного использования кода.
интерфейс Logger {default void logError () {log (Level.ERROR); } по умолчанию void logInfo () {журнал (Level.INFO); } личный журнал недействительности (уровень уровня) {SystemLogger.log (level.id); }}
Аннотации в Java - это способ встраивать метаданные в код. Эта языковая функция была представлена в J2SE 5.0.
В Java есть набор предопределенных типов аннотаций, но разрешено определять новые. Объявление типа аннотации - это особый тип объявления интерфейса. Они являются так же, как интерфейсы, за исключением того, что объявляется ключевым словом интерфейс
предшествует знак @
. Все аннотации неявно расширяются из java.lang.annotation.Annotation
и не могут быть расширены из чего-либо еще.
@interface BlockingOperations {}
Аннотации могут иметь те же объявления в теле, что и обычные интерфейсы, кроме того, они могут включать перечисления и аннотации. Основное отличие состоит в том, что объявления абстрактных методов не должны иметь никаких параметров или вызывать исключения. Также они могут иметь значение по умолчанию, которое объявляется с использованием ключевого слова default
после имени метода:
@interface BlockingOperations {boolean fileSystemOperations (); логическое значение networkOperations () по умолчанию false; }
Аннотации могут использоваться в любом виде объявления, будь то пакет, класс (включая перечисления), интерфейс (включая аннотации), поле, метод, параметр, конструктор или локальный переменная. Также их можно использовать с константами перечисления. Аннотации объявляются с использованием знака @
перед именем типа аннотации, после чего пары элемент-значение записываются в скобках. Всем элементам без значения по умолчанию должно быть присвоено значение.
@BlockingOperations (/ * обязательный * / fileSystemOperations, / * необязательный * / networkOperations = true) void openOutputStream () {// Аннотированный метод}
Помимо общей формы, есть две другие формы для объявления аннотации, которые являются сокращениями. Аннотации маркеров - это краткая форма, она используется, когда элементам не присвоены значения:
@Unused // Сокращение для @Unused () void travelToJupiter () {}
Другая краткая форма называется аннотацией одного элемента. Он используется с типами аннотаций, содержащими только один элемент, или в случае, когда присутствует несколько элементов, но только один элемент не имеет значения по умолчанию. В форме аннотации с одним элементом имя элемента опускается, вместо него записывается только значение:
/ * Эквивалент для @BlockingOperations (fileSystemOperations = true). networkOperations имеет значение по умолчанию, и ему не нужно назначать значение * / @BlockingOperations (true) void openOutputStream () {}
Generics, или параметризованные типы, или параметрический полиморфизм - одна из основных функций, представленных в J2SE 5.0. До того, как были введены дженерики, требовалось явно объявить все типы. С помощью дженериков стало возможным одинаково работать с разными типами без объявления точных типов. Основная цель дженериков - обеспечение безопасности типов и обнаружение ошибок времени выполнения во время компиляции. В отличие от C #, информация об используемых параметрах недоступна во время выполнения из-за стирания типа .
Классы можно параметризовать, добавив переменную типа внутри угловых скобок (<
и >
) после имени класса. Это делает возможным использование этой переменной типа в членах класса вместо фактических типов. Может быть несколько переменных типа, и в этом случае они объявляются в списке, разделенном запятыми.
Можно ограничить переменную типа подтипом определенного класса или объявить интерфейс, который должен быть реализован этим типом. В этом случае к переменной типа добавляется ключевое слово extends
, за которым следует имя класса или интерфейса. Если переменная ограничена как классом, так и интерфейсом, или если существует несколько интерфейсов, сначала записывается имя класса, за которым следуют имена интерфейсов со знаком и
, используемым в качестве разделителя.
/ * Этот класс имеет два переменных типа, T и V. T должен быть подтипом ArrayList и реализовывать интерфейс Formattable * / public class Mapper{public void add (T array, V item) {// array имеет метод add, потому что это подкласс ArrayList array.add (item); }}
Когда объявляется переменная параметризованного типа или создается экземпляр, ее тип записывается точно в том же формате, что и в заголовке класса, за исключением того, что фактический тип записывается вместо объявления переменной типа.
/ * Mapper создается с CustomList как T и Integer как V. CustomList должен быть подклассом ArrayList и реализовывать Formattable * / Mappermapper = new Mapper ();
Начиная с Java SE 7, можно использовать ромб (<>
) вместо аргументов типа, и в этом случае последний будет выводиться. Следующий код в Java SE 7 эквивалентен коду из предыдущего примера:
Mappermapper = new Mapper <>();
При объявлении переменной для параметризованного типа можно использовать подстановочные знаки вместо явных имен типов. Подстановочные знаки выражаются записью знака ?
вместо фактического типа. Можно ограничить возможные типы подклассами или суперклассами определенного класса, написав ключевое слово extends
или ключевое слово super
, за которым следует имя класса.
/ * Любой экземпляр Mapper с CustomList в качестве первого параметра может использоваться независимо от второго. * / Mappermapper; mapper = новый Mapper (); mapper = новый Mapper (); / * Не принимает типы, которые используют что-либо, кроме подкласса Number в качестве второго параметра * / void addMapper (Mapper , ? extends Number>mapper) {}
Использование универсальных шаблонов может быть ограничено к некоторым конкретным методам это понятие применимо и к конструкторам. Чтобы объявить параметризованный метод, переменные типа записываются перед типом возвращаемого значения метода в том же формате, что и для универсальных классов. В случае конструктора переменные типа объявляются перед именем конструктора.
class Mapper {// Сам класс не является универсальным, конструктор -Mapper (T array, V item) {}} / * Этот метод принимает только массивы того же типа, что и тип искомого элемента или его подтип * / static boolean содержит (T item, V arr) {for (T currentItem: arr) {if (item.equals (currentItem)) {return true; }} return false; }
Интерфейсы можно параметризовать так же, как классы.
расширяемый интерфейс{void addItem (T item); } // Этот класс параметризован class Array реализует Expandable {void addItem (T item) {}} // А это не так, ивместо этого используется явный тип class IntegerArray реализует Expandable {void addItem ( Целочисленный элемент) {}}
В Викиучебнике есть книга по темам: Программирование / синтаксис Java |