Новый документ (1). Концепция оопобъектноориентированноепрограммирование
Скачать 469.07 Kb.
|
сравнении объектов при помощи == идет сравнение по ссылкам. При сравнении по equals() идет сравнение по состояниям объектов (реализация метода equals для нового созданного класса ложится на плечи разработчиков). С точки зрения математики equals() обозначает отношение эквивалентности объектов. Эквивалентным называется отношение, которое является симметричным, транзитивным и рефлексивным. ● Рефлексивность: для любого ненулевого x, x.equals(x) вернет true; ● Транзитивность: для любого ненулевого x, y и z, если x.equals(y) и y.equals(z) вернет true, тогда и x.equals(z) вернет true; ● Симметричность: для любого ненулевого x и y, x.equals(y) должно вернуть true, тогда и только тогда, когда y.equals(x) вернет true. ● Также для любого ненулевого x, x.equals(null) должно вернуть false При переопределении equals() обязательно нужно переопределить метод hashCode(). Равные объекты должны возвращать одинаковые хэш коды. Хеш-код — это число. Если более точно, то это битовая строка фиксированной длины, полученная из массива произвольной длины. В терминах Java, хеш-код — это целочисленный результат работы метода, которому в качестве входного параметра передан объект. Этот метод реализован таким образом, что для одного и того же входного объекта, хеш-код всегда будет одинаковым. Следует понимать, что множество возможных хеш-кодов ограничено примитивным типом int , а множество объектов ограничено только нашей фантазией. Отсюда следует утверждение: “Множество объектов мощнее множества хеш-кодов”. Из-за этого ограничения, вполне возможна ситуация, что хеш-коды разных объектов могут совпасть. Здесь главное понять, что: ● Если хеш-коды разные, то и входные объекты гарантированно разные. ● Если хеш-коды равны, то входные объекты не всегда равны. Ситуация, когда у разных объектов одинаковые хеш-коды называется — коллизией. Вероятность возникновения коллизии зависит от используемого алгоритма генерации хеш-кода. Статья с хабра по equals и hashCode: http://habrahabr.ru/post/168195/ 50. Какой метод возвращает строковое представление объекта? someObject. toString() ; 51. Что будет, если переопределить equals не переопределяя hashCode? Какие могут возникнуть проблемы? Нарушится контракт. Классы и методы, которые использовали правила этого контракта могут некорректно работать. Так для объекта HashMap это может привести к тому, что пара, которая была помещена в Map возможно не будет найдена в ней при обращении к Map, если используется новый экземпляр ключа. 52. Есть ли какие-либо рекомендации о том, какие поля следует использовать при подсчете hashCode? Те, которые используют при определении метода equals() . Хэш код должен быть равномерно распределен на области возможных принимаемых значений. 53. Как вы думаете, будут ли какие-то проблемы, если у объекта, который используется в качестве ключа в hashMap изменится поле, которое участвует в определении hashCode? Будут. При обращении по ключу мы можем не найти значение. 54. Чем отличается абстрактный класс от интерфейса, в каких случаях что вы будете использовать? Синтаксические отличия интерфейса от абстрактного класса? Таблица 1 Абстрактные классы abstract Интерфейсы interface 1 Возможность содержать неопределенные переменные Может содержать и пустые и заполненные переменные Только явно определенные КОНСТАНТЫ, static, final 2 Модификаторы доступа Любой модификатор доступа public по умолчанию 3 Реализация методов Может содержать готовые и абстрактные методы, обязательно реализуемые в классе наследнике, имеет конструктор Может содержать только пустые методы, которые обязательно реализовывать в реализующем классе (либо методы default), не имеет конструктора 4 Наследование и реализация Наследуется только один абстрактный класс Можно реализовать множество интерфейсов, с возможностью использования в них полей с одинаковым именем переменных 5 Возможность наследоваться Может наследовать другой класс и реализовывать интерфейс (implement interface, extend class) Интерфейс может расширять другой интерфейс, но не может наследовать класс (extend interface) для имплементации класса слово - implements 6 Использования полей Поля могут использоваться только после создания экземпляра класса наследника Поля могут использоваться в реализуемых классах без создания экземпляра , т.к. все поля интерфейса - Константы Абстрактные классы используются только тогда, когда есть «is a» тип отношений; интерфейсы могут быть реализованы классами которые не связаны друг с другом. Абстрактный класс может реализовывать методы; интерфейс может реализовывать статические методы начиная с 8й версии. Интерфейс может описывать константы и методы. Все методы интерфейса по умолчанию являются публичными (public) и абстрактными (abstract), а поля — public static final. С java 8 в интерфейсах можно реализовывать default и статические методы. В Java класс может наследоваться (реализовывать) от многих интерфейсов, но только от одного абстрактного класса. С абстрактными классами вы теряете индивидуальность класса, наследующего его; с интерфейсами вы просто расширяете функциональность каждого класса. интерфейс может реализовывать статические методы и начиная с 8й версии. + default методы с 8 версии 55. Можно ли получить доступ к private переменным класса и если да, то каким образом? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 public class SomeClass { private String name = "SomeNameString"; private Integer x = 25; } public class TestPrivateAccess { public static void main(String[] args) { SomeClass someClass = new SomeClass(); try { Field reflectField = SomeClass.class.getDeclaredField("name"); //NoSuchFieldException e Field reflectField2 = SomeClass.class.getDeclaredField("x"); //NoSuchFieldException e /* Если не дать доступ, то будет ошибка java.lang.IllegalAccessException: Class .. .TestPrivateAccess can not access a member of class .. .SomeClass with 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 modifiers "private" */ reflectField.setAccessible(true); reflectField2.setAccessible(true); String fieldValue = (String) reflectField.get(someClass); //IllegalAccessException ex Integer fieldValue2 = (Integer) reflectField2.get(someClass); //IllegalAccessException ex System.out.println(reflectField);//private java.lang.String ru.javastudy.interview.oop.privateFieldAccess.SomeClass.name System.out.println(fieldValue); //SomeNameString System.out.println(reflectField2);//private java.lang.Integer ru.javastudy.interview.oop.privateFieldAccess.SomeClass.x System.out.println(fieldValue2); //25 } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace();; } 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 } } 56. Что такое volatile и transient? Для чего и в каких случаях можно было бы использовать default? volatile — не используется кэш (имеется ввиду область памяти в которой JVM может сохранять локальную копию переменной, чтобы уменьшить время обращения к переменной) при обращении к полю. Для volatile переменной JVM гарантирует синхронизацию для операций чтения/записи, но не гарантирует для операций изменения значения переменной. transient — указание того, что при сериализации/десериализации данное поле не нужно сериализовать/десериализовывать. 57. Расширение модификаторов при наследовании, переопределении и сокрытии методов. Если у класса-родителя есть метод, объявленный как private, может ли наследник расширить его видимость? А если protected? А сузить видимость? Действует общий принцип: расширять видимость можно, сужать нельзя. private методы видны только внутри класса, для потомков они не видны. Поэтому их и расширить нельзя. 58. Имеет ли смысл объявлять метод private final? Нет, такой метод и так не виден для наследников, а значит не может быть ими переопределен. 59. Какие особенности инициализации final переменных? ● Для поля. Поле помеченное при помощи слова final не может изменить свое значение после инициализации. Не статическое final поле можно инициализировать: при описании, в конструкторе (во всех), в статическом блоке, в динамическом блоке. Статическое final поле (static final) инициализируется либо в статическом блоке, либо при описании. ● Значение локальных переменных, а так же параметров метода помеченных при помощи слова final не могут быть изменены после присвоения. 60. Что будет, если единственный конструктор класса объявлен как final? К конструктору не применимо ключевое слово final . 61. Что такое finalize? Зачем он нужен? Что Вы можете рассказать о сборщике мусора и алгоритмах его работы. Метод finalize() вызывается перед тем, как объект будет удален garbage collector (сборщик мусора, далее gc ). Существует много различных реализаций gc . Основа работы следующая: gc помечает объекты, на которые больше не ссылаются другие объекты для их удаления. Затем на одном из проходов помеченные объекты удаляются. Вызов finalize() не гарантируется, т.к. приложение может быть завершено до того, как будет запущена ещё одна сборка мусора. Да, можно отменить сборку объекта с помощью метода finalize() , присвоив его ссылку какому-то статическому методу. 62. Почему метод clone объявлен как protected? Что необходимо для реализации клонирования? Это указывает на то, что хоть метод и есть в классе Object и разработчик желает им воспользоваться, то его нужно переопределить. Для этого нужно реализовать интерфейс Cloneable , чтобы соблюсти контракт. |