Каким правилам необходимо следовать при наследовании если хотим переопределить метод с исключением

Обновлено: 25.06.2024

О возможности перегрузки методов мы уже говорили – имеется в виду объявление нескольких методов класса с одним и тем же именем, но с различными сигнатурами. Термин переопределение метода означает замещение версии метода, объявленной в базовом классе, новой, с точно такой же сигнатурой.

Перегружая (overloading) унаследованный метод базового класса, мы просто добавляем в объявление производного класса новый метод

При переопределении метода в производном классе его возвращаемый тип, наименование и сигнатура должны оставаться теми же, что объявлены в базовом классе. Если два метода различаются только, скажем, типом возвращаемого значения, это считается ошибкой и компилятор на неё укажет.

Переопределённые методы обладают собственными признаками доступа. В производном классе разрешается изменять уровень

унаследованному методу базового класса, но только

повышения. Метод, объявленный как protected

в базовом классе, в производном может быть переопределён вновь с тем же модификатором protected (и это обычная практика) либо помечен как public , но снабжать его модификатором private или полностью лишать явного модификатора доступа (предусматривая признак доступа уровня пакета) нельзя. Уменьшение возможности доступа к методу относительно того уровня, который определён в базовом классе, нарушает контракт базового класса, и экземпляр производного класса теперь не может быть использован в контексте, предусматривающем применение базового.

При переопределении метода позволяется изменять и другие модификаторы. Признаками synchronized , native и strictfp

разрешено манипулировать совершенно свободно, поскольку они относятся исключительно к особенностям внутренней реализации метода. Переопределённый метод может быть помечен как final , но тот, который подвергается переопределению – нет. Метод экземпляра производного класса не может обладать той же сигнатурой, что и статический унаследованный метод, и наоборот. Переопределённый метод в производном классе, однако, может быть снабжён модификатором abstract даже в том случае, если в базовом этого предусмотрено не было.

В производном классе допускается иная трактовка возможности и необходимости использования модификатора final по отношению к параметрам метода: модификатор параметров final не входит в состав сигнатуры и обусловливает только особенности внутренней реализации метода.

4.4 Сокрытие полей

Поля класса не допускают переопределения – их можно только скрыть (hide). Когда в производном классе объявляется поле с тем же именем, что и в базовом, прежнее поле продолжает существовать, но перестаёт быть доступным, если обращаться к нему непосредственно по имени. Чтобы сослаться на одноимённое поле, принадлежащее базовому классу, следует воспользоваться служебным словом super либо сослаться на текущий объект с приведением типа к базовому классу.

4.5 Доступ к унаследованным членам класса

Если вызывается метод посредством ссылки на объект, выбор одной из возможных альтернатив обусловливается фактическим классом объекта. Если же осуществляется обращение к полю, в рассмотрение принимается объявленный тип ссылки. Пример 63 иллюстрирует сказанное.

Пример 63 . Переопределение методов и сокрытие полей class SuperShow

public String str = "SuperStr";

class ExtendShow extends SuperShow< public String str = "ExtendStr";

System.out.println("sup.str: " +sup.str); System.out.println("ext.str: " + ext.str);

Вот как выглядит результат работы программы:

Extend.show: ExtendStr Extend.show: ExtendStr sup.str: SuperStr ext.str: ExtendStr

Существует только один объект, но две переменные, ссылающиеся на него: одна относится к типу SuperShow (базовому классу), а другая – к ExtendShow (фактическому классу). Что касается метода show() , результат работы программы вполне предсказуем: выбор одного из двух перегруженных методов определяется фактическим классом объекта, а не типом переменной, ссылающейся на него. У нас есть единственный объект типа ExtendShow , и при обращении к методу show() всегда вызывается именно тот show() , который описан в ExtendShow , даже если ссылка на объект осуществляется через переменную базового типа SuperShow . Это происходит в любом случае: и когда обращение к show() выполняется с помощью внешнего вызова (как в примере), и при вызове show() из тела другого метода.

При выборе одного из двух одноимённых полей учитывается объявленный тип ссылки на объект, а не тип самого объекта. Действительно, каждый объект класса ExtendShow обладает двумя полями типа String , названными str , одно из которых, объявленное в классе SuperShow , скрыто тем, что определено в ExtendShow . Непосредственный акт выбора осуществляется во время компиляции сучётом типа ссылки, используемойдлядоступакполю объекта.

Внутри тела метода, такого как, например, show() , ссылка на поле всегда указывает именно на то поле, которое объявлено в классе, где объявлен и сам метод, либо на унаследованное поле, если соответствующее объявление поля в данном классе отсутствует. Поэтому в методе SuperShow.show() ссылка на str указывает в действительности на SuperShow.str , а в ExtendShow.show() – на ExtendShow.str .

Механизм переопределения методов позволяет расширять существующий код, наделяя его новыми специализированными функциями, которые не были изначально предусмотрены автором

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

Важно понимать, что переопределение методов является фундаментальной особенностью объектно-ориентированных языков, и способы вызова методов родительских классов являются важным средством инкапсуляции и повторного использования кода, в то время как сокрытие полей возникает лишь как неудобный побочный эффект от возможности назначить произвольное имя для поля в дочернем классе, и весь механизм доступа к скрытым полям предназначен для преодоления последствий этого побочного эффекта.

Суперкласс (родитель) — основной класс, от которого принимаются все элементы.

Подкласс (расширенный, дочерний) — класс, который преобразовывается от другого класса, при этом может иметь свои элементы.

Зачем применяют наследование в Java? Суть в том, что можно образовать новые классы, используя уже имеющийся код. При этом есть возможность добавить другие переменные в дочерний класс, получив при этом новый.

Синтаксис:

Ключевое слово extends означает, что создается новый класс от уже имеющегося.

Из примера видно, что класс Apple создается из Fruit, при этом наследуются все его элементы. Так, Fruit — это класс-родитель, а Apple — класс-потомок.

Как наследовать?

Основной и дочерний класcы создают определенную иерархию. На вершине — всегда базовый, а под ним строятся подклассы. При этом преобразованный класс служит родителем для других подклассов.

В Java существуют такие способы преобразования:

  • одиночное;
  • многоуровневое;
  • иерархическое.

Рассмотрим их по порядку.

Одиночное наследование

Механизм одиночного наследования очень прост: подкласс получает свойства только от одного основного класса:

Многоуровневое наследование

Многоуровневый процесс происходит при наследовании дополнительного класса от базового, затем этот же класс действует уже как основной для следующего:

То есть, в конце мы обращаемся к методу walk() от Pet, потом к sleep() от Cat, а затем к purr () от Kitty.

Иерархическое наследование

Иерархическое наследование происходит, когда несколько подклассов получают разрешение от одного суперкласса:

Класс Kitty унаследовал от Pet walk(), а также у него есть свой purr (), соответственно метод sleep() от Cat ему не доступен.

Правила наследования

Написание кода подчиняется своим законам. В Java также есть определенные правила.

Обращение к методу родителя с помощью super

Чтобы обратиться к методу родителя, нужно использовать ключевое слово super.

Давайте используем один из предыдущих вариантов-примеров, добавив super в преобразованный Cow:

В главном Pet есть walk (), также и в расширенном Сow, но уже с приставкой super.walk (), мы обращаемся к walk () в суперкласс из подкласса.

Получение доступа к защищенным элементам и методам

Если protected (защищен) стоит перед элементами и методами — это указание на то, что к ним можно обратиться из производного класса:

Как видно из примера, у нас есть основной класс — Pet — с защищенными name и display. Чтобы обойти эту защиту, мы создали новый объект small подкласса Kitty и получили необходимый доступ.

Наследовать можно всего один класс

Интересно, что в Java нет многократного наследования — оно возможно только от одного суперкласса.

Важно! В Java класс не может унаследовать ничего сам от себя.

Наследуется все, кроме приватных переменных и методов

В Java модификатор private сообщает о том, что классы-наследники не получат от родителя элементы с таким обозначением. Если вы попробуете произвести extends, компилятор выдаст ошибку.

Как переделать метод класса-родителя

Override (переопределение) — мощный инструмент, который применяется, когда необходимо изменить или переопределить реализацию метода, полученного от суперкласса.

Важные моменты при использовании Override:

  • переопределить можно только унаследованные методы;
  • название и параметры метода в родителе и наследнике — одинаковые;
  • методы с обозначением private не переопределяются.

Как запретить наследование

Запретить создание подкласса можно просто применив final. Если класс отмечен как final, то ни один другой класс не может унаследовать от него элементы .

В результате мы получим ошибку.

Pet обозначен как final, поэтому Kitty не может получить от него ни поля ни переменных .

Highload нужны авторы технических текстов. Вы наш человек, если разбираетесь в разработке, знаете языки программирования и умеете просто писать о сложном!
Откликнуться на вакансию можно здесь .

Переопределение метода – это случай, когда подкласс и суперкласс содержат методы, которые имеют одинаковое имя и сигнатуру типов (рисунок 1). Переопределение метода возникает в случаях, когда классы образовывают иерархию наследования.

Java. Наследование. Пример переопределения метода суперкласса A в подклассе B

Рисунок 1. Пример переопределения метода method() суперкласса A в подклассе B

На рисунке 1 класс B наследует (расширяет) класс A . Класс A есть суперклассом для класса B . В подклассе B объявляется метод с таким же именем как и в суперклассе A . Итак, в данном случае, метод с именем method() суперкласса A есть переопределенным в подклассе B .

2. Какое отличие между переопределением и перегрузкой метода?

В иерархии наследования методы суперклассов и подклассов могут быть переопределенными и перегруженными.
Между переопределением и перегрузкой метода есть следующее отличие:

  • при переопределении методы суперкласса и подкласса носят одинаковое имя и одинаковую сигнатуру типов параметров (см. рис. 1 );
  • при перегрузке методы суперкласса и подкласса носят одинаковое имя но разные сигнатуры типов параметров. На рисунке 2 продемонстрирована перегрузка метода в иерархии наследования.

Рисунок 2. Пример перегрузки метода с именем method() в классах A , B , C которые образовывают иерархию

На рисунке 2 изображены 3 класса с именами A , B , C которые образуют иерархию наследования. Класс B наследует класс A . Класс C наследует класс B . Во всех классах реализованы разные методы, которые имеют одинаковое имя method() . Параметры метода в каждом классе отличаются. Это означает, что метод method() есть перегруженым.

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

Если в суперклассе и подклассе реализованы методы, которые носят одинаковое имя и сигнатуру типов параметров, то действует следующее правило:

  • метод из подкласса переопределяет метод суперкласса.

На рисунке 3 схематически изображено правило взаимодействия между одноименными методами суперкласса и подкласса.

Java. Наследование. Переопределение метода суперкласса в методе подкласса

Рисунок 3. Демонстрация переопределения метода суперкласса в методе подкласса

На рисунке 3 изображен пример переопределения метода суперкласса в подклассе. Объявляется 3 класса с именами A , B , C . В каждом классе реализован метод с именем method() без параметров. Этот метод имеет одинаковую сигнатуру во всех классах.

Каждый объект (экземпляр) класса вызывает метод класса на который он был объявлен. Из экземпляра objB вызывается метод method() который реализован в классе B . Из экземпляра objC вызывается метод method() , который реализован в классе C .

Ниже приведен текст программы демонстрирующей переопределение методов, изображенных на рисунке 3.

Результат выполнения программы

4. Получение доступа из метода подкласса к методу суперкласса в случае, когда совпадают имена методов и сигнатуры их параметров. Ключевое слово super . Пример

Иногда нужно получить доступ из метода подкласса к методу суперкласса, который имеет такое же имя и сигнатуру параметров. В этом случае используется ключевое слово super.

На рисунке 4 изображен доступ к методу суперкласса A из подкласса B . В подклассе B есть метод с таким же именем и списком параметров, поэтому, этот метод переопределяет метод суперкласса. Чтобы доступиться к методу суперкласса A в методе подкласса B используется ключевое слово super .

Java. Наследование. Вызов метода суперкласса из метода подкласса с помощью ключевого слова super

Рисунок 4. Вызов метода суперкласса из метода подкласса с помощью ключевого слова super

Текст программы, которая демонстрирует рисунок 4 следующий

Результат выполнения программы

5. Пример, который демонстрирует перегрузку методов в классах, которые образовывают иерархию наследования

Если классы образовывают иерархию путем наследования, то в этих классах имена методов могут совпадать.

Метод считается перегруженным (не переопределенным) в случае, если:

  • в разных классах существует метод с таким же именем;
  • сигнатура параметров метода в каждом классе отличается.

Таким образом, методы с разными сигнатурами считаются перегруженными а не переопределенными.

На рисунке 5 изображен пример перегрузки метода с именем method() . Объявляются три класса с именами A , B , C которые образовывают иерархию. В классе A метод с именем method() реализован без параметров. В классе B метод с именем method() реализован с одним параметром типа int . В классе C метод с именем method() реализован с одним параметром типа double .

Java. Наследование. Перегрузка метода в классах, которые образовывают иерархию

Рисунок 5. Перегрузка метода с именем method() в классах, которые образовывают иерархию

Текст программы, которая демонстрирует рисунок 5 следующий

Результат работы программы

6. Что такое динамическая диспетчеризация методов? Пример реализации полиморфизма в Java

Динамическая диспетчеризация методов есть один из наиболее эффективных принципов объектно-ориентированного программирования.

Динамическая диспетчеризация методов – это специальный механизм, который позволяет вызвать переопределенный метод в процессе выполнения программы а не во время компиляции. Динамическая диспетчеризация методов важна при реализации полиморфизма.

Рисунок 6 демонстрирует динамическую диспетчеризацию методов. Реализованы 3 класса с именами A , B , C которые образуют иерархию. В каждом классе реализован метод с именем method() . Сигнатура метода во всех классах одинаковая.

Java. Наследование. Динамическая диспетчеризация методов для трех классов

Рисунок 6. Демонстрация динамической диспетчеризации методов для трех классов, которые образуют иерархию

В начале кода демонстрации (рисунок 6) объявляется ссылка refA на базовый класс A

Теперь этой ссылке можно присваивать значение ссылки на подкласс класса A .

Таким образом, с помощью ссылки refA можно вызвать методы экземпляров классов A , B , C которые образуют иерархию. Если refA ссылается на экземпляр класса A , то строка

будет вызывать метод с именем method() класса A .

Аналогично, если ссылка refA ссылается на экземпляр (объект) класса B , то

будет вызывать соответствующий метод класса B .

Вышесказанное касается и класса C .

Как видно из рисунка 6, соответствующий вариант метода method() определяется типом объекта, на который ссылается ссылка refA , а не типом этой ссылки в момент ее объявления.

Ниже приведен программный код, который демонстрирует динамическую диспетчеризацию методов, изображенную на рисунке 6.

Результат выполнения программы

7. Пример, демонстрирующий способы реализации полиморфизма (динамической диспетчеризации методов)

Полиморфизм может быть реализован в программах двумя способами:

  • при присваивании ( = ) ссылке на базовый класс экземпляра любого производного класса. В этом случае, с помощью ссылки (через символ ‘ . ‘) вызывается переопределенный метод того экземпляра, на который в данный момент указывает эта ссылка;
  • при реализации некоторого метода, который получает параметром ссылку на базовый класс. В этом случае, в теле метода вызывается переопределенный метод по ссылке (метод, имеет общее имя и сигнатуру во всех классах иерархии). От того, на экземпляр какого класса указывает ссылка, зависит какой именно переопределенный метод будет вызван.

Нижеследующий пример демонстрирует эти два случая на примере иерархии из трех классов A , B , C . Все классы имеют метод Print() без параметров.

При наследовании методы и поля существующего класса используются повторно (наследуются) вновь создаваемым классом, причем для адаптации класса к новым условиям в него добавляют дополнительные поля и методы.

Рефлексия — позволяет исследовать свойства классов в ходе выполнения программы.

Определение подкласса


class Villa extends Building
Дополнительные методы и поля
>

Если мы в классе Villa хотим определить новый метод getArea(), который будет также учитывать площадь участка вокруг виллы, то:


public double getArea()
double baseArea = super.getArea();//вызов метода getaArea() из суперкласса.
return baseArea + outsideArea;
>

super не означает ссылку на объект. По нему нельзя присвоить значение другой объектной переменной. Это слово всего лишь означает, что нужно вызвать метод из суперкласса.


public Villa(String s, double a)
super(s,a)
outsideArea=0;
>

Мы можем создать массив такого типа:


Building[] quarter = new Building;

Данный массив может также хранить объекты класса Village.


for (Building b : quarter)
System.out.println(b.getArea());

Причем для объекта Village вызовется соответствующий метод getArea() из класса-наследника, а не супер-класса.

Способность переменной (в нашем случае b) ссылаться на объекты, имеющие разные фактические типы, называется полиморфизмом. Автоматический выбор нужного метода во время выполнения программы называется динамическим связыванием.

Полиморфизм

В Java объектные переменные являются полиморфными. Переменная типа Building может ссылаться как на объект класса Building, так и на объект любого подкласса, производного от класса Building.


Villa presidentVilla = new Villa(…);
Building[] quarter = new Building;
quarter = presidentVilla;

presidentVilla.getOutsideArea(); // Допустимо!
quarter.getOutsideArea(); // Ошибка!

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


Villa v = quarter; // ОШИБКА!

Динамическое связывание

Что происходит при вызове метода, принадлежащего некоторому объекту?

Предотвращение наследования: конченые классы и методы

Классы, которые нельзя расширять, называются конечными и обозначаются ключевыми словом final. Все методы конечного класса являются конечными, но не поля!

P.S. с помощью final объявляются константы.

Отдельный метод класса также может быть конечным.

Существует единственный аргумент в пользу указания ключевого слова final при объявлении метода или класса: гарантия неизменности семантики в подклассе.

Приведение типов

Иногда ссылку на объект требуется привести к типу другого класса. Для такого приведения типов существует только одна причина: необходимость использовать все функциональные возможности объекта после того, как его фактический тип был на время забыт.

В процессе своей работы компилятор проверяет, не обещаете ли вы слишком много, сохраняя значение в переменной. Так, если вы присваиваете переменной суперкласса ссылку на объект подкласса, то обещаете меньше положенного, и компилятор разрешает сделать это. А если вы присваиваете объект суперкласса переменной подкласса, то обещаете больше положенного, и поэтому вы должны подтвердить свои обещания, указа в скобках имя класса для приведения типов.

Правила приведения типов при наследовании:

  1. Приведение типов можно выполнять только в иерархии наследования
  2. Для того, чтобы проверить корректность приведения суперкласса к подклассу, следует выполнить операцию instanceof

Но в целом при наследовании лучше свести к минимуму приведение типов и выполнении операции instanceof.

Абстрактные классы

Класс, содержащий один или несколько абстрактных методов, можно объявить абстрактным следующим образом:


abstract class Person
//Реализация метода не требуется
public abstract String getDescription();
>

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

Абстрактные методы представляют собой прототипы методов, реализованных в подклассах. Расширяя абстрактный класс, можно оставить некоторые или все абстрактные методы неопределенными.
Создать экземпляры абстрактного класса нельзя!
Класс может быть объявлен абстрактным, даже если он не содержит ни одного абстрактного метода.

Как только все методы из класса становятся конкретными, класс перестает быть абстрактным.
Абстрактные методы в основном применяются при создании интерфейсов.

Защищенный доступ

У подкласса отсутствует доступ к закрытым полям суперкласса (private).

Если член (поле или метод) класса объявлен как protected, то он доступен не только внутри самого класса, но и внутри всех классов-наследников.

Пользоваться защищёнными полями следует очень аккуратно. Например, если вашим классом будут пользоваться другие разработчики, то вы уже не сможете изменить реализацию класса, не уведомив их. А это противоречит ООП, поощряющему инкапсуляцию данных.

Применение защищенных методов более оправданно. Метод можно объявить защищенным, чтобы ограничить его применение. Это означает, что в методах подклассов, предшественники которых известны изначально, можно вызвать защищенный метод, а методы других классов нельзя.

  1. private — ограничивает область действия классом
  2. public — не ограничивает область действия
  3. protected — ограничивает область действия пакетом и всеми подклассами
  4. модификатор отсутствует — область действия ограничивается пакетом по умолчанию.

Глобальный суперкласс Object

Метод equals

Данный метод реализован в классе Object и он проверяет только следующее: ссылаются ли переменные на один и тот же объект.

Определяя метод equals() для подкласса, сначала следует вызвать одноименный метод из суперкласса. Если проверка даст отрицательный результат, то объекты нельзя считать равнозначными. Если же поля суперкласса совпадают, можно приступать к сравнению полей подкласса.

Спецификация Java требует, чтобы метод equals() обладал следующими характеристиками:

  1. Рефлексивность. При вызове х.equals (х) по любой ненулевой ссылке х должно возвращаться логическое значение true.
  2. Симметричность. При вызове х.equals (у) по любым ссылкам х и у должно
    возвращаться логическое значение true тогда и только тогда, когда при вызове у.equals (х) возвращается логическое значение true.
  3. Транзитивность. Если при вызовах х.equals (у) и у.equals (z) по любым ссылкам х, у и z возвращается логическое значение true, то и при вызове х.equals (z) возвращается логическое значение true.
  4. Согласованность. Если объекты, на которые делаются ссылки х и у, не из­
    меняются, то при повторном вызове х.equals (у) должно возвращаться то же
    самое значение.
  5. При вызове х.equals (null) по любой непустой ссылке х должно возвращаться логическое значение false.

Как создать метод equals()

  1. Присвойте явному параметру имя otherObject. Впоследствии его тип нужно будет привести к типу другой переменной под названием other.
  2. Проверьте, одинаковы ли ссылки this и otherObject, таким образом: if (this == otherObject) return true; Это выражение необходимо лишь для более быстрой проверки.
  3. Выясните, является ли ссылка otherObject пустой (null). Если да, то следует возвратить логическое значение false. if (otherObject == null) return false;
  4. Сравните классы this и otherObject. Если семантика проверки может измениться в подклассе, то воспользуйтесь методом getClass(): if(getClass() != otherObject.getClass()) return false; Если одна и та же семантика остается справедливой для всех подклассов, произведите проверку с помощью instanceof следующим образом: if (!(otherObject instanceof ClassName)) return false;
  5. Приведите тип объекта otherObject к типу переменной требуемого класса: ИмяКласса other = (ИмяКласса)otherObject;
  6. Сравните все поля. Для полей примитивных типов служит операция ==, а для объектных полей — метод Objects.equals(). Если все поля двух объектов совпадают, то возвращается логическое значение true, а иначе — false. return поле1 == other.поле1 && поле2.equals(other.поле2) && …; Если вы переопределяете в подклассе метод equals(), в него следует включить вызов super.equals(other). P.S. Если имеются поля типа массива, то для проверки на равенство соответствующих элементов массива можно воспользоваться статическим методом Arrays.equals().

Метод hashCode()

Хеш-код — это целое число, генерируемое на основе конкретного объекта.
Метод hashCode() определен в классе Object. Поэтому у каждого объекта имеется хеш-код, определяемый по умолчанию.

Методы equals() и hashCode() должны быть совместимы: если в результате вызова x.equals(y) возвращается true, то и результаты вызовов x.hashCode() и y.hashCode() также должны совпадать.

Метод toString()

Данный метод возвращает значение объекта в виде символьной строки.


public String toString()
return getClass().getName()
+ "";
>

При создании подкласса следует определить собственный метод toString() добавить поля подкласса. Так, если в суперклассе вызывается getClass().getName(), то в подклассе просто вызывается метод super.toString().

Имеется веское основание для реализации toString() в каждом классе: если объект объединяется с символьной строкой с помощью операции +, то компилятор Java автоматически вызывает метод toString(), чтобы получить строковое представление этого объекта.

Массивы наследуют метод toString() от класса Object. Поэтому для вывода одномерных массивов можно воспользоваться Arrays.toString(). А для вывода многомерных массивов необходимо вызвать Arrays.deepToString().

Обобщенные списочные массивы

Как мы знаем, задав размер массива, его потом нелегко изменить. Эту проблему проще всего решить, используя списочные массивы. Для этого применяются экземпляры класса ArrayList. Он может динамически изменять размеры массива.

Класс ArrayList является обобщенным с параметром типа. Тип элемента массива пишется в угловых скобках, например: ArrayList.


ArrayList quarter = new ArrayList ();

Начиная с Java 7 можно опускать параметр типа с правой стороны выражения.

Для добавления новых элементов в списочный массив служит метод add().

Первоначальную емкость списочного массива можно передать конструктору:


ArrayList quarter = new ArrayList (100);

Емкость списочного массива может быть увеличена, в отличие от размера массива.

Метод size() возвращает фактическое количество элементов в списочном массиве. Равнозначное выражение для определения размера обычного массива выглядит так: a.length.

Метод trimToSize() используется если вы уверены, что списочный массив будет иметь постоянный размер. Если добавить новые элементы в списочный массив после усечения его размера методом trimToSize(), то блок памяти будет перемещен, на что потребуется дополнительное время.

Доступ к элементам списочных массивов

Класса ArrayList не входит в состав Java, а является служебным классом в стандартной библиотеке. Поэтому вместо удобных квадратных скобок необходимо вызывать методы get() и set().

Внимание! Для заполнения необходимо вызывать add() вместо set()!

LinkedList — если часто вставляем/удаляем, в остальных случаях ArrayList.

Объектные оболочки и автоупаковка

У всех примитивных типов есть аналоги в виде классов. Такие классы принято называть объектными оболочками. Классы объектных оболочек являются неизменяемыми, т.о. изменить значение, хранящееся в объектной оболочке после ее создания, нельзя.


// Автоупаковка это когда запись вида
list.add(3);
// Автоматически преобразуется в данную запись
list.add(new Integer(3));

При сравнении объектов-оболочек необходимо использовать метод equals().

За упаковку и распаковку отвечает отвечает виртуальная машина, а не компилятор.

Читайте также: