banner banner banner
Объектно-ориентированное программирование на Java. Платформа Java SE
Объектно-ориентированное программирование на Java. Платформа Java SE
Оценить:
Рейтинг: 0

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

Объектно-ориентированное программирование на Java. Платформа Java SE

скачать книгу бесплатно


Мы уже видели три исключения: ArithmeticException, ArrayIndexOutOfBoundsException и NumberFormatException.

Следующее исключение, которое мы увидим, – это исключение NullPointerException.

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

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

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

Тогда мы получим такое же исключение NullPointerException.

Имейте в виду, что «length» – это метод в случае класса String, но поле в случае массива.

И, если мы попытаемся получить доступ к позиции в массиве, который не был инициализирован, программа будет генерировать исключение NullPointerException, а не исключение ArrayIndexOutOfBoundsException.

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

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

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

Второе исключение, которое связано с объектами и классами, и которое мы увидим, это ClassCastException.

Чтобы проиллюстрировать это исключение, рассмотрим эту иерархию классов, где Vehicle является суперклассом, и Car и Bike – это подклассы.

Согласно этой иерархии, можно создать экземпляр класса Car и присвоить его переменной типа Vehicle, потому что Car также является Vehicle.

Это приведение правильное и позволяет нам воспользоваться свойством полиморфизма, сохраняя в одном массиве Vehicle набор объектов классов Car и Bike.

Позже в программе нам может понадобиться привести этот экземпляр к объекту класса Car.

Единственное условие, которое налагает Java, – это сделать это приведение явным.

Однако, если мы попытаемся применить этот экземпляр к объекту класса Bike, программа выбросит ClassCastException во время выполнения, потому что объект в переменной «v» не является байком.

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

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

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

Один и тот же метод может выбросить несколько исключений в зависимости от конкретных обстоятельств.

Примитивы и объекты

Теперь в качестве обобщения.

В Java есть два общих типа данных: примитивы и объекты.

Примитив – это тип данных Java, которые считаются простейшей формой данных.

Данные этого типа хранятся непосредственно в памяти.

Это данные типа int, char, double и boolean.

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

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

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

Так как примитивы такие простые, мы можем выполнять с ними прямые математические операции, такие как сложение, вычитание, деление, и так далее.

Теперь, что такое объект?

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

Такие вещи, как String, Array, Scanner и ArrayList считаются объектами.

И все они начинаются с большой буквы в Java, чтобы обозначить их как объекты.

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

Затем, когда вы передаете это значение в качестве параметра, вы передаете ссылку, а не фактические данные.

И это потому, что объекты намного больше примитивов, и постоянно копировать их очень затратно.

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

Поскольку объекты сложнее примитивов, вы не можете выполнять такие вещи, как сложение и вычитание, как с простыми числами.

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

Например, если вы хотите узнать, сколько символов в строке, вы вызываете метод length.

Каждый объект имеет свой собственный набор моделей поведения.

И есть одна вещь, о которой нужно знать.

Это специальное ключевое слово null.

Null – это просто слово, которое означает отсутствие объекта.

По сути, это значение 0 для объекта.

Точно так же, как 0 – это значение 0 для int или 0.0 – это значение 0 для double.

Null – это значение 0 для всех типов объектов.

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

Если мы создадим новый массив символов, мы знаем, что он хранит значения нулей по умолчанию.

Но что он хранит в случае, когда мы создаем массив строк?

Это Null.

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

Это важно знать, потому что вы можете столкнуться с очень распространенным типом исключения Null Pointer.

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

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

Там нет строки, поэтому мы получаем так называемое исключение Null Pointer.

Вы не можете назвать длину того, чего не существует.

Имейте в виду, что null означает объект, а не пустой объект.

Например, вы можете вызвать метод length для пустой String.

Это длина равна нулю.

Но нет такой длины, как длина того, чего не существует.

Просто важно знать, что null означает, что здесь нет объекта.

И нам нужно туда его поместить.

Теперь, когда мы понимаем, что такое примитив и что такое объект, важно понять, как компьютер рассматривает эти два типа переменных в своей собственной памяти.

Потому что это оказывает огромное влияние на то, как вы их программируете.

Представим себе, что это память компьютера.

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

Это общая сетка с адресами для каждого отдельного местоположения, очень похожая на массив.

Когда вы создаете новую переменную примитивного типа, компьютер занимает одно место в памяти и просто помещает эту информацию прямо там, имя и значение переменной.

Когда вы создаете новый объект, он является динамическим.

Он может расти и сокращаться, он может быть большим.

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

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

И затем он занимает целую секцию памяти для какого-либо большого объекта.

И, теперь у нас есть массив, находящийся в памяти, где одна из ячеек хранит адрес, где находятся реальные данные.

Это и есть ссылка.

Таким образом существует большое различие между примитивами и объектами.

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

Они настолько малы, что это имеет смысл.

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

Между ними нет реальной связи.

Это будут две совершенно разные переменные.

Как вы можете себе представить, объекты функционируют по-другому.

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

Поэтому, если я создаю новый массив, а затем создаю другой массив, и устанавливаю его равным первому массиву, что копируется?

Компьютер копирует ссылку.

Теперь у меня есть две переменные, которые указывают на одну и ту же информацию.

Поэтому, если я что-то изменяю в массиве z, изменится и массив y, и наоборот.

Вы просто скопировали адрес, где находится информация.

Поэтому, если я создам объект и передам его как параметр в метод, я передам ссылку или адрес.

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

Мне даже не нужно возвращать его в методе.

Как было сказано ранее, массивы – это объекты. Однако, у них нет полезных методов внутри объекта Array.

Для этого в Java есть класс Arrays,

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

Вот несколько популярных методов из класса Arrays.

Метод toString возвращает строковое представление массива.