<dependency>
<groupId>org.apache.commons</groupId> (1)
<artifactId>commons-csv</artifactId> (2)
<version>1.14.1</version> (3)
</dependency>@inponomarev
Иван Пономарёв, КУРС/МФТИ
Современный интернет адрес: company.com/product (com — top level domain, company — домен внутри com).
Более логичный вариант: com.company/product — постоянное движение от общего к частному — проиграл на заре Интернета по историческим причинам.
Reverse domain name notation — ключевая идея для именования пакетов и библиотек в Java, основанная на уникальности и понятном владении доменными именами.
Reverse domain notation + иерархическая система, которую можно модерировать внутри организации:
edu.phystech.foo
edu.phystech.foo.bar
Каждый .java-файл начинается с объявления пакета:
package edu.phystech.hello;
В корне пакета может быть файл package-info.java, не содержащий код, а только JavaDoc-описание над ключевым словом package.
<Имя пакета>.<имя класса> задаёт полный идентификатор любого класса, доступного в исходном коде или через библиотеки (например, edu.phystech.hello.App)
Пакеты физически — это дерево папок: edu/phystech/hello. Таким образом, в папке edu возможны подпапки edu/phystech и edu/berkley.
Пакеты логически — это плоский список. Два разных пакета полностью независимы, даже если визуально один является «подпакетом» другого.
Пример включения зависимости в Maven:
<dependency>
<groupId>org.apache.commons</groupId> (1)
<artifactId>commons-csv</artifactId> (2)
<version>1.14.1</version> (3)
</dependency>| 1 | домен огранизации в reverse notation (https://commons.apache.org/) |
| 2 | имя проекта |
| 3 | версия релиза, например в формате semver (https://semver.org/) |
То же самое в Groovy (Kotlin DSL):
implementation("org.apache.commons:commons-csv:1.14.1")Чтобы загрузить собственную библиотеку на Maven Central, нужно доказать владение доменом (например, прописав «магическое» значение в TXT-поле в DNS)
Благодаря давней и надёжной инфраструктуре защиты прав на доменные имена, мы гарантированы, что никто не опубликует библиотеку от имени Microsoft, Apple или Oracle.
Нет смысла «захватывать» красивые имена для библиотек или заниматься typosquatting-ом: у каждого своё пространство имён
Контраст с npm и PyPi: исчерпание «красивых» имён, typosquatting, проблемы с безопасностью. Зато — просто и изящно, в отличие от Java.
Проверьте mvn --version (по состоянию на осень 2026, Maven 3.9.x и Java 25.x)
Запустите
mvn archetype:generate \
-DarchetypeGroupId=org.atp-fivt \
-DarchetypeArtifactId=homework-quickstart \
-DarchetypeVersion=3.0Понадобится некоторое время, чтобы скачать и закешировать нужные библиотеки
Заполните groupId, (например, edu.phystech), artifactId ( например, homework1)
Примите значения по умолчанию для version и package
Исследуйте содержимое файла pom.xml и структуру папок. "Hello world" пример находится в App.java.
Запустите сборку с помощью mvn verify.
<build><plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration> (1)
<archive><manifest>
<mainClass>edu.phystech.App</mainClass>
</manifest></archive>
</configuration>
</plugin>| 1 | Plugin parameters |
java -jar target\helloworld-1.0-SNAPSHOT.jar
Hello World!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 falsevar var = 42;(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
(Java 21)
when/**
* 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); //10char16 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
HereEscape 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+) |
booleantrue и 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 herevar 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()));Арифметические: +, -, *, /, %
Деление работает как целочисленное, если оба аргумента целочисленные
Унарные + и -.
|
| |
|
| |
|
| |
|
| Дополнительный код (two’s complement), инверсия и добавление 1. |
|
| |
|
| старший (знаковый) бит сохраняется |
|
| старший (знаковый) бит заполняется нулём |
5 >> 32 == ?
5 >> 32 == 5
для int используются только 5 младших бит второго операнда (0..31),
для long используются только 6 младших бит второго операнда (0..63)
&, |, ^, ~
< <= > >= instanceof
== !=
Без короткого замыкания: &, |, ^, ! (вместо тильды — восклицательный знак!)
С коротким замыканием &&, ||.
x != 0 && 1 / x > x + y // no division by 0int x;
System.out.println(x = 42); //печатает 42Пример использования:
while ((n = readValue()) != null)
... //делаем что-то с na++, ++a
a--, --a
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=
ВНИМАНИЕ: может показаться, что эти операции атомарны. Но это не так.
x < y ? x : yOperators | 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(…) (дань уважения языку C):
double r;
for (int i = 0; i < 10; i++, r = Math.random()) {
}if | ![]() |
if + block | ![]() |
if + block + else | ![]() |
else группируется с ближайшим if | ![]() |
else if | ![]() |
switchПолностью совместим с классическим switch в языке C, но имеет мощные расширения. Пожалуй, наиболее сильно переработанная синтаксическая конструкция из унаследованных из C.
| ![]() |
switch-case особенности:Используя "C-style" switch, не забываем break-и (утилиты типа Checkstyle напоминают), иначе выполняем всё до конца switch, как в C!
Обычный switch бывает: по целому, по char-у, по String-у (Java 7+), по enum-у.
Бывает также switch c pattern matching (Java 21+), о котором мы расскажем в других лекциях.
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 hereint i;
for (i = 1; i <= 10; i++)
{
. . .
}
// i is still defined herebreak и 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;
read_data: while (. . .) { // <<<label is here!
. . .
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
}