@inponomarev
Иван Пономарёв, КУРС/МФТИ
Hello, World!
New Maven Project
New package
New class
psvm — sout
Манифест (runnable jar)
abstract continue for new switch
assert default if package synchronized
boolean do goto private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while
_ (underscore)
null true false
(Java 9)
open module requires transitive exports
opens to uses provides with
(Java 10)
var
(Java 14)
yield record
(Java 15)
sealed non-sealed permits
/**
* This is the first sample program in Core Java Chapter 3
* @version 1.01 1997-03-22
* @author Gary Cornell
*/
public class FirstSample
{
public static void main(String[] args)
{
/*multiline
comment*/
System
.out //single-line comment
.println("We will not use 'Hello, World!'");
}
}
Value
Примитивные
byte
, short
, int
, long
char
float
, double
,
boolean
Reference
Массивы
Объекты
null
, будь он неладен
Type | Storage | Range |
| 1 byte | –128 to 127 |
| 2 bytes | –32,768 to 32,767 |
| 4 bytes | –2,147,483,648 to 2,147,483, 647 |
| 8 bytes | –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
Long 100L
Underscores 1_000_000
Hexadecimal 0xCAFEBABE
Binary 0b0101
Octal 010
Type | Storage | Range |
| 4 bytes | Approximately ±3.40282347E+38F (6–7 significant decimal digits) |
| 8 bytes | Approximately ±1.79769313486231570E+308 (15 significant decimal digits) |
2.998e8
1.0
(1.
)
3.14F
0x1.0p-3
(0.125, 2 в минус третьей степени)
Double.POSITIVE_INFINITY
Double.NEGATIVE_INFINITY
Double.NaN
System.out.println(2.0 - 1.1)
выводит 0.8999999999999999
НИКОГДА НЕ СЧИТАЙТЕ ДЕНЬГИ DOUBLE-ОМ!
System.out.println(2.0 / 0.0)
выводит 'Infinity` (но 2 / 0 — divizion by zero)
System.out.println(0.0 / 0.0)
выводит 'NaN`
Сравнение с бесконечностью и NaN
не работает, надо проверять с помощью Double.isNaN
, Double.isInfinite
.
strictfp
double x = 9.997F; //float в double неявно
int nx = (int) x; //9
nx = (int) Math.round(x); //10
char
16 bit
code unit in the UTF-16 encoding
Не всегда целый символ (хотя почти всегда)!
Осторожней с Unicode, используйте String
char
'ы'
'\u03C0'
(греческая π)
'\''
(escaped single quote)
Ловушка Unicode Escape: // Look inside c:\users
String s = "Hello, world!";
//Before Java 13
String txt =
"Some\n" +
" Nested\n" +
" Text\n" +
" Is\n" +
"Here\n";
Some
Nested
Text
Is
Here
String txt = """
Some
Nested
Text
Is
Here
""";
//Максимальное число пробелов впереди убрано:
Some
Nested
Text
Is
Here
Escape sequence | Name | Unicode Value |
| Backspace | \u0008 |
| Tab | \u0009 |
| Linefeed | \u000a |
| Carriage return | \u000d |
| Double quote | \u0022 |
| Single quote | \u0027 |
| Backslash | \u005c |
| intentional whitespace (Java 13+) | |
| line continuation (Java 13+) |
boolean
true
и false
В отличие от C и многих других языков, целые числа не сводятся автоматически к boolean
Избегаем ошибок вида if (x = 0) {…
// декларация
double salary;
int vacationDays;
long earthPopulation;
boolean done;
// не очень приветствуется
int i, j;
// технически можно, но . . .
int суммаНДФЛ;
int vacationDays;
System.out.println(vacationDays); //COMPILATION ERROR
// variable not initialized
Возможные способы инициализации:
int vacationDays;
vacationDays = 12;
int vacationDays = 12;
final
(константы)final
используется в двух смыслах:
запрещает изменять значение
запрещает переопределять методы/классы
final int a;
...
a = 42; // инициализация
...
a = 43; // compilation error:
// variable a might already have been initialized
Место определения: класс, метод, блок
Нет ничего за пределами класса («глобальных» переменных)!
int n;
. . .
{
int k;
int n; // Error--can't redefine n in inner block
. . .
} // k is only defined up to here
var i = 1; // i is of int type
//BEFORE JAVA 10
URL codefx = new URL("http://codefx.org");
URLConnection connection = codefx.openConnection();
Reader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
//AFTER JAVA 10
var codefx = new URL("http://codefx.org");
var connection = codefx.openConnection();
var reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
Арифметические: +
, -
, *
, /
, %
Деление работает как целочисленное, если оба аргумента целочисленные
Унарные +
и -
.
|
| |
|
| |
|
| |
|
| |
|
| |
|
| старший (знаковый) бит сохраняется |
|
| старший (знаковый) бит заполняется нулём |
5 >> 32 == ?
5 >> 32 == 5
для int
используются только 5 младших бит второго операнда (0..31),
для long
используются только 6 младших бит второго операнда (0..63)
&
, |
, ^
, ~
<
<=
>
>=
instanceof
==
!=
Без короткого замыкания: &
, |
, ^
, !
(вместо тильды — восклицательный знак!)
С коротким замыканием &&
, ||
.
x != 0 && 1 / x > x + y // no division by 0
int x;
System.out.println(x = 42); //печатает 42
Пример использования:
while ((n = readValue()) != null)
... //делаем что-то с n
a++
, ++a
a--
, --a
+=
, -=
, *=
, /=
, %=
, &=
, |=
, ^=
, <<=
, >>=
, >>>=
ВНИМАНИЕ: может показаться, что эти операции атомарны. Но это не так.
x < y ? x : y
Operators | Associativity |
| Left to right |
| Right to left |
| Left to right |
| Left to right |
| Left to right |
| Left to right |
| Left to right |
Operators | Associativity |
| Left to right |
| Left to right |
| Left to right |
| Left to right |
| Left to right |
//У конъюнкции выше приоритет, чем у дизъюнкции, поэтому
a || b && c
// есть по сути
a || (b && c)
Operators | Associativity |
| Right to left |
| Right to left |
//Since += associates right to left, the expression
a += b += c
//means
a += (b += c)
//That is, the value of b += c
// (which is the value of b after the addition)
//is added to a.
А его нет!
Можно несколько statement-ов перечислить через запятую в блоке for(…)
, или в блоке try(…)
if
| ![]() |
if
+ block
| ![]() |
if
+ block + else
| ![]() |
else
группируется с ближайшим if
| ![]() |
else if
| ![]() |
switch
Та же ерунда, что и в C/C++:
| ![]() |
switch
-case
особенности:Не забываем break
-и (утилиты типа Checkstyle напоминают), иначе выполняем всё до конца switch
, как в C!
switch бывает: по целому, по char
-у, по String
-у (Java 7+) и по enum
-у.
JDK 12 & 13 — Preview Feature
JDK 14 — Standard Feature
int numLetters = switch(day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case SATURDAY -> 8;
default -> 9;
}
Expression | Statement |
|
|
Expression | Statement (Good Old C-style Switch) |
|
|
Из любого типа можно построить массив данного типа.
Длина массива может быть определена в runtime, но после создания не может быть изменена.
Массив аллоцируется в куче и передаётся по ссылке.
Массивы проверяют тип данных (ArrayStoreException
) и границы (ArrayIndexOutOfBoundsException
) в run-time.
Правда жизни: скорее всего, вы не будете использовать массивы в современном коде.
Два варианта:
int[] a
int a[]
— не делайте так
Инициализация:
int[] a = new int[100];
int[] a = {1, 3, 5};
анонимный массив: foo(new int[] {2, 4, 6});
int[] luckyNumbers = smallPrimes;
luckyNumbers[5] = 12; // теперь smallPrimes[5] тоже 12
luckyNumbers = Arrays.copyOf(luckyNumbers, 2 * luckyNumbers.length);
//теперь luckyNumbers это отдельный массив
//и он стал в два раза длиннее
String[] a = new String[1];
//компилируется. ведь строка это объект,
//и потому почему б не считать массив строк массивом объектов?
Object[] b = a;
//runtime ArrayStoreException
b[0] = 5;
(Всё это страшно не совместимо с дженериками и коллекциями, которые пытаются ловить ошибки типов во время компиляции, но об этом речь впереди.)
На самом деле их нет, но есть массивы массивов
| ![]() |
| ![]() |
while
: то же, что и в C
| ![]() |
final boolean flag = false;
. . .
while (flag) {
. . . //не скомпилируется, unreachable code
}
do while
: цикл с постусловием
| ![]() |
Правда жизни: do-while
бывает нужен очень, ОЧЕНЬ редко.
for
Снова всё то же, что и в C (по сути, сокращение цикла while
):
for (int i = 1; i <= 10; i++)
System.out.println(i);
И даже, хотя оператора «запятая» нет, можно так (но не нужно):
for (int i = 1; i <= 10; i++, j++)
System.out.println(i);
for (int i = 1; i <= 10; i++)
{
. . .
}
// i no longer defined here
int i;
for (i = 1; i <= 10; i++)
{
. . .
}
// i is still defined here
break
и continue
Прерывание цикла целиком:
while (years <= 100) {
balance += payment;
double interest = balance * interestRate / 100;
balance += interest;
if (balance >= goal) break;
years++;
}
Переход к следующему циклу:
Scanner in = new Scanner(System.in);
while (sum < goal) {
System.out.print("Enter a number: ");
n = in.nextInt();
if (n < 0) continue;
sum += n; // not executed if n < 0
}
goto
, но есть метки для break
и continue
!Scanner in = new Scanner(System.in);
int n;
// label is here!
read_data: while (. . .) {
. . .
for (. . .) {
System.out.print("Enter a number >= 0: ");
n = in.nextInt();
if (n < 0)
break read_data;
// break out of read_data loop
. . .
}
}
if (n < 0) {
// deal with bad situation
} else {
// carry out normal processing
}