Вводный курс. Язык программирования Java
- Вводный курс. Язык программирования Java
- Просмотров: 19658
5. Типы данных
Любые данные – константы, переменные, значения функций характеризуются в Jave типом данных.
Язык программирования Java является языком со строгой типизацией. Это означает, что все объекты программы (переменные, константы и т.д.) должны быть описаны до первого использования. Описания информируют транслятор, во-первых, о существовании используемых переменных и других объектов, во-вторых, указывают на свойства этих объектов.
Тип данных определяет:
-
- внутреннее представление данных в памяти компьютера;
- множество значений, которые могут принимать величины этого типа;
- операции, которые могут выполняться над величинами этого типа.
Введение типов данных является одной из базовых концепций языка Java, заключающейся в том, что при выполнении операции присваивания переменной значения выражения, переменная и выражение должны быть одного типа. Такая проверка выполняется компилятором, что значительно упрощает поиск ошибок и приводит к повышению надежности программы.
Множество типов данных языка Java обычно делят на две группы:
-
- Примитивные – primitive
- Ссылочные – reference
Ссылочные типы являются объектами. Примитивные типы – это скалярные величины. В языках программирования, не являющихся объектно-ориентированными, примитивные типы называют простыми типами.
Примитивный тип данных (Primitive)
Примитивные типы Java не являются объектами. Всего их восемь, к ним относятся: byte, short, int, long, float, double, charи boolean.
Каждый примитивный тип как член класса имеет значение по умолчанию:
Примитивный тип | Значение по умолчанию |
byte, short, int, long | 0 |
float | 0.0F |
double | 0.0D |
char | 0; или ‘\u0000’ |
boolean | false |
Если использовать локальную переменную без инициализации компилятор выдаст ошибку.
Пример.
В классе объявим несколько полей класса примитивного типа без инициализации, в конструкторе выведем их значения.
public class Test {
int x;
char ch;
boolean f;
double d;
// конкструтор
public Test()
{
System.out.println("x=" + x);
System.out.println("ch=" + ch);
System.out.println("f=" + f);
System.out.println("d=" + d);
}
}
На экран будет выведено:
x=0
ch=
f=false
d=0.0
Далее, добавим в класс метод Metod(), объявим в нем переменную i примитивного типа также без инициализации - это локальная переменая и попробуем вывести ее значение.
public class Test {
int x;
char ch;
boolean f;
double d;
// конкструтор
public Test()
{
System.out.println("x=" + x);
System.out.println("ch=" + ch);
System.out.println("f=" + f);
System.out.println("d=" + d);
}
// добавим некоторый метод
public void Metod()
{
int i; //локальная переменная не инициализирована
System.out.println("i=" + i); // компилятор выдаст ошибку
}
}
Компилятор выдаст ошибку: «variable i might not have been initialized» - переменная i, возможно, не была инициализирована и предложит выполнить ее инициализацию.
Логический тип
В Java переменные логического типа задаются с помощью ключевого слова boolean и могут иметь лишь одно из двух значений: true или false.
Тип boolean занимает в памяти 8 бит.
В Java в отличие от C и C++ константа true не равна 1, а константа false не равна 0.
B Java значения true и false могут быть присвоены только тем переменным, которые объявлены как boolean, или использоваться в выражениях с булевскими операциями. Например, логическое выражение, которое должно быть истинно, если значение х попадает в интервал [x1, x2], должно быть записано следующим образом:
х>=x1 && х<=x2
Чтобы сделать выражение хорошо читаемым, используют скобки
(х>=x1) && (х<=x2)
Вот пример.
boolean isInRange;
int x1= 1;
int x2=5;
int x=3;
isInRange = x>x1 && x<x2;
System.out.println("Внутри диапазона: " +isInRange);
Будет выведено:
Внутри диапазона: true
Целочисленный тип
Целые типы различаются по размеру отведенной для них памяти:
- byte - 8-разрядное целое число
- short - 16-разрядное целое число
- int - 32-разрядное целое число
- long - 64-разрядное целое число
- char - 16-разрядное беззнаковое целое, представляющее собой символ UTF-16 (буквы и цифры)
Тип | Размер (бит) битах | Минимальное значение | Максимальное значение |
byte |
8 (знаковое) |
-128 |
127 |
short |
16(знаковое) |
-32768 |
32767 |
int |
32(знаковое) |
-2147483648 |
2147483647 |
long |
64(знаковое) |
-922372036854775808 |
922372036854775807 |
char |
16(без знаковое) |
0 |
65536 |
Символьный тип
Для работы с символами в Java используется тип данных char, в котором символ представлен в 16-битным значением в Unicode-таблице.
Unicode (Юникод) - это стандарт кодирования символов, который позволяет предоставить знаки всех языков мира. Каждый символ представлен двумя байтами, которые позволяют хранить в себе число от нуля до 65535, что и позволяет использовать 65536 различных символов.
Диапазон допустимых значений этого типа от 0 до 65536. Не существует отрицательных значений типа char. Над переменными символьного типа допустимо выполнение арифметических операций.
Вот небольшой пример.
char ch1, ch2, ch3, ch4;
int kod;
int sum;
ch1 = 'A'; // Записываем в переменную ch1 символ A
ch2 = 65; // переменной ch2 также присваивается символ A. Его Unicode код равен 65
ch3 = 'B'; // Записываем в переменную ch3 символ B, его код 66
ch4 = 'C'; // Записываем в переменную ch3 символ C, его код 67
kod=(int)ch1; //получаем код переменной по символу из Unicode-таблицы
System.out.println(ch1 + " " + ch2 + " "+ kod ); //будет выведено: A A 65
// находим сумму
sum =ch2 + ch3 + ch4; // выполняется сложение кодов: 65 + 66 + 67 = 198
System.out.println(sum); //будет выведено 198
//по коду найдем символ
System.out.println((char)sum); //будет выведен символ E
Символьный тип данных допускает и логические операции. Вот пример.
boolean f;
f= ch3>ch1; // код 67 > 65
System.out.println(f); //будет выведено true
Переменная f примет значение true потому, что символ ch1 имеет код меньше чем символ ch3: ch1 расположен по алфавиту и в Unicode-таблице также раньше символа ch3.
Вещественные типы
Значения вещественных типов в компьютере представляются приближенно. Диапазон изменения данных вещественного типа определяется двумя типами: float -вещественный с одинарной точностью, double - двойной точностью.
Тип | Разрядность (бит) | Диапазон | Точность |
float | 32 | 3,4e-38 < … < 3,4e38 | 7-8 цифр |
double | 64 | 1,7e-308 < …< 1,7e308 | 17 цифр |
Вещественные числа могут быть представлены в двух форматах: с фиксированной и плавающей точкой.
Формат записи числа с фиксированной точкой совпадает с обычной математической записью десятичного числа с дробной частью. Дробная часть отделяется от целой части с помощью точки, например
34.5, -4.0, 77.001, 100.56
Формат записи с плавающей точкой применяется при записи очень больших или очень малых чисел. В этом формате число, стоящее перед символом «E», умножается на число 10 в степени, указанной после символа «E». Вот примеры.
Запись с плавающей точкой | Математическая запись |
1E-4 | 1*10-4 |
3.4574E+3 | 3.4574*10+3 |
4.51E+1 | 4.51*10+1 |
Примеры чисел с плавающей точкой:
Число | Запись на Java |
0,0001 | 1E-4 |
3457,4 | 34574E-1 |
double vx =1E-4;
double vy =7.94E+4;
double vz = 34574E-1;
System.out.println(vx); // будетвыведено 1.0E-4
System.out.println(vy); // будетвыведено 79400.0
System.out.println(vz); // будетвыведено 3457.4
Стандартные математические функции возвращают тип double, численные константы по умолчанию также определены как double. Чтобы задать число типа float, необходимо добавить в его конец символ "f" или символ "F".
Примеры объявления переменных с плавающей точкой:
float x = 3.5f;
float y = 4.94E+1f;
double z = 1.0.
Ссылочный тип данных. (Reference)
Ссылочным типом называются тип, для которого в ячейке памяти содержится не сами данные, а только адреса этих данных, то есть ссылки на данные.
Ссылочные типы в языке Java включают:
-
- Массивы
- Классы
- Интерфейсы
- Перечисления
Свойства ссылочного типа данных:
-
- При выполнении операции присваивания в ссылочную переменную заносится адрес данных, а не сами данные.
-
- Если ссылочной переменной не присвоено значение - адрес данных, в ней хранится null.
-
- null – это зарезервированное слово, в котором храниться нулевой адрес. Любому ссылочному типу может быть присвоено значение null. Поскольку null хранит адрес, то естественно мы не можем присвоить null переменной любого примитивного типа: byte, short, int, long, float, double, char и boolean.
-
- Все ссылочные переменные изначально инициализируются значением null.
-
- Непосредственного доступа к адресу, хранящемуся в ссылочных переменных нет.
-
- Ссылки можно присваивать друг другу, если они совместимы по типам, а также присваивать значение null. При этом из одной ссылочной переменной в другую копируется адрес.
-
- Ссылочные переменные можно сравнивать на равенство, в том числе на равенство null. При этом сравниваются не данные, а их адреса, хранящиеся в ссылочных переменных.
Различие примитивных и ссылочных типов данных
Возьмем примитивный тип int и рассмотрим следующий код:
int a=5; // объявляем первую переменную и инициализируем ее
int b=a; // объявляем вторую переменную, далее присваиваем b=a.
//В этой операции выполняется копирование значения ячейки а в ячейку b
a=3; // меняем значение первой переменной
// выводим значение переменной a
System.out.println(“a= “ + a); // будетвыведено a= 3
// выводим значение переменной b
System.out.println(“b= “ + b); // будет выведено b= 5
Из данного примера следует, что при выполнении операции присвоения для переменных, имеющих примитивный тип, выполняется копирование данных из одной ячейки памяти в другую.
Выполним операцию присвоения (копирования) для ссылочных переменных. Для этого напишем простой класс Point -точка на плоскости, имеющая координаты x и y.
public static class Point{
public int x; //координататочки x
public inty; //координата тоски y
//конструктор
Point(int X, int Y) {
x=X;
y=Y;
}
}
Создадим несколько объектов класса Point и выполним операцию присвоения.
//cоздаем объект – первую точку
//при выполнении данной операции будет
//создана переменная объектного типа p1,
//которая будет содержать адрес объекта
Point p1 = new Point(1,1);
//создаем переменную p2 и выполняем
//операцию присваивания
Point p2=p1;
//меняем координату x первого объекта
p1.x=7;
//выводим координаты первого и второго объекта
System.out.println("p1.x="+ p1.x);
System.out.println("p1.y="+ p1.y);
System.out.println("p2.x="+ p2.x);
System.out.println("p3.y="+ p2.y);
System.out.println("---------");
//создаем переменную p3 и выполняем
Point p3 = null;
//создаем третий объект
p3= new Point(3,3);
//выполняем операцию присваивания
//теперь все переменные указывают на
//третий объект
p2=p3;
p1=p3;
System.out.println("p3.x="+ p3.x);
System.out.println("p3.y="+ p3.y);
//выводим коорлинаты
System.out.println("---------");
System.out.println("p1.x="+ p1.x);
System.out.println("p1.y="+ p1.y);
System.out.println("p2.x="+ p2.x);
System.out.println("p3.y="+ p2.y);
System.out.println("---------");
буудет выведено:
p1.x=7
p1.y=1
p2.x=7
p3.y=1
---------
p3.x=3
p3.y=3
---------
p1.x=3
p1.y=3
p2.x=3
p3.y=3
---------
Из данного примера следует, что при выполнении операции присвоения применительно к ссылочным переменным копируются адреса, а не сами данные. В данном примере мы получили, что все объектные переменные ссылаются на третий объект. Первый объект остался существовать, но на него никто не ссылается. Более того, адрес первого объекта нигде не сохранился, и поэтому это потерянный объект, другими словами «мусор», который только занимает память.