Примитивные типы в Java

Идеальный объектно-ориентированный язык

Как уже говорилось ранее, Java – объектно-ориентированный язык. В Java есть классы (class), и есть объекты (object) – экземпляры заданного класса. Однако, Java не является идеальным объектно-ориентированным языком. Почему?

Давайте рассмотрим, как должен выглядеть идеальный объектно-ориентированный язык. Если бы Java была таковым, то все типы в ней были бы классами, все переменные – объектами, все действия с переменными – функциями. Например, тип целых чисел был бы неким классом, а все действия с целыми числами – методами этого класса. Описать это пришлось бы следующим образом:

public class Int {
    public void increment() {
    ...
    }
    public void add(Int n) {
    ...
    }
    ...
}

И, если мы хотим, к примеру, увеличить значение переменной n на 1, то вместо привычного

int n = 0;
n++;

необходимо было бы писать так:

Int n = new Int();
n.increment();

Таким образом, в идеальном объектно-ориентированном языке не должно быть никаких плюсов и прочих операций – их необходимо описывать как  методы класса. Не должно быть даже присваивания. И, соответственно, не должно быть никаких типов кроме классов. И вообще, в таком случае при создании объекта (например, «целого числа»), создавалась бы некоторая «коробочка», в которую помещалось бы наше некоторое значение, и каждая операция требовала бы «залезания» в эту «коробочку», поиска в ней нашего числа и уже потом произведения с ним определенного действия. Это занимало бы кучу времени. Но Java не является идеальным объектно-ориентированным языком, поэтому мы избежим всех этих неудобств.

Примитивные типы в Java

В Java существует 8 типов, кроме классов:

boolean логический тип
char символьный тип
byte целочисленные типы
short
int
long
float типы с плавающей точкой
double

Рассмотрим их подробнее.

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

Для всех типов, кроме boolean, определены операции сравнения:

операция обозначение
равенство ==
неравенство !=
больше >
меньше <
больше или равно >=
меньше или равно <=

Для типа boolean можно выполнять проверку на равенство/неравенство.

Особенностью типов float и double является значение NaN. NaN никогда не равно самому себе и ничему другому. Для проверки, является ли значением переменной (типа float/double) NaN, существуют специальные функции:

float f;
double d;
....
Float.isNaN(f);
Double.isNaN(d);

Преобразование типов

Иногда возникают ситуации, когда необходимо переменной одного типа присвоить значение переменной другого типа. Например:

int a = 1;
byte b = 2;
a = b;

Как поступать в этом случае? Все типы условно можно расположить «в порядке увеличения»:

byte < short < int < long < float < double

Если мы хотим переменой «большего» типа присвоить значение «меньшего» типа, то выполняем обычное присваивание:

int a = 1;
float f = 2.2f;
f = a;

Если же наоборот, переменной «меньшего» типа значение «большего», то надо указывать тип, в который мы преобразовываем:

int a = 1;
float f = 2.2f;
a = (int)f;

При этом дробная часть просто отбросится.

Преобразовывать число в переменную типа char всегда необходимо явно, а вот переменную типа char явно преобразовывают только в byte и short:

int a;
char c = '*', c1;
byte b;
a = c;
c1 = (char)a;
b = (byte)c1;

Небольшое отступление о кодировке Unicode

Как уже говорилось, переменные типа char в Java хранятся в кодировке Unicode. Еще недавно казалось, что любой символ помещается в 7 бит, т.е. для хранения одного символа достаточно 1 байта. Однако, в некоторых алфавитах символов больше, чем 256. Идея Unicode состоит в том, чтобы хранить 1 символ четырьмя байтами. Т.е. в такой кодировке помещается 232, что больше 4 млрд. символов. 

Существуют кодировки символов с постоянной длиной: UCS–2 (двухбайтовая кодировка) и UCS–4 (четырехбайтовая кодировка). В кодировке UCS–4 символ записывается, как есть, согласно стандарту Unicode. На самом деле в таблице Unicode количество всех символов меньше 216, и для записи символа в кодировке UCS–2, берётся его запись, согласно стандарту Unicode, и из неё выкидываются первые два байта. Также существует кодировка UTF–8, в которой разные символы записываются разным количеством байт. Наиболее часто встречающиеся – 1 байтом, менее встречающиеся – 2 байтами и совсем редко встречающиеся – 3 байтами.

Символ с номером, меньшим чем 128 записывается так:

0.......

Символ с номером большим, чем 128, но меньшим, чем 2048 – так:

110..... 10......

Символ с номером между 2048 и 65536 – так:

1110.... 10...... 10......

В данный момент любой символ в UTF-8 записывается не более чем 3 байтами.