Типы данных в Java

Тип данных - множество значений и набор операций с ними.

В Java, в отличие от Python, любое значение в коде программы имеет тип. Пример из python:

def f(x):
    print(x)  # какой тип? непонятно
    if x == 1:
        a = "abc"
    else:
        a = 42
    print(a)  # какой тип? непонятно

    print(a + 1)  # сломается, если строка

В Java типы переменных и любых выражений точно известны еще на этапе написания программы (на этапе компиляции).

При написании программы нужно четко представлять себе типы всех переменных и выражений.

Типы

Базовые типы

Целые: byte, short, int, long

Дробные: float, double

Логический: boolean

Символьный: char

Ровно 8 штук

Объектные типы

Их бесконечно много, потому что можно создавать свои. В ближайшее время будем изучать String, массивы. Потом File, Path, Scanner (читатель из файла) и т.д. до бесконечности.

Переменная

Перед тем как пользоваться переменной, ее нужно завести.

Синтаксис: ТИП ИМЯ;

int x; - переменная для хранения целых. char c; - перемененая для хранения символов. String s; - для хранения строк

В эти переменные можно записывать только тот тип, для которого она была создана:

int x;
x = "asdf";  //ошибка

Оператор присваивания: ИМЯ = ВЫРАЖЕНИЕ;

При введении переменной можно сразу присвоить ей значение (инициализорвать):

int x = 42;

Здесь совершаются два действия: создать, присвоить.

В 99% случаев при создании переменной можно сразу ее инициализировать.

Переменной, которой не присваивалось значение пользоваться нельзя.

int x;
sout(x); //ошибка!  sout - сокращение от
         //System.out.println

Это ошибка времени компиляции, т.е. программа не скомпилируется и, тем более, не запустится.

Аналогичный пример, тоже ошибка:

int x;
if (a == 42)
    x = 10;
sout(x);   // ошибка. x might not have been initialized
           // переменная, возможно, не была инициализирована

А вот так можно:

int x;
if (a == 42)
    x = 10;
else
    x = 11;
sout(x);

Целые типы и литералы целых типов

Литерал, напомним, это набор символов, обозначающий определенное значение определенного типа.

42 - это литерал типа int.

Целые числа записываются цифрами. Можно ставить минус в начале для отрицательных чисел. (Но минус - это оператор, а не часть литерала.)

42
123
-15
1000000
1_000_000  // подчеркивания в любом месте числа игнорируются
015        // это 15 в 8-ой с/счисления. Т.е. эквивалентно 13
019        // ошибка. В 8-ой системе нет 9.
13         // 100% эквивалентно 015
0xBEEF42   // 0x - начало 16-ой системы счисления.
0xFF0000   // цвет так можно кодировать

Это все значения типа int. В 99% случаев целое число вы будете хранить как тип int.

byte - 1 байт. Диапазон: -128..127 (всего 256 значений) Тип нужен чаще всего для хранения массива байт: содержимое файла, данные, пришедшие по сети и т.п.

short - 2 байта. -32768..32767 (мало значений) int - 4 байта. -2млрд..+2млрд long - 8 байт -410^18..+410^18.

3_000_000_000 - ошибка, нет такого литерала. Не влезает в int.

3_000_000_000L - буква L в конце - показатель литерала long.

42L - это тоже тип long, обычно не имеет смысла, потому что базовые типы легко превращаются друг в друга автоматически:

long x = 42;

Формально, здесь переменной типа long присваивается значение типа int. Здесь происходит автоматическое преобразование типа int в long. Есть фиксированные правила, какие базовые типы в какие могут превратиться, они достаточно естественны, не будем их приводить, кроме одного примера:

double x = 42; //можно целое превратить в вещественное
int x = 4.2; // наоборот - ошибка

Вещественные типы

float - 4 байта double - 8 байт

Примеры литералов

1.5  // double
1.5f // float
1.5F // float
0.1
1.
1.0  // эквивалентно предыдущему
1_000_000.001
1.23e9 // e9 или E9 = умножить на 10^9, перенести запятую
       // на 9 позиций вправо
2.39E-9 

Используйте double, если нет необходимости в экономии.

Логический тип

boolean, всего два значения. true и false.

boolean isGood = true;

Символьный тип

char. Произвольный Unicode символ (2 байта).

Записывается в одинарных кавычках (не двойных).

char c1 = 'x';
char c2 = '1';  //не 1
char с3 = '%';
char с4 = ' ';
char с5 = 'π'; // греческая буква
char c6 = '\n'; // символ перевода строки
char c7 = '\t'; // символ табуляции
char c8 = '\\'; // символ обратного слэша
char c9 = '\u03C0'; //после букву u 16-ый код символа
                    //100% эквивалентно 'π'

Cтроковый тип

Хранит последовательности символов. Записывается в двойных кавычках.

Итого, одинарные кавычки - char, двойные - String.

"abc"
""  //строка без символов
"abc\nxyz" //abc потом перевод строки потом xyz
"\u03C0\u03C0\u03C0" // строка из трех символов пи.
"πππ" // эквивалентно

Операции над значениями типов

Арифметические операции

+, -, *, /. Степени нет.

Деление с остатком: %.

Операции действуют в зависимости от типа:

1 + 2 // сложение чисел
"abc" + "xyz" // конкатенация (соединение) строк.
"abc" + 1 // разрешено конкатенировать строки и любые другие
          // типы. Получится "abc1". (все автоматически 
          // превращается в строку, если складывается со строкой)

"abc" + 1 + 2  // "abc12" (здесь 2 прибавляется к строке) 
1 + 2 + "abc"  // "3abc", 1 складывается с 2.

1 / 2      // деление целых. Операция получается целочисленная
           // ответ 0
1. / 2.    // а это уже деление вещественных. Ответ 0.5
1 / 2.     // Арифметические операции расширяют тип до большего,
           // поэтому 1 (int) преобразуется в 1 (double)

Приведение типа: (int)1.23 тип в скобках перед значением - это оператор приведения типа. Т.е. преобразуем тип в int. Дробная часть отбросится. Выше мы писали, что многие такие преобразования происходят автоматически.

Операции сравнения:

<, >, >=, <=

Сравнение чисел (и char, они автоматически превращаются в short?) Результат операции - тип boolean:

2 >= 3 результат операции это false.

10 >= 6 >= 1 В python так можно, это True. А в Java:

true >= 1, т.е. ошибка. Потому что 10 >= 6 посчиталось сначала.

Еще две операции:

== и !=

Это операторы проверки на равенство и неравенство. Они применяются к значениям любых типов. По смыслу соответствуют is в Python. Т.е. проверяют идентичность значений. Истина при сравнении будет, если сравниваются два одинаковых объекта. Если нужно сравнивать содержимое объектов, нужно действовать иначе, см. позже. Вывод. Строки нельзя сравнивать через ==. (Так же как в python мы не сравниваем строки через is).

Логические операторы

|| логическое или && логическое и ! логическое отрицание

Не используйте операторы | и &, потому что они имеют немного другой смысл как логические операторы. И их можно использовать как побитовые операторы для целых чисел (побитовое или, и).

Если есть выражение

x != 0 && y / x > 1

Это никогда не приводит к ошибке деления на ноль, потому что оператор && не вычисляет второй аргумент, если первый оказался false. Аналогично устроен ||

А вот выражение

x != 0 & y / x > 1

может привести к ошибке, потому что деление будет выполнено независимо от x.