Базовые конструкции программирования
Понятие синтаксиса и семантики языков программирования
Переменные, типы данных, выражения и присваивание значений переменным
Представление данных в памяти компьютера: биты, байты и т.п.
Простейший ввод/вывод
Условные конструкции и их разновидности
Итеративные конструкции (циклы)
Синтаксис языка программирования — набор правил, описывающий комбинации символов алфавита, считающиеся правильно структурированной программой (документом) или её фрагментом. Синтаксису языка противопоставляется его семантика. Синтаксис языка описывает «чистый» язык, в то же время семантика приписывает значения (действия) различным синтаксическим конструкциям.
Каждый язык программирования имеет синтаксическое описание как часть грамматики. Синтаксис языка можно описать, например, с помощью правил Бэкуса — Наура.
Синтаксис проверяется на ранних стадиях трансляции. В интерпретируемых языках программирования проверка синтаксиса производится или в процессе интерпретации (выполнения), или в процессе предварительной компиляции в промежуточный код. Кроме того, синтаксис может проверяться непосредственно при редактировании исходных текстов программ при использовании IDE.
Переменная — поименованная, либо адресуемая иным способом область памяти, адрес которой можно использовать для осуществления доступа к данным. Данные, находящиеся в переменной (то есть по данному адресу памяти), называются значением этой переменной.
Локальные и глобальные переменные. Области видимости
По зоне видимости различают локальные и глобальные переменные. Первые доступны только конкретной подпрограмме, вторые — всей программе. С распространением модульного и объектного программирования, появились ещё и общие переменные (доступные для определённых уровней иерархии подпрограмм). Область видимости иногда задаётся классом памяти. Ограничение видимости может производиться путём введения пространств имён.
Ограничение зоны видимости придумали как для возможности использовать одинаковые имена переменных (что разумно, когда в разных подпрограммах переменные выполняют похожую функцию), так и для защиты от ошибок, связанных с неправомерным использованием переменных (правда, для этого программист должен владеть и пользоваться соответствующей логикой при структуризации данных).
Простые и сложные переменные
По наличию внутренней структуры, переменные могут быть простыми или сложными (составными).
Простые переменные не имеют внутренней структуры, доступной для адресации. Последняя оговорка важна потому, что для компилятора или процессора переменная может быть сколь угодно сложной, но конкретная система (язык) программирования скрывает от программиста её внутреннюю структуру, позволяя адресоваться только «в целом».
Сложные переменные - программист создаёт для хранения данных, имеющих внутреннюю структуру. Соответственно, есть возможность обратиться напрямую к любому элементу.
Самыми характерными примерами сложных типов являются массив (все элементы однотипные) и запись (элементы могут иметь разный тип).
Следует подчеркнуть относительность такого деления: для разных программ одна и та же переменная может иметь разную структуру.
Например, компилятор различает в переменной вещественного типа 4 поля: знаки мантиссы и порядка, плюс их значения, но для программиста, компилирующего свою программу, вещественная переменная — единая ячейка памяти, хранящая вещественное число.
Переменные - это контейнеры для хранения значений данных.
В Java есть разные типы переменных, например:
String - сохраняет текст, например «Привет». Строковые значения заключены в двойные кавычки.
int - хранит целые числа без десятичных знаков, например 123 или -123
float - хранит числа с плавающей запятой с десятичными знаками, например 19,99 или -19,99
char - хранит отдельные символы, такие как «a» или «B». Значения символов заключены в одинарные кавычки.
boolean - сохраняет значения с двумя состояниями: истина или ложь
Чтобы создать переменную, вы должны указать тип и присвоить ему значение:
Синтаксис
type variableName = value;
Где type - это один из типов Java (например, int или String), а variableName - это имя переменной (например, x или name). Знак равенства используется для присвоения значений переменной.
Как создать переменную, которая должна хранить текст
Create a variable called name of type and assign it the value "John":
String name = "John";
System.out.println(name);
Создайте переменную myNum типа int и присвойте ей значение 15:
int myNum = 15;
System.out.println(myNum);
Вы также можете объявить переменную без присвоения значения и присвоить значение позже:
int myNum;
myNum = 15;
System.out.println(myNum);
Обратите внимание, что если вы присвоите новое значение существующей переменной, оно перезапишет предыдущее значение:
int myNum = 15;
myNum = 20; // myNum is now 20
System.out.println(myNum);
Однако вы можете добавить ключевое слово final, если вы не хотите, чтобы другие (или вы) перезаписывали существующие значения (это объявит переменную как «final» или «постоянную», что означает неизменяемую и доступную только для чтения)
final int myNum = 15;
myNum = 20; // will generate an error: cannot assign a value to a final variable
int myNum = 5;
float myFloatNum = 5.99f;
char myLetter = 'D';
boolean myBool = true;
String myText = "Hello";
Отображение переменных
Метод println() часто используется для отображения переменных.
Чтобы объединить текст и переменную, используйте символ +:
String name = "John";
System.out.println("Hello " + name);
Вы также можете использовать символ +, чтобы добавить переменную к другой переменной:
String firstName = "John ";
String lastName = "Doe";
String fullName = firstName + lastName;
System.out.println(fullName);
Для числовых значений символ + работает как математический оператор (обратите внимание, что здесь мы используем переменные типа int (целые)):
int x = 5;
int y = 6;
System.out.println(x + y); // Print the value of x + y
Из приведенного выше примера вы можете ожидать:
х хранит значение 5
у хранит значение 6
Затем мы используем метод println() для отображения значения x + y, равного 11.
Чтобы объявить более одной переменной одного типа, используйте список, разделенный запятыми:
int x = 5, y = 6, z = 50;
System.out.println(x + y + z);
Одно значение для нескольких переменных
Вы также можете присвоить одно и то же значение нескольким переменным в одной строке:
int x, y, z;
x = y = z = 50;
System.out.println(x + y + z);
Идентификаторы
Все переменные Java должны иметь уникальные имена.
Эти уникальные имена называются идентификаторами.
Идентификаторы могут быть короткими именами (например, x и y) или более описательными именами (age, sum, totalVolume).
Примечание: рекомендуется использовать описательные имена для создания понятного и поддерживаемого кода:
// Good
int minutesPerHour = 60;
// OK, but not so easy to understand what m actually is
int m = 60;
Общие правила именования переменных следующие:
Имена могут содержать буквы, цифры, символы подчеркивания и знаки доллара.
Имена должны начинаться с буквы
Имена должны начинаться со строчной буквы и не должны содержать пробелов.
Имена также могут начинаться с $ и _
Имена чувствительны к регистру («myVar» и «myvar» — разные переменные)
Зарезервированные слова (например, ключевые слова Java, такие как int или boolean) не могут использоваться в качестве имен.
Как объяснялось в предыдущей главе, переменная в Java должна иметь указанный тип данных:
int myNum = 5; // Integer (whole number)
float myFloatNum = 5.99f; // Floating point number
char myLetter = 'D'; // Character
boolean myBool = true; // Boolean
String myText = "Hello"; // String
Типы данных делятся на две группы:
Примитивные типы данных — включают byte, short, int, long, float, double, boolean и char.
Непримитивные типы данных, такие как String, Arrays и Classes.
Примитивные типы данных
Примитивный тип данных определяет размер и тип значений переменных и не имеет дополнительных методов.
В Java существует восемь примитивных типов данных:
Data Type Size Description
byte 1 byte from -128 to 127
short 2 bytes from -32,768 to 32,767
int 4 bytes -2,147,483,648 to 2,147,483,647
long 8 bytes from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
float 4 bytes fractional numbers. Sufficient for storing 6 to 7 decimal digits
double 8 bytes fractional numbers. Sufficient for storing 15 decimal digits
boolean 1 bit true or false values
char 2 bytes Stores a single character/letter or ASCII values
Примитивные числовые типы делятся на две группы:
Целочисленные типы хранят целые числа, положительные или отрицательные (например, 123 или -456), без десятичных знаков. Допустимые типы: byte, short, int и long. Какой тип использовать, зависит от числового значения.
Типы с плавающей запятой представляют числа с дробной частью, содержащей один или несколько десятичных знаков. Есть два типа: float и double.
Byte
Тип данных byte может хранить целые числа от -128 до 127. Его можно использовать вместо int или других целочисленных типов для экономии памяти, если вы уверены, что значение будет в пределах от -128 до 127:
byte myNum = 100;
System.out.println(myNum);
Short
Тип данных short может хранить целые числа от -32768 до 32767:
short myNum = 5000;
System.out.println(myNum);
Int
Тип данных int может хранить целые числа от -2147483648 до 2147483647. В целом и в нашем учебнике тип данных int является предпочтительным типом данных, когда мы создаем переменные с числовым значением.
int myNum = 100000;
System.out.println(myNum);
Long
Тип данных long может хранить целые числа от -9223372036854775808 до 9223372036854775807. Он используется, когда int недостаточно велик для хранения значения. Обратите внимание, что вы должны закончить значение буквой «L»:
long myNum = 15000000000L;
System.out.println(myNum);
Floating Point Types
Тип данных с плавающей запятой может хранить дробные числа от 3,4e-038 до 3,4e + 038. Обратите внимание, что вы должны закончить значение буквой «f»:
float myNum = 5.75f;
System.out.println(myNum);
Double
Тип данных double может хранить дробные числа от 1,7e-308 до 1,7e + 308. Обратите внимание, что вы должны закончить значение буквой «d»:
double myNum = 19.99d;
System.out.println(myNum);
Число с плавающей запятой также может быть научным числом с буквой "e" для обозначения степени 10:
float f1 = 35e3f;
double d1 = 12E4d;
System.out.println(f1);
System.out.println(d1);
Booleans
Логический тип данных объявляется с помощью ключевого слова boolean и может принимать только значения true или false:
boolean isJavaFun = true;
boolean isFishTasty = false;
System.out.println(isJavaFun); // Outputs true
System.out.println(isFishTasty); // Outputs false
Логические значения в основном используются для условного тестирования.
Characters
Тип данных char используется для хранения одного символа. Символ должен быть заключен в одинарные кавычки, например 'A' или 'c':
char myGrade = 'B';
System.out.println(myGrade);
Strings
Тип данных String используется для хранения последовательности символов (текста). Строковые значения должны быть заключены в двойные кавычки:
String greeting = "Hello World";
System.out.println(greeting);
Непримитивные типы данных
Непримитивные типы данных называются ссылочными типами, поскольку они относятся к объектам.
Основное различие между примитивными и непримитивными типами данных:
Примитивные типы предопределены (уже определены) в Java. Непримитивные типы создаются программистом и не определяются Java (за исключением String).
Непримитивные типы можно использовать для вызова методов для выполнения определенных операций, а примитивные типы — нет.
Примитивный тип всегда имеет значение, в то время как непримитивные типы могут быть нулевыми.
Примитивный тип начинается со строчной буквы, а непримитивные типы начинаются с прописной буквы.
Размер примитивного типа зависит от типа данных, в то время как не примитивные типы имеют одинаковый размер.
Примерами непримитивных типов являются строки, массивы, классы, интерфейс и т. д.
Приведение типов
Приведение типов — это когда вы присваиваете значение одного примитивного типа данных другому типу.
В Java существует два типа приведения:
Расширение Casting (автоматически) - преобразование меньшего шрифта в больший размер шрифта
byte -> short -> char -> int -> long -> float -> double
Сужающий Casting (вручную) - преобразование типа большего размера в тип меньшего размера
double -> float -> long -> int -> char -> short -> byte
Расширяющийся Casting
Расширение приведения выполняется автоматически при передаче типа меньшего размера в тип большего размера:
public class Main {
public static void main(String[] args) {
int myInt = 9;
double myDouble = myInt; // Automatic casting: int to double
System.out.println(myInt); // Outputs 9
System.out.println(myDouble); // Outputs 9.0
}
}
Сужение Casting
Сужающее приведение нужно делать вручную, помещая тип в круглых скобках перед значением:
public class Main {
public static void main(String[] args) {
double myDouble = 9.78d;
int myInt = (int) myDouble; // Manual casting: double to int
System.out.println(myDouble); // Outputs 9.78
System.out.println(myInt); // Outputs 9
}
}
Операторы используются для выполнения операций с переменными и значениями.
В приведенном ниже примере мы используем оператор + для сложения двух значений:
int x = 100 + 50;
Хотя оператор + часто используется для сложения двух значений, как в приведенном выше примере, его также можно использовать для сложения переменной и значения или переменной и другой переменной:
int sum1 = 100 + 50; // 150 (100 + 50)
int sum2 = sum1 + 250; // 400 (150 + 250)
int sum3 = sum2 + sum2; // 800 (400 + 400)
Java делит операторы на следующие группы:
Арифметические операторы
Операторы присваивания
Операторы сравнения
Логические операторы
Побитовые операторы
Арифметические операторы
Арифметические операторы используются для выполнения общих математических операций.
Operator Name Description Example
+ Addition Adds together two values x + y
- Subtraction Subtracts one value from another x - y
* Multiplication Multiplies two values x * y
/ Division Divides one value by another x / y
% Modulus Returns the division remainder x % y
++ Increment Increases the value of a variable by 1 ++x
-- Decrement Decreases the value of a variable by 1 --x
Операторы присваивания Java
Операторы присваивания используются для присвоения значений переменным.
В приведенном ниже примере мы используем оператор присваивания (=), чтобы присвоить значение 10 переменной с именем x:
int x = 10;
Оператор сложения присваивания (+=) добавляет значение к переменной:
int x = 10;
x += 5;
Operator Example Same As
= x = 5 x = 5
+= x += 3 x = x + 3
-= x -= 3 x = x - 3
*= x *= 3 x = x * 3
/= x /= 3 x = x / 3
%= x %= 3 x = x % 3
&= x &= 3 x = x & 3
|= x |= 3 x = x | 3
^= x ^= 3 x = x ^ 3
>>= x >>= 3 x = x >> 3
<<= x <<= 3 x = x << 3
Операторы сравнения Java
Операторы сравнения используются для сравнения двух значений:
Operator Name Example
== Equal to x == y
!= Not equal x != y
> Greater than x > y
< Less than x < y
>= Greater than or equal to x >= y
<= Less than or equal to x <= y
Логические операторы Java
Логические операторы используются для определения логики между переменными или значениями:
Operator Name Description Example
&& Logical and Returns true if both statements are true x < 5 && x < 10
|| Logical or Returns true if one of the statements is true x < 5 || x < 4
! Logical not Reverse the result, returns false if the result is true !(x < 5 && x < 10)
Строки используются для хранения текста.
Переменная String содержит набор символов, заключенных в двойные кавычки:
String greeting = "Hello";
Длина строки
Строка в Java на самом деле является объектом, который содержит методы, которые могут выполнять определенные операции со строками. Например, длину строки можно узнать с помощью метода length():
String txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
System.out.println("The length of the txt string is: " + txt.length());
Дополнительные строковые методы
Доступно множество строковых методов, например toUpperCase() и toLowerCase():
String txt = "Hello World";
System.out.println(txt.toUpperCase()); // Outputs "HELLO WORLD"
System.out.println(txt.toLowerCase()); // Outputs "hello world"
Поиск символа в строке
Метод indexOf() возвращает индекс (положение) первого вхождения указанного текста в строку (включая пробелы):
String txt = "Please locate where 'locate' occurs!";
System.out.println(txt.indexOf("locate")); // Outputs 7
Java считает позиции с нуля.
0 — первая позиция в строке, 1 — вторая, 2 — третья...
Конкатенация строк
Оператор + можно использовать между строками для их объединения. Это называется конкатенацией:
String firstName = "John";
String lastName = "Doe";
System.out.println(firstName + " " + lastName);
Обратите внимание, что мы добавили пустой текст (""), чтобы создать пробел между именем и фамилией при печати.
Вы также можете использовать метод concat() для объединения двух строк:
String firstName = "John ";
String lastName = "Doe";
System.out.println(firstName.concat(lastName));
Добавление чисел и строк
ПРЕДУПРЕЖДЕНИЕ!
Java использует оператор + как для сложения, так и для конкатенации.
Добавляются числа. Строки объединены.
Если вы добавите два числа, результатом будет число:
int x = 10;
int y = 20;
int z = x + y; // z will be 30 (an integer/number)
Если вы добавите две строки, результатом будет конкатенация строк:
String x = "10";
String y = "20";
String z = x + y; // z will be 1020 (a String)
Если вы добавите число и строку, результатом будет конкатенация строк:
String x = "10";
int y = 20;
String z = x + y; // z will be 1020 (a String)
Специальные символы
Поскольку строки должны быть заключены в кавычки, Java неправильно поймет эту строку и выдаст ошибку:
String txt = "We are the so-called "Vikings" from the north.";
Чтобы избежать этой проблемы, используйте escape-символ обратной косой черты.
Экранирующий символ обратной косой черты (\) превращает специальные символы в строковые символы:
Escape character Result Description
\' ' Single quote
\" " Double quote
\\ \ Backslash
Последовательность \" вставляет в строку двойную кавычку:
String txt = "We are the so-called \"Vikings\" from the north.";
Последовательность \' вставляет одинарную кавычку в строку:
String txt = "It\'s alright.";
Последовательность \\ вставляет в строку одну обратную косую черту:
String txt = "The character \\ is called backslash.";
Шесть других escape-последовательностей допустимы в Java:
Code Result
\n New Line
\r Carriage Return
\t Tab
\b Backspace
\f Form Feed
Math.max(x,y)
Math.max(5, 10);
Math.min(x,y)
Math.min(5, 10);
Math.sqrt(x)
The Math.sqrt(x) method returns the square root of x:
Math.sqrt(64);
Math.abs(x)
Math.abs(-4.7);
Random Numbers
xample
int randomNum = (int)(Math.random() * 101); // 0 to 100
Очень часто в программировании вам понадобится тип данных, который может иметь только одно из двух значений, например:
YES / NO
ON / OFF
TRUE / FALSE
Для этого Java имеет логический тип данных, который может принимать true или false.
Булевые значения Javaboolean isJavaFun = true;
boolean isFishTasty = false;
System.out.println(isJavaFun); // Outputs true
System.out.println(isFishTasty); // Outputs false
Логическое выражение
int x = 10;
int y = 9;
System.out.println(x > y); // returns true, because 10 is higher than 9
System.out.println(10 > 9); // returns true, because 10 is higher than 9
В следующих примерах мы используем оператор равенства (==) для вычисления выражения:
int x = 10;
System.out.println(x == 10); // returns true, because the value of x is equal to 10
System.out.println(10 == 15); // returns false, because 10 is not equal to 15
Используйте оператор if, чтобы указать блок кода Java, который будет выполняться при условии true.
if (condition) {
// block of code to be executed if the condition is true
}
if (20 > 18) {
System.out.println("20 is greater than 18");
}
Мы также можем проверить переменные:
int x = 20;
int y = 18;
if (x > y) {
System.out.println("x is greater than y");
}
Условия Java и операторы If
Java поддерживает обычные логические условия по математике:
Less than: a < b Меньше чем: a <b
Less than or equal to: a <= b Менше або дорівнює: a <= b
Greater than: a > b Больше: a> b
Greater than or equal to: a >= b Больше или равно: a> = b
Equal to a == b Равно: a == b
Not Equal to: a != b Не равняется: a! = B
Java имеет следующие условные операторы:
Используйте if, чтобы указать блок кода, который будет выполнен, если указанное истинное условие
Используйте else, чтобы указать блок кода, который будет выполнен, если то же условие ошибочно
Используйте else if, чтобы указать новое условие для проверки, если первое условие ошибочно
Используйте switch, чтобы указать много альтернативных блоков кода для выполнения
else оператор
Используйте оператор else, чтобы указать блок кода, который будет выполнен при условии false.
if (condition) {
// block of code to be executed if the condition is true
} else {
// block of code to be executed if the condition is false
}
int time = 20;
if (time < 18) {
System.out.println("Good day.");
} else {
System.out.println("Good evening.");
}
// Outputs "Good evening."
else if оператор
Используйте оператор else if, чтобы задать новое условие при первом условии false.
if (condition1) {
// block of code to be executed if condition1 is true
} else if (condition2) {
// block of code to be executed if the condition1 is false and condition2 is true
} else {
// block of code to be executed if the condition1 is false and condition2 is false
}
Example
int time = 22;
if (time < 10) {
System.out.println("Good morning.");
} else if (time < 20) {
System.out.println("Good day.");
} else {
System.out.println("Good evening.");
}
// Outputs "Good evening."
Вы можете просто написать:
int time = 20;
String result = (time < 18) ? "Good day." : "Good evening.";
System.out.println(result);
Используйте оператор switch, чтобы выбрать один из многих блоков кода для выполнения.
switch(expression) {
case x:
// code block
break;
case y:
// code block
break;
default:
// code block
}
Вот как это работает:
Выражение switch оценивается один раз.
Значение выражения сравнивается со значениями каждого case.
Если есть совпадение, выполняется соответствующий блок кода.
Ключевые слова break и default не являются обязательными и будут описаны позже в этой главе.
В приведенном ниже примере номер дня недели используется для вычисления названия дня недели:
int day = 4;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
}
// Outputs "Thursday" (day 4)
Ключевое слово break
Когда Java достигает ключевого слова break, она выходит из блока switch.
Это остановит выполнение большего количества кода и тестирования случаев внутри блока.
Когда совпадение найдено и работа сделана, пора сделать перерыв. Нет необходимости в дополнительном тестировании.
Ключевое слово по default указывает код для запуска, если нет совпадения по регистру:
int day = 4;
switch (day) {
case 6:
System.out.println("Today is Saturday");
break;
case 7:
System.out.println("Today is Sunday");
break;
default:
System.out.println("Looking forward to the Weekend");
}
// Outputs "Looking forward to the Weekend"
Loops - циклы
Циклы могут выполнять блок кода до тех пор, пока достигается указанное условие.
Циклы удобны, потому что они экономят время, уменьшают количество ошибок и делают код более читаемым.
Цикл while перебирает блок кода, пока выполняется указанное условие true:
while (condition) {
// code block to be executed
Example
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
Цикл do / while - это вариант цикла while. Этот цикл выполнит блок кода один раз, прежде чем проверять, истинно ли условие, затем он будет повторять цикл, пока условие true.
do {
// code block to be executed
}
while (condition);
int i = 0;
do {
System.out.println(i);
i++;
}
while (i < 5);
Если вы точно знаете, сколько раз вы хотите перебрать блок кода, используйте цикл for вместо цикла while:
for (statement 1; statement 2; statement 3) {
// code block to be executed
}
Оператор 1 выполняется (один раз) перед выполнением блока кода.
Оператор 2 определяет условие выполнения блока кода.
Оператор 3 выполняется (каждый раз) после выполнения блока кода.
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
Существует также цикл "for-each", который используется исключительно для циклического перебора элементов в массиве:
for (type variableName : arrayName) {
// code block to be executed
}
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (String i : cars) {
System.out.println(i);
}
Оператор break также можно использовать для выхода из цикла.
for (int i = 0; i < 10; i++) {
if (i == 4) {
break;
}
System.out.println(i);
}
Оператор continue прерывает одну итерацию (в цикле), если возникает указанное условие, и продолжает следующую итерацию в цикле.
for (int i = 0; i < 10; i++) {
if (i == 4) {
continue;
}
System.out.println(i);
}
Вы также можете использовать break и continue в циклах while:
int i = 0;
while (i < 10) {
System.out.println(i);
i++;
if (i == 4) {
break;
}
}
int i = 0;
while (i < 10) {
if (i == 4) {
i++;
continue;
}
System.out.println(i);
i++;
}
Массивы используются для хранения нескольких значений в одной переменной вместо объявления отдельных переменных для каждого значения.
Чтобы объявить массив, укажите тип переменной в квадратных скобках:
String[] cars;
Теперь мы объявили переменную, которая содержит массив строк. Чтобы вставить в него значения, мы можем использовать литерал массива - поместите значения в список, разделенный запятыми, внутри фигурных скобок:
String[] cars = {"Volvo", "", "", ""};
Чтобы создать массив целых чисел, вы можете написать:
int[] myNum = {10, 20, 30, 40};
Доступ к элементам массива
Вы получаете доступ к элементу массива, обращаясь к порядковому номеру.
Этот оператор обращается к значению первого элемента в cars:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
System.out.println(cars[0]); // Outputs Volvo
Изменить элемент массива
Чтобы изменить значение определенного элемента, обратитесь к порядковому номеру:
cars[0] = "Opel";
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
cars[0] = "Opel";
System.out.println(cars[0]);
// Now outputs Opel instead of Volvo
Array Length
Чтобы узнать, сколько элементов в массиве, используйте свойство length:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
System.out.println(cars.length); // Outputs ?
Вы можете перебирать элементы массива с помощью цикла for и использовать свойство length, чтобы указать, сколько раз цикл должен выполняться.
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (int i = 0; i < cars.length; i++) {
System.out.println(cars[i]);
}
Цикл через массив с For-Each
for (type variable : arrayname) {
...
}
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (String i : cars) {
System.out.println(i);
}
Многомерный массив - это массив массивов.
Чтобы создать двумерный массив, добавьте каждый массив в свой собственный набор фигурных скобок:
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
myNumbers теперь представляет собой массив с двумя массивами в качестве его элементов.
Чтобы получить доступ к элементам массива myNumbers, укажите два индекса: один для массива и один для элемента внутри этого массива. В этом примере осуществляется доступ к третьему элементу (2) во втором массиве (1) myNumbers:
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
int x = myNumbers[1][2];
System.out.println(x); // Outputs 7
Мы также можем использовать цикл for внутри другого цикла for, чтобы получить элементы двумерного массива (нам все еще нужно указать на два индекса):
public class Main {
public static void main(String[] args) {
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
for (int i = 0; i < myNumbers.length; ++i) {
for(int j = 0; j < myNumbers[i].length; ++j) {
System.out.println(myNumbers[i][j]);
}
}
}
}
Метод — это блок кода, который запускается только при вызове.
Вы можете передавать данные, известные как параметры, в метод.
Методы используются для выполнения определенных действий, и они также известны как функции.
Зачем использовать методы? Чтобы повторно использовать код: определите код один раз и используйте его много раз.
Метод должен быть объявлен внутри класса. Он определяется именем метода, за которым следуют круглые скобки (). Java предоставляет некоторые предопределенные методы, такие как System.out.println(), но вы также можете создавать свои собственные методы для выполнения определенных действий:
Пример:
public class Main {
static void myMethod() {
// code to be executed
}
}
Объяснение примера
myMethod() — это имя метода
static означает, что метод принадлежит классу Main, а не объекту класса Main.
void означает, что этот метод не имеет возвращаемого значения.
Вызов метода
Чтобы вызвать метод в Java, напишите имя метода, за которым следуют две круглые скобки () и точка с запятой;
В следующем примере myMethod() используется для печати текста (действия) при его вызове:
Пример:
public class Main {
static void myMethod() {
System.out.println("I am learning programming");
}
public static void main(String[] args) {
myMethod();
}
}
Метод также может быть вызван несколько раз:
Пример:
public class Main {
static void myMethod() {
System.out.println("I am learning programming");
}
public static void main(String[] args) {
myMethod();
myMethod();
myMethod();
}
}
Параметры и аргументы
Информация может быть передана методам в качестве параметра. Параметры действуют как переменные внутри метода.
Параметры указываются после имени метода в круглых скобках. Вы можете добавить столько параметров, сколько хотите, просто разделите их запятой.
В следующем примере есть метод, который принимает строку с именем fname в качестве параметра. При вызове метода мы передаем имя, которое используется внутри метода для вывода полного имени:
public class Main {
static void myMethod(String fname) {
System.out.println(fname + " Refsnes");
}
public static void main(String[] args) {
myMethod("Liam");
myMethod("Jenny");
myMethod("Anja");
}
}
Несколько параметров
Вы можете иметь столько параметров, сколько хотите:
public class Main {
static void myMethod(String fname, int age) {
System.out.println(fname + " is " + age);
}
public static void main(String[] args) {
myMethod("Liam", 5);
myMethod("Jenny", 8);
myMethod("Anja", 31);
}
}
Возвращаемые значения
Ключевое слово void, используемое в приведенных выше примерах, указывает, что метод не должен возвращать значение. Если вы хотите, чтобы метод возвращал значение, вы можете использовать примитивный тип данных (например, int, char и т. д.) вместо void и использовать ключевое слово return внутри метода:
public class Main {
static int myMethod(int x) {
return 5 + x;
}
public static void main(String[] args) {
System.out.println(myMethod(3));
}
}
В этом примере возвращается сумма двух параметров метода:
public class Main {
static int myMethod(int x, int y) {
return x + y;
}
public static void main(String[] args) {
System.out.println(myMethod(5, 3));
}
}
Вы также можете сохранить результат в переменной (рекомендуется, так как ее легче читать и поддерживать):
public class Main {
static int myMethod(int x, int y) {
return x + y;
}
public static void main(String[] args) {
int z = myMethod(5, 3);
System.out.println(z);
}
}
Метод с If...Else
Обычно внутри методов используются операторы if...else:
public class Main {
static void checkAge(int age) {
if (age < 18) {
System.out.println("Access denied - You are not old enough!");
} else {
System.out.println("Access granted - You are old enough!");
}
}
public static void main(String[] args) {
checkAge(20);
}
}
При перегрузке методов несколько методов могут иметь одно и то же имя с разными параметрами:
int myMethod(int x)
float myMethod(float x)
double myMethod(double x, double y)
Рассмотрим следующий пример, в котором есть два метода, добавляющие числа разного типа:
static int plusMethodInt(int x, int y) {
return x + y;
}
static double plusMethodDouble(double x, double y) {
return x + y;
}
public static void main(String[] args) {
int myNum1 = plusMethodInt(8, 5);
double myNum2 = plusMethodDouble(4.3, 6.26);
System.out.println("int: " + myNum1);
System.out.println("double: " + myNum2);
}
Вместо определения двух методов, которые должны делать одно и то же, лучше перегрузить один.
В приведенном ниже примере мы перегружаем метод plusMethod для работы как с int, так и с double:
static int plusMethod(int x, int y) {
return x + y;
}
static double plusMethod(double x, double y) {
return x + y;
}
public static void main(String[] args) {
int myNum1 = plusMethod(8, 5);
double myNum2 = plusMethod(4.3, 6.26);
System.out.println("int: " + myNum1);
System.out.println("double: " + myNum2);
}
В Java переменные доступны только внутри области, в которой они созданы. Это называется область применения.
Переменные, объявленные непосредственно внутри метода, доступны в любом месте метода после строки кода, в которой они были объявлены:
public class Main {
public static void main(String[] args) {
// Code here CANNOT use x
int x = 100;
// Code here can use x
System.out.println(x);
}
}
Область блока
Блок кода относится ко всему коду, заключенному в фигурные скобки {}.
Переменные, объявленные внутри блоков кода, доступны только коду между фигурными скобками, который следует за строкой, в которой была объявлена переменная:
public class Main {
public static void main(String[] args) {
// Code here CANNOT use x
{ // This is a block
// Code here CANNOT use x
int x = 100;
// Code here CAN use x
System.out.println(x);
} // The block ends here
// Code here CANNOT use x
}
}
Рекурсия — это метод создания самого вызова функции. Этот метод позволяет разбить сложные проблемы на простые, которые легче решить.
Рекурсию может быть немного сложно понять. Лучший способ понять, как это работает, — это поэкспериментировать.
Пример рекурсии
Сложить два числа легко, но сложить диапазон чисел сложнее. В следующем примере рекурсия используется для сложения диапазона чисел, разбивая его на простую задачу сложения двух чисел:
public class Main {
public static void main(String[] args) {
int result = sum(10);
System.out.println(result);
}
public static int sum(int k) {
if (k > 0) {
return k + sum(k - 1);
} else {
return 0;
}
}
}
Когда вызывается функция sum(), она добавляет параметр k к сумме всех чисел, меньших k, и возвращает результат. Когда k становится равным 0, функция просто возвращает 0. При запуске программа выполняет следующие шаги:
10 + sum(9)
10 + ( 9 + sum(8) )
10 + ( 9 + ( 8 + sum(7) ) )
...
10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + sum(0)
10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
Поскольку функция не вызывает себя, когда k равно 0, программа останавливается на этом и возвращает результат.
Состояние остановки
Точно так же, как циклы могут столкнуться с проблемой бесконечного зацикливания, рекурсивные функции могут столкнуться с проблемой бесконечной рекурсии. Бесконечная рекурсия — это когда функция никогда не перестает вызывать себя. Каждая рекурсивная функция должна иметь условие остановки, то есть условие, при котором функция прекращает вызывать себя. В предыдущем примере условие остановки возникает, когда параметр k становится равным 0.
Полезно увидеть множество различных примеров, чтобы лучше понять концепцию. В этом примере функция добавляет диапазон чисел между началом и концом. Условием остановки для этой рекурсивной функции является то, что end не больше, чем start:
public class Main {
public static void main(String[] args) {
int result = sum(5, 10);
System.out.println(result);
}
public static int sum(int start, int end) {
if (end > start) {
return end + sum(start, end - 1);
} else {
return end;
}
}
}
Процедурное программирование — это написание процедур или методов, выполняющих операции с данными, в то время как объектно-ориентированное программирование — это создание объектов, содержащих как данные, так и методы.
Объектно-ориентированное программирование имеет несколько преимуществ перед процедурным программированием:
ООП быстрее и проще в исполнении
ООП обеспечивает четкую структуру программ
ООП помогает сохранить код Java СУХИМ «Не повторяйтесь» и упрощает поддержку, изменение и отладку кода.
ООП позволяет создавать полностью повторно используемые приложения с меньшим количеством кода и более коротким временем разработки.
Совет. Принцип «Не повторяйся» (DRY) заключается в уменьшении повторения кода. Вы должны извлечь коды, которые являются общими для приложения, поместить их в одно место и использовать повторно, а не повторять.
Java — что такое классы и объекты?
Классы и объекты — два основных аспекта объектно-ориентированного программирования.
Итак, класс — это шаблон для объектов, а объект — это экземпляр класса.
При создании отдельных объектов они наследуют все переменные и методы класса.
Java — это объектно-ориентированный язык программирования.
Все в Java связано с классами и объектами, а также с их атрибутами и методами. Например: в реальной жизни машина — это объект. У автомобиля есть атрибуты, такие как вес и цвет, и методы, такие как движение и торможение.
Класс подобен конструктору объектов или «чертежу» для создания объектов.
Создать класс
Чтобы создать класс, используйте класс ключевого слова:
public class Main {
int x = 5;
}
Создать объект
В Java объект создается из класса. Мы уже создали класс с именем Main, так что теперь мы можем использовать его для создания объектов.
Чтобы создать объект Main, укажите имя класса, за которым следует имя объекта, и используйте ключевое слово new:
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj = new Main();
System.out.println(myObj.x);
}
}
Несколько объектов
Вы можете создать несколько объектов одного класса:
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj1 = new Main(); // Object 1
Main myObj2 = new Main(); // Object 2
System.out.println(myObj1.x);
System.out.println(myObj2.x);
}
}
Использование нескольких классов
Вы также можете создать объект класса и получить к нему доступ в другом классе. Это часто используется для лучшей организации классов (один класс имеет все атрибуты и методы, а другой класс содержит метод main() (код для выполнения)).
Помните, что имя java-файла должно совпадать с именем класса. В этом примере мы создали два файла в одном каталоге/папке:
Main.java
public class Main {
int x = 5;
}
Второй.java
class Second {
public static void main(String[] args) {
Main myObj = new Main();
System.out.println(myObj.x);
}
}
В предыдущей главе мы использовали термин «переменная» для x в примере (как показано ниже). На самом деле это атрибут класса. Или вы могли бы сказать, что атрибуты класса являются переменными внутри класса:
public class Main {
int x = 5;
int y = 3;
}
Доступ к атрибутам
Вы можете получить доступ к атрибутам, создав объект класса и используя синтаксис с точкой (.):
В следующем примере создается объект класса Main с именем myObj. Мы используем атрибут x объекта для вывода его значения:
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj = new Main();
System.out.println(myObj.x);
}
}
Изменить атрибуты
Вы также можете изменить значения атрибутов:
public class Main {
int x;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 40;
System.out.println(myObj.x);
}
}
Или переопределить существующие значения:
public class Main {
int x = 10;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 25; // x is now 25
System.out.println(myObj.x);
}
}
Если вы не хотите переопределять существующие значения, объявите атрибут окончательным:
public class Main {
final int x = 10;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 25; // will generate an error: cannot assign a value to a final variable
System.out.println(myObj.x);
}
}
Ключевое слово final полезно, когда вы хотите, чтобы переменная всегда хранила одно и то же значение, например PI (3.14159...).
Несколько объектов
Если вы создаете несколько объектов одного класса, вы можете изменить значения атрибутов в одном объекте, не затрагивая значения атрибутов в другом:
public class Main {
int x = 5;
public static void main(String[] args) {
Main myObj1 = new Main(); // Object 1
Main myObj2 = new Main(); // Object 2
myObj2.x = 25;
System.out.println(myObj1.x); // Outputs 5
System.out.println(myObj2.x); // Outputs 25
}
}
Несколько атрибутов
Вы можете указать столько атрибутов, сколько хотите:
public class Main {
String fname = "John";
String lname = "Doe";
int age = 24;
public static void main(String[] args) {
Main myObj = new Main();
System.out.println("Name: " + myObj.fname + " " + myObj.lname);
System.out.println("Age: " + myObj.age);
}
}
Из главы «Методы Java» вы узнали, что методы объявляются внутри класса и используются для выполнения определенных действий:
public class Main {
static void myMethod() {
System.out.println("Hello World!");
}
}
myMethod() печатает текст (действие) при вызове. Чтобы вызвать метод, напишите имя метода, за которым следуют две круглые скобки () и точка с запятой;
public class Main {
static void myMethod() {
System.out.println("Hello World!");
}
public static void main(String[] args) {
myMethod();
}
}
Static vs. Public
Вы часто будете видеть Java-программы со статическими или общедоступными атрибутами и методами.
В примере выше мы создали статический метод, а это значит, что к нему можно обращаться без создания объекта класса, в отличие от public, доступ к которому возможен только через объекты:
public class Main {
// Static method
static void myStaticMethod() {
System.out.println("Static methods can be called without creating objects");
}
// Public method
public void myPublicMethod() {
System.out.println("Public methods must be called by creating objects");
}
// Main method
public static void main(String[] args) {
myStaticMethod(); // Call the static method
// myPublicMethod(); This would compile an error
Main myObj = new Main(); // Create an object of Main
myObj.myPublicMethod(); // Call the public method on the object
}
}
Конструктор в Java — это специальный метод, который используется для инициализации объектов. Конструктор вызывается при создании объекта класса. Его можно использовать для установки начальных значений атрибутов объекта:
// Create a Main class
public class Main {
int x; // Create a class attribute
// Create a class constructor for the Main class
public Main() {
x = 5; // Set the initial value for the class attribute x
}
public static void main(String[] args) {
Main myObj = new Main(); // Create an object of class Main (This will call the constructor)
System.out.println(myObj.x); // Print the value of x
}
}
Обратите внимание, что имя конструктора должно совпадать с именем класса и не может иметь тип возвращаемого значения (например, void).
Также обратите внимание, что конструктор вызывается при создании объекта.
Все классы имеют конструкторы по умолчанию: если вы не создадите конструктор класса самостоятельно, Java создаст его за вас. Однако тогда вы не сможете установить начальные значения для атрибутов объекта.
Параметры конструктора
Конструкторы также могут принимать параметры, которые используются для инициализации атрибутов.
В следующем примере в конструктор добавляется параметр int y. Внутри конструктора мы устанавливаем x в y (x=y). Когда мы вызываем конструктор, мы передаем конструктору параметр (5), который установит значение x равным 5:
public class Main {
int x;
public Main(int y) {
x = y;
}
public static void main(String[] args) {
Main myObj = new Main(5);
System.out.println(myObj.x);
}
}
Вы можете иметь столько параметров, сколько хотите:
public class Main {
int modelYear;
String modelName;
public Main(int year, String name) {
modelYear = year;
modelName = name;
}
public static void main(String[] args) {
Main myCar = new Main(1969, "Mustang");
System.out.println(myCar.modelYear + " " + myCar.modelName);
}
}
К настоящему времени вы хорошо знакомы с ключевым словом public, которое встречается почти во всех наших примерах:
public class Main
Ключевое слово public является модификатором доступа, что означает, что оно используется для установки уровня доступа для классов, атрибутов, методов и конструкторов.
Разделим модификаторы на две группы:
Модификаторы доступа — контролируют уровень доступа
Модификаторы без доступа — не контролируют уровень доступа, но предоставляют другие функции.
Модификаторы доступа
Для классов вы можете использовать как public, так и default:
public Класс доступен любому другому классу
default Класс доступен только классам в том же пакете. Это используется, когда вы не указываете модификатор.
Для атрибутов, методов и конструкторов вы можете использовать одно из следующих:
public Код доступен для всех классов
private Код доступен только внутри объявленного класса
default Код доступен только в том же пакете. Это используется, когда вы не указываете модификатор.
protected Код доступен в том же пакете и подклассах.
Модификаторы отсутствия доступа
Для классов вы можете использовать либо final, либо abstract:
final Класс не может быть унаследован другими классами
abstract Класс нельзя использовать для создания объектов
Для атрибутов и методов вы можете использовать одно из следующих:
final Атрибуты и методы не могут быть переопределены/изменены
static Атрибуты и методы принадлежат классу, а не объекту
abstract Может использоваться только в абстрактном классе и только в методах. Метод не имеет тела, например, abstract void run();.
transient Атрибуты и методы пропускаются при сериализации содержащего их объекта
synchronized методы могут быть доступны только одному потоку за раз
volatile Значение атрибута не кэшируется локально в потоке и всегда считывается из «основной памяти».
Final
Если вы не хотите переопределять существующие значения атрибутов, объявите атрибуты окончательными:
public class Main {
final int x = 10;
final double PI = 3.14;
public static void main(String[] args) {
Main myObj = new Main();
myObj.x = 50; // will generate an error: cannot assign a value to a final variable
myObj.PI = 25; // will generate an error: cannot assign a value to a final variable
System.out.println(myObj.x);
}
}
Static
Статический метод означает, что к нему можно получить доступ без создания объекта класса, в отличие от общедоступного:
public class Main {
// Static method
static void myStaticMethod() {
System.out.println("Static methods can be called without creating objects");
}
// Public method
public void myPublicMethod() {
System.out.println("Public methods must be called by creating objects");
}
// Main method
public static void main(String[ ] args) {
myStaticMethod(); // Call the static method
// myPublicMethod(); This would output an error
Main myObj = new Main(); // Create an object of Main
myObj.myPublicMethod(); // Call the public method
}
}
Abstract
Абстрактный метод принадлежит абстрактному классу и не имеет тела. Тело предоставляется подклассом:
// Code from filename: Main.java
// abstract class
abstract class Main {
public String fname = "John";
public int age = 24;
public abstract void study(); // abstract method
}
// Subclass (inherit from Main)
class Student extends Main {
public int graduationYear = 2018;
public void study() { // the body of the abstract method is provided here
System.out.println("Studying all day long");
}
}
// End code from filename: Main.java
// Code from filename: Second.java
class Second {
public static void main(String[] args) {
// create an object of the Student class (which inherits attributes and methods from Main)
Student myObj = new Student();
System.out.println("Name: " + myObj.fname);
System.out.println("Age: " + myObj.age);
System.out.println("Graduation Year: " + myObj.graduationYear);
myObj.study(); // call abstract method
}
}
Смысл инкапсуляции в том, чтобы убедиться, что «конфиденциальные» данные скрыты от пользователей. Чтобы достичь этого, вы должны:
объявить переменные/атрибуты класса как приватные
предоставить общедоступные методы получения и установки для доступа и обновления значения частной переменной
Get и Set
Из предыдущей главы вы узнали, что доступ к закрытым переменным возможен только внутри одного и того же класса (внешний класс не имеет к ним доступа). Однако к ним можно получить доступ, если мы предоставим общедоступные методы get и set.
Метод get возвращает значение переменной, а метод set устанавливает значение.
Синтаксис для обоих таков, что они начинаются либо с get, либо с set, за которым следует имя переменной с первой буквой в верхнем регистре:
public class Person {
private String name; // private = restricted access
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String newName) {
this.name = newName;
}
}
Метод get возвращает значение имени переменной.
Метод set принимает параметр (newName) и присваивает его переменной name. Ключевое слово this используется для ссылки на текущий объект.
Однако, поскольку переменная имени объявлена как приватная, мы не можем получить к ней доступ извне этого класса:
public class Main {
public static void main(String[] args) {
Person myObj = new Person();
myObj.name = "John"; // error
System.out.println(myObj.name); // error
}
}
Почему инкапсуляция?
Улучшенный контроль над атрибутами и методами класса
Атрибуты класса можно сделать доступными только для чтения (если вы используете только метод get) или только для записи (если вы используете только метод set).
Гибкость: программист может изменить одну часть кода, не затрагивая другие части
Повышенная безопасность данных
Наследование (подкласс и суперкласс)
В Java можно наследовать атрибуты и методы от одного класса к другому. Мы разделяем «концепцию наследования» на две категории:
подкласс (дочерний) - класс, который наследуется от другого класса
суперкласс (родительский) - класс, наследуемый от
Чтобы наследовать от класса, используйте ключевое слово extends.
В приведенном ниже примере класс Car (подкласс) наследует атрибуты и методы класса Vehicle (надкласс):
class Vehicle {
protected String brand = "Ford"; // Vehicle attribute
public void honk() { // Vehicle method
System.out.println("Tuut, tuut!");
}
}
class Car extends Vehicle {
private String modelName = "Mustang"; // Car attribute
public static void main(String[] args) {
// Create a myCar object
Car myCar = new Car();
// Call the honk() method (from the Vehicle class) on the myCar object
myCar.honk();
// Display the value of the brand attribute (from the Vehicle class) and the value of the modelName from the Car class
System.out.println(myCar.brand + " " + myCar.modelName);
}
}
Вы заметили защищенный модификатор в Vehicle?
Мы устанавливаем атрибут бренда в Vehicle в модификатор защищенного доступа. Если бы он был установлен как частный, класс Car не смог бы получить к нему доступ.
Почему и когда использовать «Наследование»?
- Это полезно для повторного использования кода: повторно используйте атрибуты и мето
Полиморфизм означает «много форм», и он возникает, когда у нас есть много классов, связанных друг с другом путем наследования.
Как мы указали в предыдущей главе; Наследование позволяет нам наследовать атрибуты и методы другого класса. Полиморфизм использует эти методы для выполнения различных задач. Это позволяет нам выполнять одно и то же действие разными способами.
Например, подумайте о суперклассе Animal, в котором есть метод animalSound(). Подклассами животных могут быть Свиньи, Кошки, Собаки, Птицы - И у них также есть своя реализация звука животного (свинья хрюкает, кошка мяукает и т. д.):
class Animal {
public void animalSound() {
System.out.println("The animal makes a sound");
}
}
class Pig extends Animal {
public void animalSound() {
System.out.println("The pig says: wee wee");
}
}
class Dog extends Animal {
public void animalSound() {
System.out.println("The dog says: bow wow");
}
}
Помните из главы «Наследование», что мы используем ключевое слово extends для наследования от класса.
Теперь мы можем создать объекты Pig и Dog и вызвать метод animalSound() для них обоих:
class Animal {
public void animalSound() {
System.out.println("The animal makes a sound");
}
}
class Pig extends Animal {
public void animalSound() {
System.out.println("The pig says: wee wee");
}
}
class Dog extends Animal {
public void animalSound() {
System.out.println("The dog says: bow wow");
}
}
class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Create a Animal object
Animal myPig = new Pig(); // Create a Pig object
Animal myDog = new Dog(); // Create a Dog object
myAnimal.animalSound();
myPig.animalSound();
myDog.animalSound();
}
}