Классы и объекты
Java — это объектно-ориентированный язык, поэтому код в ваших программах будет состоять из объектов и классов.
Классы
Java позволяет создавать классы, которые представляют объекты из реального мира. Например, можно создать класс Car (автомобиль) или Animal (животное) и задать им различные свойства. Для класса Car логично создать такие свойства как двери, колёса, лобовое стекло и т.д. Имея класс Car, можно создать новые классы Легковушки, Грузовики, Автобусы, которые будут иметь все свойства класса Car, а также свои собственные свойства. У класса Animal соответственно можно задать свойства Лапы, Хвост, а затем создать наш любимый класс Cat, у которого будет ещё дополнительное свойство Усы. Иными словами, классы могут наследовать свойства от других классов. Родительский класс называется суперклассом. Внутри классов могут быть объявлены поля и методы.
Для объявления класса служит ключевое слово class. Вспомним стандартную строчку кода из Android-проекта:
public class MainActivity extends Activity < // код внутри класса >
Упрощённая общая форма для класса может иметь следующий вид:
class ИмяКласса < тип переменная_экземпляра1; тип имяМетода(список параметров)< // тело метода >>
В Java принято начинать имена класса с большой буквы. В классе могут быть несколько переменных и методов. Переменные, определённые внутри класса (не метода), называются переменными экземпляра или полями (fields). Код пишется внутри класса. Методы и переменные внутри класса являются членами класса.
Объекты
Новый объект (или экземпляр) создаётся из существующего класса при помощи ключевого слова new:
Cat barsik = new Cat(); // создали кота из класса Cat
В большинстве случаев вы будете использовать такой способ. Пусть вас не удивляет, что приходится дважды использовать слово Cat, оно имеет разный смысл.
Слева от оператора присваивания = определяется имя переменной и его тип Cat. В правой части выражения происходит выделение памяти для нового экземпляра класса Cat и инициализируется экземпляр. Оператор присваивания присваивает переменной ссылку на только что созданный объект. Имена объектов не нужно начинать с большой буквы, как у класса. Так вы будете различать, где класс, а где экземпляр класса. Если имя экземпляра класса состоит из нескольких слов, то используется верблюжья нотация, когда все первые буквы слов, кроме первой, пишутся с большой — superBlackCat.
Если вы помните, при объявлении примитивных типов мы указывали нужный тип в самом начале.
int catAge;
Поэтому код Cat barsik также определяет его тип. Он не всегда может совпадать с именем класса.
Pet barsik = new Cat();
В этом примере используется тип класса домашних любимцев Pet, а обращаемся к классу котов Cat.
Простой пример создания класса Box (коробка для кота):
class Box < int width; // ширина коробки int height; // высота коробки int depth; // глубина коробки >
При таком варианте Java автоматически присвоит переменным значения по умолчанию. Например, для int это будет значение 0. Но не всегда значения по умолчанию подойдут в вашем классе. Если вы создали переменную для описания количества лап у кота, то логично сразу присвоить значение 4. Поэтому считается хорошей практикой сразу присваивать нужные значения полям класса, не полагаясь на систему.
Вам нужно создать отдельный файл Box.java, в который следует вставить код, описанный выше. О том, как создавать новый файл для класса я не буду здесь расписывать.
Сам класс — это просто шаблон, заготовка. Чтобы ваше приложение могло использовать данный шаблон, нужно создать на его основе объект при помощи ключевого слова new:
Box catBox = new Box; // создали реальный объект с именем catBox на основе шаблона Box
Красивая получилась коробочка.
Объект catBox, объявленный в коде вашей программы, сразу займёт часть памяти на устройстве. При этом объект будет содержать собственные копии переменных экземпляра width, height, depth. Для доступа к этим переменным используется точка (.). Если мы хотим присвоить значение переменной width, то после создания объекта класса можете написать код:
catBox.width = 400; // ширина коробки для кота 400 миллиметров
Если мы хотим вычислить объём коробки, то нужно перемножить все значения размеров коробки:
Box catBox = new Box(); catBox.width = 400; catBox.height = 200; catBox.depth = 250; int volume = catBox.width * catBox.height * catBox.depth; mInfoTextView.setText("Объём коробки: " + volume);
Каждый объект содержит собственные копии переменных экземпляра. Вы можете создать несколько объектов на основе класса Box и присваивать разные значения для размеров коробки. При этом изменения переменных экземпляра одного объекта никак не влияют на переменные экземпляра другого объекта. Давайте объявим два объекта класса Box:
Box bigBox = new Box(); // большая коробка Box smallBox = new Box(); // маленькая коробка int volume; // присвоим значения переменным для большой коробки bigBox.width = 400; bigBox.height = 200; bigBox.depth = 250; // присвоим значения переменным для маленькой коробки smallBox.width = 200; smallBox.height = 100; smallBox.depth = 150; // вычисляем объём первой коробки volume = bigBox.width * bigBox.height * bigBox.depth; mInfoTextView.setText("Объём большой коробки: " + volume + "\n"); // вычисляем объём маленькой коробки volume = smallBox.width * smallBox.height * smallBox.depth; mInfoTextView.append("Объём маленькой коробки: " + volume);
Когда мы используем конструкцию типа Box bigBox = new Box();, то в одной строке выполняем сразу два действия — объявляем переменную типа класса и резервируем память под объект. Можно разбить конструкцию на отдельные части:
Box bigBox; // объявляем ссылку на объект bigBox = new Box(); // резервируем память для объекта Box
Обычно такую конструкцию из двух строк кода не используют на практике, если нет особых причин.
Когда мы используем ключевое слово new и указываем имя класса, то после имени ставим круглые скобки, которые указывают на конструктор класса. О них поговорим позже.
Ключевое слово final
Поле может быть объявлено как final (финальное). Это позволяет предотвратить изменение содержимого переменной, по сути, это становится константой. Финальное поле должно быть инициализировано во время его первого объявления.
final int FILE_OPEN = 1;
Теперь можно пользоваться переменной FILE_OPEN так, как если бы она была константой, без риска изменения их значений. Принято записывать имена заглавными буквами.
Кроме полей, final можно использовать для параметров метода (препятствует изменению в пределах метода) и у локальных переменных (препятствует присвоению ей значения более одного раза).
Также слово final можно применять к методам, чтобы предотвратить его переопределение.
class Cat < final void meow() < System.out.println("Мяу"); >> class Kittent extends Cat < // Этот метод создать не получится void meow() < System.out.println("Да хоть гав-гав, всё равно не заведётся"); >>
Ещё один вариант использования ключевого слова final — предотвращение наследования класса. При этом неявно всего методы класса также становятся финальными. Поэтому нельзя одновременно объявить класс абстрактным и финальным, поскольку абстрактный класс является лишь шаблоном и только его подклассы реализуют методы.
final class Tail < // . >// Следующий класс недопустим class BigTail extends Tail < // Ошибка! Класс Хвост нельзя переопределять. >
Ключевое слово instanceof — Проверка принадлежности к классу
Иногда требуется проверить, к какому классу принадлежит объект. Это можно сделать при помощи ключевого слова instanceof. Это булев оператор, и выражение foo instanceof Foo истинно, если объект foo принадлежит классу Foo или его наследнику, или реализует интерфейс Foo (или, в общем виде, наследует класс, который реализует интерфейс, который наследует Foo).
Возьмём пример с рыбками, которые знакомы котам не понаслышке. Пусть у нас есть родительский класс Fish и у него есть унаследованные подклассы SaltwaterFish и FreshwaterFish. Мы можем протестировать, относится ли заданный объект к классу или подклассу по имени
SaltwaterFish nemo = new SaltwaterFish(); if(nemo instanceof Fish) < // рыбка Немо относится к классу Fish // это может быть класс Fish (родительский класс) или подкласс типа // SaltwaterFish или FreshwaterFish. if(nemo instanceof SaltwaterFish) < // Немо - это морская рыбка! >>
Данная проверка удобна во многих случаях. В Android очень много классов, которые происходят от класса View — TextView, CheckBox, Button, имеющие свои собственные наборы свойств. И если имеется метод с параметром View, то при помощи instanceof можно разделить логику кода:
void checkforTextView(View view) < if(view instanceof TextView) < // Код для элемента TextView >else < // Для других элементов View >>
import — Импорт класса
Оператор import сообщает компилятору Java, где найти классы, на которые ссылается код. Любой сложный объект использует другие объекты для выполнения тех или иных функций, и оператор импорта позволяет сообщить о них компилятору Java. Оператор импорта обычно выглядит так:
import ClassNameToImport;
За ключевым словом import следуют класс, который нужно импортировать, и точка с запятой. Имя класса должно быть полным, то есть включать свой пакет. Чтобы импортировать все классы из пакета, после имени пакета можно поместить .*.
В Android Studio импорт класса происходит автоматически при наборе кода. Также это срабатывает и при вставке кода. Если имена классов совпадают, то студия может запросить помощь. Тогда вам нужно вручную указать нужное полное имя класса.
Импорт позволяет избежать долгого набора имени класса. Без импорта нам пришлось бы писать все классы в коде программы полностью.
ru.alexanderklimov.MyClass.Cat.sayMeow(); java.lang.System.out.println("Мяу");
Статический импорт
Существует ещё статический импорт, применяемый для импорта статических членов класса или интерфейса. Это позволяет сократить количество кода. Например, есть статические методы Math.pow(), Math.sqrt(). Для вычислений сложных формул с использованием математических методов, код становится перегружен. К примеру, вычислим гипотенузу.
hypot = Math.sqrt(Math.pow(side1, 2) + Math.pow(side2, 2));
В данном случае без указания класса не обойтись, так как методы статические. Чтобы не набирать имена классов, их можно импортировать следующим образом:
import static java.lang.Math.sqrt; import static java.lang.Math.pow; . hypot = sqrt(pow(side1, 2) + pow(side2, 2));
После импорта уже нет необходимости указывать имя класса.
Второй допустимый вариант, позволяющий сделать видимыми все статические методы класса:
import static java.lang.Math.*;
В этом случае вам не нужно импортировать отдельные методы. Но такой подход в Android не рекомендуется, так как требует больше памяти.
Класс Class
На первый взгляд, класс Class звучит как «масло масляное». Тем не менее, класс с таким именем существует и он очень полезен.
Программно получить имя класса
Иногда из программы нужно получить имя используемого класса. Для этого есть специальные методы getClass().getName() и другие родственные методы. Допустим, нам нужно узнать имя класса кнопки, на которую мы нажимаем в программе.
public void onClick(View view) < String className = view.getClass().getName(); String simpleName = view.getClass().getSimpleName(); String canonicalName = view.getClass().getCanonicalName(); if (canonicalName == null) < canonicalName = "null"; >String s = "Имя класса: " + className + "\n" + "SimpleName: " + simpleName + "\n" + "CanonicalName: " + canonicalName + "\n"; mInfoTextView.setText(s); >
Имя класса: android.support.v7.widget.AppCompatButton SimpleName: AppCompatButton CanonicalName: android.support.v7.widget.AppCompatButton
getSimpleName() возвращает только имя класса без пакета, другие методы вернут полное название.
Если нужно узнать имя класса активности, то достаточно кода:
// подставьте имя вашей активности String className = MainActivity.class.getName();
Если вам известно имя класса, то можете получить сам класс:
try < // получим объект Class ClassmyClass = Class.forName("ru.alexanderklimov.test.MainActivity"); mInfoTextView.setText(myClass.getName()); // выводим в TextView Intent intent = new Intent(this, myClass); startActivity(intent); > catch (ClassNotFoundException e) < // TODO Auto-generated catch block e.printStackTrace(); >
Метод getSuperclass() возвращает имя суперкласса. Остальные несколько десятков методов не столь популярны.
Опишите процесс создания экземпляра класса
Сначала класс и цепочка его предков должны быть загружены, сверху вниз. Рассмотрим ClassLoader и процесс загрузки классов в будущих постах. Здесь важно сказать, что класс загружается только один раз, при первом к нему обращении в рамках одного класслоадера.
После загрузки каждого класса выделяется память под его статические поля и выполняются статические блоки инициализации. В будущем возможно будет ленивой не только загрузка всего класса, но и инициализация его статических финальных полей.
Далее инстанциируется сам экземпляр. Как и с загрузкой классов, процесс выполняется для всей цепочки наследования, с самого дальнего родителя:
1. Выделяется память в куче для экземпляра, получается ссылка на этот экземпляр;
2. Выполняются инициализации нестатических полей и блоков инициализации в порядке объявления;
3. Вызывается конструктор;
Статические поля интерфейсов не инициализируются при создании объекта, а другого состояния интерфейс не имеет – это исключает вопрос порядка инициализации предков при множественном наследовании.
В процессе конструирования объекта может возникать проблема виртуального вызова в конструкторе, свойственная для многих языков. Effective Java Item 17 рекомендует не использовать переопределяемые методы в расширяемом классе. Иллюстрация неочевидного поведения в результате приведена ниже:
5. Java – Классы и объекты
Java является объектно-ориентированным языком программирования. Как язык, который имеет функцию объектно-ориентирования, он поддерживает следующие основные понятия:
- полиморфизм;
- наследование;
- инкапсуляция;
- абстракция;
- классы;
- объекты;
- экземпляр;
- метод;
- парсинг.
В этом уроке мы рассмотрим объекты и классы в Java, их концепции.
Класс может быть определен как шаблон, который описывает поведение объекта, который в свою очередь имеет состояние и поведение. Он является экземпляром класса. Например: собака может иметь состояние – цвет, имя, а также и поведение – кивать, лаять, есть.
Объекты
Давайте теперь посмотрим вглубь, что является объектами. Если мы рассмотрим реальный мир, то найдём много предметов вокруг нас, автомобили, собаки, люди, и т.д. Все они имеют состояние и образ жизни.
Если учесть, собаку, то ее состояние – имя, порода, цвет, а образ жизни — лай, виляние хвостом, бег.
Если сравнить программный объект в Java с предметов из реального мира, то они имеют очень схожие характеристики, у них также есть состояние и поведение. Программное состояние хранят в полях, а поведение отображается через методы.
Таким образом, в разработке программного обеспечения, методы работают на внутреннем состоянии объекта, а связи с другими, осуществляется с помощью методов.
Классы
Класс, из которого создаются отдельные объекты, обозначен фиолетовым цветом.
Пример создания класса в Java, приводится ниже:
public class Dog < String breed; int age; String color; void barking()< >void hungry() < >void sleeping() < >>
Класс может содержать любой из следующих видов переменных:
- Локальные переменные, определенные внутри методов, конструкторов или блоков. Они будут объявлены и инициализированы в методе, и будут уничтожены, когда метод завершится.
- Переменные экземпляра являются переменными в пределах класса, но и снаружи любого метода. Они инициализируются при загрузке. Переменные экземпляра могут быть доступны из внутри любого метода, конструктора или блоков этого конкретного класса.
- Переменные класса или статические переменные класса в Java объявляются в классе вне любого метода с помощью статического ключевого слова.
В Java классы могут иметь любое количество методов для доступа к значению различных видов методов. В приведенном выше примере, barking(), hungry() и sleeping() являются методами.
Далее упомянуты некоторые из важных тем, которые должны быть рассмотрены для понимания значения классов и объектов в языке программирования.
Конструктор класса
При обсуждении вопроса класса, одной из наиболее важных подтем в Java является конструктор. Каждый класс имеет конструктор. Если мы не напишем его или, например, забудем, компилятор создаст его по умолчанию для этого класса.
Каждый раз, когда в Java создается новый объект, будет вызываться по меньшей мере один конструктор. Главное правило является то, что они должны иметь то же имя, что и класс, который может иметь более одного конструктора.
Пример конструктора приведен ниже:
public class Puppy < public Puppy()< >public Puppy(String name) < // Так выглядит конструктор в Java и у него один параметр, name. >>
Примечание: в следующих разделах мы будем более подробно обсуждать, если у нас будет два разных типа конструкторов.
Создание объекта
Варианты, как создать объект в классе:
- Объявление: объявление переменной с именем переменной с типом объекта.
- Инстанцирование: используется «новое» ключевое слово.
- Инициализация: «новое» ключевое слово сопровождается вызовом конструктора. Этот вызов инициализирует новый объект.
Пример приводится ниже:
public class Puppy < public Puppy(String name)< // Это конструктор и у него один параметр, name. System.out.println("Передаваемое имя:" + name ); >public static void main(String []args) < // Создание объекта myPuppy. Puppy myPuppy = new Puppy( "Багет" ); >>
Если Вы скомпилируете и запустите выше программу, то она выдаст следующий результат:
Передаваемое имя: Багет
Доступ к переменным экземпляра и методам
Переменные и методы доступны в Java через созданные объекты. Чтобы получить доступ к переменной экземпляра, полный путь должен выглядеть следующим образом::
/* Сначала создайте объект */ ObjectReference = new Constructor(); /* Теперь вызовите переменную следующим образом */ ObjectReference.variableName; /* Теперь Вы можете вызвать метод класса */ ObjectReference.MethodName();
Пример
Этот пример объясняет, как получить доступ к переменные экземпляра и методам класса в Java:
public class Puppy < int puppyAge; public Puppy(String name)< // Это конструктор и у него один параметр, name. System.out.println("Передаваемое имя:" + name ); >public void setAge( int age ) < puppyAge = age; >public int getAge( ) < System.out.println("Возраст щенка:" + puppyAge ); return puppyAge; >public static void main(String []args) < /* Создание объекта. */ Puppy myPuppy = new Puppy( "Багет" ); /* Вызов метод класса, чтобы установить возраст щенка. */ myPuppy.setAge( 2 ); /* Вызов другого метода класса, чтобы получить возраст щенка. */ myPuppy.getAge( ); /* Получение переменной экземпляра класса. */ System.out.println("Значение переменной:" + myPuppy.puppyAge ); >>
Если Вы скомпилируете и запустите выше программу, то она выдаст следующий результат:
Передаваемое имя: Багет Возраст щенка: 2 Значение переменной: 2
Правила объявления классов, операторов импорта и пакетов в исходном файле
В последней части этого раздела давайте рассмотрим правила декларации исходного файла. Эти правила в Java имеют важное значение при объявлении классов, операторов импорта и операторов пакета в исходном файле.
- В исходном файле может быть только один публичный класс (public class).
- Исходный файл может иметь несколько «непубличных» классов.
- Название публичного класса должно совпадать с именем исходного файла, который должен иметь расширение .java в конце. Например: имя класса public class Employee<>, то исходный файл должен быть Employee.java.
- Если класс определен внутри пакета, то оператор пакет должно быть первым оператором в исходном файле.
- Если присутствуют операторы импорта, то они должны быть написаны между операторами пакета и объявлением класса. Если нет никаких операторов пакета, то оператор импорта должен быть первой строкой в исходном файле.
- Операторы импорта и пакета будут одинаково выполняться для всех классов, присутствующих в исходном файле. В Java не представляется возможным объявить различные операторы импорта и/или пакета к различным классам в исходном файле.
Классы имеют несколько уровней доступа и существуют различные типы классов: абстрактные классы (abstract class), конечные классы (final class) и т.д. Обо всем этом обсудим в уроке модификаторы доступа.
Помимо указанных выше типов классов, Java также имеет некоторые специальные классы, называемые внутренние (Inner class) и анонимные классы (Anonymous class).
Пакет (package)
При разработке приложений сотни классов и интерфейсов будет написано, поэтому категоризации этих классов является обязательным, а также это делает жизнь намного проще.
Операторы импорта (import)
Если задать полное имя, которое включает в себя пакет и имя класса, то компилятор может легко найти исходный код или классы. В Java импорт это способ задать правильное место для компилятора, чтобы найти конкретный класс.
Например, следующая строка будет просить компилятор загрузить все классы, доступные в каталоге «java_installation/java/io»:
import java.io.*;
Простой пример по выше описанному
Для нашего обучения создадим два класса. Это будут классы Employee и EmployeeTest.
Для начала откройте блокнот и добавьте следующий код. Помните, что этот класс Employee является открытым или публичным классом. Теперь сохраните исходный файл с именем Employee.java.
Класс Employee имеет четыре переменных экземпляра name, age, designation и salary. Он имеет один явно определенный конструктор, который принимает параметр.
import java.io.*; public class Employee < String name; int age; String designation; double salary; // Это конструктор класса Employee. public Employee(String name)< this.name = name; >// Присвоение возраста работника переменной age. public void empAge(int empAge) < age = empAge; >/* Присвоение переменной designation. */ public void empDesignation(String empDesig) < designation = empDesig; >/* Присвоение переменной salary. */ public void empSalary(double empSalary) < salary = empSalary; >/* Вывод подробной информации. */ public void printEmployee() < System.out.println("Имя:"+ name ); System.out.println("Возраст:" + age ); System.out.println("Наименование:" + designation ); System.out.println("Заработная плата:" + salary); >>
Как упоминалось выше, обработка начинается с основного метода. Поэтому для нас, чтобы запустить класс Employee, должен быть главный метод и созданные объекты. Создадим отдельный класс для этих задач.
Ниже приводится класс EmployeeTest, в котором создаются два экземпляра класса Employee и вызывают методы для каждого объекта, для присвоения значений каждой переменной.
Сохраните следующий код в файл «EmployeeTest.java»:
import java.io.*; public class EmployeeTest < public static void main(String args[])< /* Создание двух объектов с помощью конструктора. */ Employee empOne = new Employee("Олег Олегов"); Employee empTwo = new Employee("Иван Иванов"); // Вызов метода для каждого созданного объекта. empOne.empAge(26); empOne.empDesignation("Старший инженер-программист"); empOne.empSalary(1000); empOne.printEmployee(); empTwo.empAge(21); empTwo.empDesignation("Инженер-программист"); empTwo.empSalary(500); empTwo.printEmployee(); >>
Теперь, скомпилировав оба класса, запустим EmployeeTest и получим следующий результат:
C:> javac Employee.java C:> vi EmployeeTest.java C:> javac EmployeeTest.java C:> java EmployeeTest Имя: Олег Олегов Возраст: 26 Наименование: Старший инженер-программист Заработная плата: 1000.0 Имя: Иван Иванов Возраст: 21 Наименование: Инженер-программист Заработная плата: 500.0
В следующем уроке обсудим основные типы данных, и как они могут быть использованы при разработке java-приложений.
Оглавление
- 1. Java – Самоучитель для начинающих
- 2. Java – Обзор языка
- 3. Java – Установка и настройка
- 4. Java – Синтаксис
- 5. Java – Классы и объекты
- 6. Java – Конструкторы
- 7. Java – Типы данных и литералы
- 8. Java – Типы переменных
- 9. Java – Модификаторы
- 10. Java – Операторы
- 11. Java – Циклы и операторы цикла
- 11.1. Java – Цикл while
- 11.2. Java – Цикл for
- 11.3. Java – Улучшенный цикл for
- 11.4. Java – Цикл do..while
- 11.5. Java – Оператор break
- 11.6. Java – Оператор continue
- 12. Java – Операторы принятия решений
- 12.1. Java – Оператор if
- 12.2. Java – Оператор if..else
- 12.3. Java – Вложенный оператор if
- 12.4. Java – Оператор switch..case
- 12.5. Java – Условный оператор (? 🙂
- 13. Java – Числа
- 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
- 13.2. Java – Метод compareTo()
- 13.3. Java – Метод equals()
- 13.4. Java – Метод valueOf()
- 13.5. Java – Метод toString()
- 13.6. Java – Метод parseInt()
- 13.7. Java – Метод Math.abs()
- 13.8. Java – Метод Math.ceil()
- 13.9. Java – Метод Math.floor()
- 13.10. Java – Метод Math.rint()
- 13.11. Java – Метод Math.round()
- 13.12. Java – Метод Math.min()
- 13.13. Java – Метод Math.max()
- 13.14. Java – Метод Math.exp()
- 13.15. Java – Метод Math.log()
- 13.16. Java – Метод Math.pow()
- 13.17. Java – Метод Math.sqrt()
- 13.18. Java – Метод Math.sin()
- 13.19. Java – Метод Math.cos()
- 13.20. Java – Метод Math.tan()
- 13.21. Java – Метод Math.asin()
- 13.22. Java – Метод Math.acos()
- 13.23. Java – Метод Math.atan()
- 13.24. Java – Метод Math.atan2()
- 13.25. Java – Метод Math.toDegrees()
- 13.26. Java – Метод Math.toRadians()
- 13.27. Java – Метод Math.random()
- 14. Java – Символы
- 14.1. Java – Метод Character.isLetter()
- 14.2. Java – Метод Character.isDigit()
- 14.3. Java – Метод Character.isWhitespace()
- 14.4. Java – Метод Character.isUpperCase()
- 14.5. Java – Метод Character.isLowerCase()
- 14.6. Java – Метод Character.toUpperCase()
- 14.7. Java – Метод Character.toLowerCase()
- 14.8. Java – Метод Character.toString()
- 15. Java – Строки
- 15.1. Java – Метод charAt()
- 15.2. Java – Метод compareTo()
- 15.3. Java – Метод compareToIgnoreCase()
- 15.4. Java – Метод concat()
- 15.5. Java – Метод contentEquals()
- 15.6. Java – Метод copyValueOf()
- 15.7. Java – Метод endsWith()
- 15.8. Java – Метод equals()
- 15.9. Java – Метод equalsIgnoreCase()
- 15.10. Java – Метод getBytes()
- 15.11. Java – Метод getChars()
- 15.12. Java – Метод hashCode()
- 15.13. Java – Метод indexOf()
- 15.14. Java – Метод intern()
- 15.15. Java – Метод lastIndexOf()
- 15.16. Java – Метод length()
- 15.17. Java – Метод matches()
- 15.18. Java – Метод regionMatches()
- 15.19. Java – Метод replace()
- 15.20. Java – Метод replaceAll()
- 15.21. Java – Метод replaceFirst()
- 15.22. Java – Метод split()
- 15.23. Java – Метод startsWith()
- 15.24. Java – Метод subSequence()
- 15.25. Java – Метод substring()
- 15.26. Java – Метод toCharArray()
- 15.27. Java – Метод toLowerCase()
- 15.28. Java – Метод toString()
- 15.29. Java – Метод toUpperCase()
- 15.30. Java – Метод trim()
- 15.31. Java – Метод valueOf()
- 15.32. Java – Классы StringBuilder и StringBuffer
- 15.32.1. Java – Метод append()
- 15.32.2. Java – Метод reverse()
- 15.32.3. Java – Метод delete()
- 15.32.4. Java – Метод insert()
- 15.32.5. Java – Метод replace()
- 16. Java – Массивы
- 17. Java – Дата и время
- 18. Java – Регулярные выражения
- 19. Java – Методы
- 20. Java – Потоки ввода/вывода, файлы и каталоги
- 20.1. Java – Класс ByteArrayInputStream
- 20.2. Java – Класс DataInputStream
- 20.3. Java – Класс ByteArrayOutputStream
- 20.4. Java – Класс DataOutputStream
- 20.5. Java – Класс File
- 20.6. Java – Класс FileReader
- 20.7. Java – Класс FileWriter
- 21. Java – Исключения
- 21.1. Java – Встроенные исключения
- 22. Java – Вложенные и внутренние классы
- 23. Java – Наследование
- 24. Java – Переопределение
- 25. Java – Полиморфизм
- 26. Java – Абстракция
- 27. Java – Инкапсуляция
- 28. Java – Интерфейсы
- 29. Java – Пакеты
- 30. Java – Структуры данных
- 30.1. Java – Интерфейс Enumeration
- 30.2. Java – Класс BitSet
- 30.3. Java – Класс Vector
- 30.4. Java – Класс Stack
- 30.5. Java – Класс Dictionary
- 30.6. Java – Класс Hashtable
- 30.7. Java – Класс Properties
- 31. Java – Коллекции
- 31.1. Java – Интерфейс Collection
- 31.2. Java – Интерфейс List
- 31.3. Java – Интерфейс Set
- 31.4. Java – Интерфейс SortedSet
- 31.5. Java – Интерфейс Map
- 31.6. Java – Интерфейс Map.Entry
- 31.7. Java – Интерфейс SortedMap
- 31.8. Java – Класс LinkedList
- 31.9. Java – Класс ArrayList
- 31.10. Java – Класс HashSet
- 31.11. Java – Класс LinkedHashSet
- 31.12. Java – Класс TreeSet
- 31.13. Java – Класс HashMap
- 31.14. Java – Класс TreeMap
- 31.15. Java – Класс WeakHashMap
- 31.16. Java – Класс LinkedHashMap
- 31.17. Java – Класс IdentityHashMap
- 31.18. Java – Алгоритмы Collection
- 31.19. Java – Iterator и ListIterator
- 31.20. Java – Comparator
- 32. Java – Дженерики
- 33. Java – Сериализация
- 34. Java – Сеть
- 34.1. Java – Обработка URL
- 35. Java – Отправка Email
- 36. Java – Многопоточность
- 36.1. Java – Синхронизация потоков
- 36.2. Java – Межпоточная связь
- 36.3. Java – Взаимная блокировка потоков
- 36.4. Java – Управление потоками
- 37. Java – Основы работы с апплетами
- 38. Java – Javadoc
Классы и создание объектов классов
На предыдущем занятии мы с вами познакомились с общей концепцией ООП. Но, чтобы вы могли все это использовать на практике, в частности, на языке Java, нужно знать как реализуются ее элементы. И, как всегда, начнем по порядку с самого начала – описания способа объявления классов и создания его объектов (экземпляров).
Во всех наших прежних программах у нас фигурировали строчки:
public class Main { public static void main(String[] args) { } }
Смотрите, здесь вначале используется ключевое слово class, за которым следует его название – Main. Далее, открываются фигурные скобки и записывается функция main(), которая является точкой входа в программу. Это пример того, как можно объявлять класс. Начальный синтаксис здесь такой:
[модификаторы] class <
данные (переменные класса);
методы (функции класса);
другие классы и интерфейсы.
>
Как видите, внутри класса можно объявлять переменные, методы, вложенные классы и интерфейсы (что такое интерфейс мы будем говорить позже). Фактически, класс может содержать любые конструкции языка Java и иметь произвольный, самый изощренный функционал.
Конечно, сейчас мы изощряться не будем, а объявим в нашей программе простейший класс и, обычно, я выбираю класс для представления точек на плоскости:
class Point { int x, y; }
Все, вот так просто можно добавить свой собственный класс в программу. Имя этого класса Point и он содержит два поля (две переменные) x и y.
Здесь сразу следует сделать два замечания:
1. В языке Java каждый новый класс принято записывать в отдельном файле проекта. Причем, имя файла должно совпадать с именем класса – это требование языка.
2. Объявление класса может находиться в любом месте программы. Это никак не влияет на возможность его использования, где бы то ни было в рамках проекта.
Например, мы можем создать ссылку типа Point в функции main(), несмотря на то, что сам класс объявлен после нее:
public static void main(String[] args) { Point pt; }
Я пока оставлю объявление класса в этом же файле для упрощения изложения материала. Итак, мы создали ссылку pt на класс Point. Посмотрим повнимательнее на эту запись. Что из нее следует? Да, имя класса можно воспринимать как новый тип данных. И этот тип данных формирует ссылки на соответствующие объекты. Обратите внимание, я произношу слово «ссылка», а не «переменная». В чем разница? Ссылка – это скрытый указатель, который хранит адрес объекта, на который ссылается, а переменная любого примитивного типа – это имя ячейки памяти, в которой непосредственно хранятся данные:

В этом принципиальная разница между ссылками и обычными переменными. Как же узнать, когда мы работаем со ссылками, а когда с переменными? Очень просто:
Если в качестве типа данных используется имя класса или интерфейса, то формируется ссылка. Если же используется примитивный тип данных (например, int, short, double, bool и т.п.), то объявляется обычная переменная.
Итак, мы создали ссылку на класс Point. Но самого объекта в памяти еще нет. Для его создания используется оператор new, за которым указывается имя класса создаваемого экземпляра:
Point pt = new Point();
Все, теперь у нас появился новый объект и на него ссылается переменная pt:

Что, если мы захотим создать еще один такой же объект. Давайте это сделаем вот так:
Мы здесь создаем еще один экземпляр класса Point в памяти устройства, и на него ссылается та же переменная pt. В итоге произойдет следующее:

Прежняя ссылка pt изменит свой адрес и будет ссылаться только на второй объект. Что произойдет с первым? Он так и останется в памяти «безымянным солдатом»? Без единой ссылки? Ссылок на него действительно не будет и пользоваться им мы уже не сможем. Но в памяти он не останется – он будет автоматически уничтожен сборщиком мусора. Это одно из ключевых отличий языка Java от языка C++ – наличие сборщика мусора. Благодаря ему, программист в Java может не беспокоиться об удалении ненужных объектов, то есть, объектов, на которые нет внешних ссылок. И это предотвращает неприятную историю, известную, как «утечка памяти», когда ненужные объекты остаются в памяти и постепенно накапливаются по мере работы программы. Это частая проблема языка C++ и, к счастью, в Java ничего подобного нет. Как мы потом увидим, это значительно упрощает программы и увеличивает гибкость программного кода.
Итак, мы научились объявлять классы и создавать его экземпляры. Как теперь обратиться к полям x, y созданного объекта и записать туда числовую информацию? Для этого используется следующий синтаксис:
Например, для доступа к полям через ссылку pt мы должны записать следующее:
pt.x = 1; pt.y = 2;
В результате, в объект, на который ссылается переменная pt будут записаны числа 1 и 2:

Соответственно, их можно потом прочитать оттуда, например, так:
System.out.println("x = " + pt.x + ", y = " + pt.y);
Вот так в самом простом варианте происходит запись и чтение данных из полей объекта. Причем, если создать еще один объект класса Point и записать туда другие числовые значения:
Point pt2 = new Point(); pt2.x = 10; pt2.y = 20; System.out.println("x = " + pt2.x + ", y = " + pt2.y);
То это будут совершенно другие данные, никак не связанные с первыми. То есть, мы получим два независимых объекта класса Point.
Вот так в простейшем случае объявляются классы в Java и создаются их экземпляры. На следующем занятии мы продолжим эту тему и поговорим о конструкторах класса.
Путь кодера
Подвиг 1. Объявить класс Point3D для хранения координат трехмерного пространства. Создать три таких объекта, записать в них различные координаты и вывести их поля в консоль.
Подвиг 2. Объявить класс Line, который бы хранил две координаты: начало и конец линии. Создать два таких объекта, записать и вывести по ним информацию в консоль.
Видео по теме

#11 Концепция объектно-ориентированного программирования (ООП)

#12 Классы и создание объектов классов

#13 Конструкторы, ключевое слово this, инициализаторы

#14 Методы класса, сеттеры и геттеры, public, private, protected

#15 Пакеты, модификаторы конструкторов и классов

#16 Ключевые слова static и final

#17 Внутренние и вложенные классы

#18 Как делается наследование классов

#19 Ключевое слово super, оператор instanceof

#20 Модификаторы private и protected, переопределение методов, полиморфизм

#21 Абстрактные классы и методы

#22 Интерфейсы — объявление и применение

#23 Интерфейсы — приватные, статические и дефолтные методы, наследование интерфейсов

#24 Анонимные внутренние классы

#25 Перечисления (enum)

#26 Обобщения классов (Generics)

#27 Ограничения типов, метасимвольные аргументы, обобщенные методы и конструкторы

#28 Обобщенные интерфейсы, наследование обобщенных классов
© 2024 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта