Подготовка к собеседованию по JAVACORE. Ответы на вопросы по Core. Core 1 ооп что такое ооп
Скачать 80.55 Kb.
|
Процедурная Java Какие примитивные типы данных есть в Java? В Java есть 8 примитивных типов, которые делят на 4 группы, вот они: Целые числа - byte, short, int, long Числа с плавающей точкой (иначе вещественные) - float, double Логический - boolean Символьный - char Целочисленные типы различаются между собой только диапазонами возможных значений, например, для хранения номера элемента в таблице Менделеева пока хватит переменной типа byte.
Типы с плавающей точкой[править]
Логический тип[править]
Если требуется создать ссылку на один из примитивных типов данных, необходимо использовать соответствующий класс-обертку. Также в таких классах есть некоторые полезные методы и константы, например минимальное значение типа int можно узнать использовав константу Integer.MIN_VALUE. Оборачивание примитива в объект называется упаковкой (boxing), а обратный процесс распаковкой (unboxing).
Что такое автоупаковка и автораспаковка В версиях ниже JDK 1.5 было не легко преобразовывать примитивные типы данных, такие как int, char, float, double в их классы оболочки Integer, Character, Float, Double. Начиная с версии JDK 5 эта функция, преобразования примитивных типов в эквивалентные объекты, реализована автоматически. Это свойство известно как Автоупаковка (Autoboxing). Обратный процесс соответственно – Распаковка (Unboxing) т.е. процесс преобразования объектов в соответствующие им примитивные типы. Автоупаковка применяется компилятором Java в следующих условиях: Когда значение примитивного типа передается в метод в качестве параметра метода, который ожидает объект соответствующего класса-оболочки. Когда значение примитивного типа присваивается переменной, соответствующего класса оболочки. Что такое явное и неявное приведение типов? В каких случаях в java нужно использовать явное приведение? Помимо значений, типы отличаются еще и размером в памяти. int занимает больше, чем byte. А long — больше, чем short. Объем занимаемой примитивами памяти можно сравнить с матрешками: Внутри матрешки есть свободное место. Чем больше матрешка — тем больше места. Внутрь большой матрешки long мы легко можем положить меньшую по размеру int. Она легко уместится, и ничего делать дополнительно не нужно. В Java при работе с примитивами это называется автоматическим преобразованием. По-другому его называют расширением. У нас было изначальное значение — 10000000 Оно хранилось в переменной int, которая занимала 32 бита, и в двоичной форме оно выглядело так: Мы записываем это значение в переменную short, но она может хранить только 16 бит! Соответственно, только первые 16 бит нашего числа и будут туда перемещены, остальные — отбросятся. В итоге в переменную short попадет значение , которое в десятичной форме как раз равно -27008 Именно поэтому компилятор “просил подтверждения” в форме явного приведения к конкретному типу. Во-первых, оно показывает, что ты берешь ответственность за результат на себя, а во-вторых, указывает компилятору сколько места выделить при приведении типов. Ведь если бы мы в последнем примере приводили int к типу byte, а не к short, в нашем распоряжении было бы только 8 бит, а не 16, и результат был бы уже другим. Что такое пул интов? Наверняка вам известно, что при сравнении двух объектов в Java на == обычно получается не тот результат, что нужен, т.к. идет сравнение ссылок на объекты, а не данных этих объектов. Хм, давайте тогда посмотрим на следующий код и на результат его выполнения: public class Temp { public static void main(String []args){ Integer i1 = 10; Integer i2 = 10; System.out.println(i1 == i2); } } Как думаете, что он напечатает? А напечатает он true. А вот еще один код: public class Temp { public static void main(String []args){ Integer i1 = 130; Integer i2 = 130; System.out.println(i1 == i2); } } Этот код уже выведет false. На первый взгляд странно, не так ли? Сейчас объясню. В Java есть пул(pool) целых чисел в промежутке [-128;127]. Т.е. если мы создаем Integer в этом промежутке, то вместо того, чтобы каждый раз создавать новый объект, JVM берет их из пула. Таким образом, в первом примере i1 и i2 указывают на один и тот же объект из пула, а во втором - создаются два разных объекта. Отсюда и результат. Стоит заметить, что в приведенных выше примерах не использовалось ключевое слово new. Какие нюансы у строк в Java? Класс String — immutable, что означает неизменяемость. Также он final, то есть от него нельзя наследоваться, нельзя сделать какую-то свою строку на основе этого класса. Его объекты нельзя изменять после создания. На самом деле все методы, которые якобы меняют строку, создают новый объект. Основными причинами этого являются безопасность и String pool. Безопасность с точки зрения потоков, заключается в отсутствии необходимости синхронизировать операции. Можно передавать строку между потоками. Поэтому не нужно беспокоится, что строка будет изменена. Что такое пул строк? String pool — это некий кэш строк. В памяти, где хранятся объекты, есть место, куда сохраняются строки, созданные путем указания в коде литералов. Для ускорения работы и сохранения памяти можно хранить несколько ссылок на одну строку, если значения их одинаковые. Почему не рекомендуется изменять строки в цикле? Что рекомендуется использовать? Строки являются неизменяемыми объектами и поэтому возможно компилятору придётся создавать как минимум один новый объект, чтобы удержать результат при аппендинге к строкам. Конструирование строки в цикле требует создания новой строки в каждой итерации и поэтому отнимает больше времени и памяти. Это плохо скажется на производительности алгоритма. Почему строки не рекомендуется использовать для хранения паролей? Так как строки в Java являются неизменными, то ваш пароль в виде обычного текста будет доступен в памяти, пока сборщик мусора не очистит её. И поскольку String используются в String pool для повторного использования, существует довольно высокая вероятность того, что пароль останется в памяти надолго, что совсем не безопасно. Любой, у кого есть доступ к дампу памяти, может найти пароль в текстовом виде, и это — серьезная причина, чтобы использовать зашифрованный пароль, а не простой текст. Поскольку строки являются неизменными, их содержимое нельзя изменить. Любое изменение приведет к созданию новой строки. А вот в случае с char [], вы можете заменить любой его элемент нулем или пустым символом. Таким образом, хранение пароля в массиве символов явно снижает риск перехвата пароля. Java сама по себе (ну, через своих создателей, разумеется) рекомендует использовать метод getPassword () из класса JPasswordField, который возвращает char []. Можно также попробовать устаревший (deprecated) метод getText (). Почему бы не последовать рекомендациям авторов языка? С типом String всегда существует опасность того, что текст, хранящийся в строке будет напечатан в файле логов или в консоли. В то же время в случае использования Array, вы не будете печатать содержимое массива, а только его расположение в памяти. Конечно, это не то чтобы серьезная причина, но всё-таки в этом тоже есть смысл. Почему String неизменяемый и финализированный класс? Почему строка является популярным ключом в HashMap в Java? Изменяемость строк несло бы в себе потенциальную угрозу безопасности приложения. Поскольку в Java строки используются для передачи параметров для авторизации, открытия файлов и т.д. — неизменяемость позволяет избежать проблем с доступом. Так как строка неизменяемая то, она безопасна для много поточности и один экземпляр строки может быть совместно использован различными потоками. Это позволяет избежать синхронизации для потокобезопасности. Таким образом, строки в Java полностью потокобезопасны. Поскольку строка неизменная, её hashcode кэшируется в момент создания и нет никакой необходимости рассчитывать его снова. Это делает строку отличным кандидатом для ключа в Map и его обработка будет быстрее, чем других ключей HashMap. Поэтому строка наиболее часто используется в качестве ключа HashMap. Что делает метод intern() в классе String? Когда метод intern() вызван, если пул строк уже содержит строку, эквивалентную к нашему объекту, что подтверждается методом equals(Object), тогда возвращается ссылка на строку из пула. В противном случае объект строки добавляется в пул и ссылка на этот объект возвращается. Этот метод всегда возвращает строку, которая имеет то же значение, что что и текущая строка, но гарантирует что это будет строка из пула уникальных строк. Можно ли использовать строки в конструкции switch? Важные моменты по поводу использования switch со строками в Java: Использование String в операторе switch делает код более читабельным, заменив многократное использование if-else. Оператор switch является чувствительным к регистру. В Switch используется метод String.equals() для сравнивания переданного на вход значения с существующими значениями. Обязательно проверяйте переданную в switch строку на null, иначе можно получить NullPointerException. Согласно Java 7 документации по строкам в switch, компилятор Java генерирует более эффективный байт-код, чем для нескольких if-else. Прежде чем использовать switch в своих программах или проектах на работе, убедитесь, что проект использует Java 7 и выше — иначе будет выброшено исключение. Какая основная разница между String, StringBuffer, StringBuilder? Строка является неизменной и финализированной в Java, поэтому все наши манипуляции со строкой всегда будут создавать новую строку. Манипуляции со строками ресурсоемкие, поэтому Java обеспечивает два полезных класса для манипуляций со строками – StringBuffer и StringBuilder. StringBuffer и StringBuilder являются изменяемыми классами. Операции с StringBuffer потокобезопасны и синхронизированы, а методы StringBuilder не потокобезопасны. Поэтому когда несколько нитей работают с одной строкой, мы должны использовать StringBuffer, но в однопоточном окужении мы должны использовать StringBuilder. StringBuilder более производительный, чем StringBuffer, поскольку не обременен синронизацией. Существуют ли в java многомерные массивы? Java-разработчики иногда пользуются двумерными массивами, гораздо реже — трёхмерными, ну а массивы ещё большей размерности — чрезвычайно редки. С большой долей вероятности вы с ними не будете сталкиваться. Двумерный массив в Java — это массив массивов, то есть в каждой его ячейке находится ссылка на некий массив. Но гораздо проще его представить в виде таблицы, у которой задано количество строк (первое измерение) и количество столбцов (второе измерение). Двумерный массив, у которого все строки имеют равное количество элементов, называется прямоугольным. Какими значениями инициируются переменные по умолчанию? boolean: false char: u0000 (пустой символ) int,short,byte / long: 0 / 0L float /double: 0.0f / 0.0d ссылочные типы: null Что такое сигнатура метода? Сигнатура метода — это имя метода плюс параметры (причем порядок параметров имеет значение). В сигнатуру метода не входит возвращаемое значение, а также бросаемые им исключения. Расскажите про метод main Метод main() отличается от всех остальных методов тем, что является, как правило, точкой входа в программу. Этот метод вызывается виртуальной машиной Java. Как только заканчивается выполнение метода main(), так сразу же завершается, тем самым, работа самой программы. Метод main(), так и любой другой метод, должен быть обязательно вложен в класс. После компиляции класс, содержащий метод main(), запускается на выполнение командой java ПолноеИмяКласса Эта команда приводит к выполнению метода main(), вложенного в данный класс. Оговоримся, что после имени класса могут следовать параметры командной строки, которые будут обсуждаться ниже. Каким образом переменные передаются в методы, по значению или по ссылке? Данные передаются между методами через параметры. Есть два способа передачи параметров: Передача по значению (by value). Значения фактических параметров копируются. Вызываемый метод создает свою копию значений аргументов и затем ее использует. Поскольку работа ведется с копией, на исходный параметр это никак не влияет. Передача по ссылке (by reference). Параметры передаются как ссылка (адрес) на исходную переменную. Вызываемый метод не создает свою копию, а ссылается на исходное значение. Следовательно, изменения, сделанные в вызываемом методе, также будут отражены в исходном значении. В Java переменные хранятся следующим образом: Локальные переменные, такие как примитивы и ссылки на объекты, создаются в стеке. Объекты — в куче (heap). Теперь вернемся к основному вопросу: переменные передаются по значению или по ссылке? Java всегда передает параметры по значению ООП в Java Какие виды классов есть в java? В Java есть 4 вида классов внутри другого класса: Вложенные внутренние классы – нестатические классы внутри внешнего класса. Вложенные статические классы – статические классы внутри внешнего класса. Локальные классы Java – классы внутри методов. Анонимные Java классы – классы, которые создаются на ходу. Расскажите про вложенные классы. В каких случаях они применяются? Для начала, нам нужно создать класс Airplane, куда мы можем занести немного описание: название самолета, идентификационный код, рейс. public class Airplane { private String name, id, flight; public Airplane(String name, String id, String flight) { this.name = name; this.id = id; this.flight = flight; } // getters/setters } Теперь мы хотим добавить крылья. Создавать отдельный класс? Возможно в этом и есть логика, если у нас сложная программа для конструирования самолетов, и где нам нужно создавать огромное количество производных классов (классы, которые обладают такой же логикой, как и родительский класс, то есть класс, от которого они наследуются, но так же расширяют родительский класс, добавляя логику или более подробные характеристики), но что, если у нас просто игра, где у нас есть один самолет? Тогда нам будет рациональней укомплектовать всю структуру в одном месте (в одном классе). Тут идут в бой нестатические вложенные классы. По сути, это более подробное описание каких-то деталей нашего внешнего класса. В данном примере, нам нужно создать крылья для самолета – левое и правое. Давайте создавать! public class Airplane { private String name, id, flight; private Wing leftWing = new Wing("Red", "X3"), rightWing = new Wing("Blue", "X3"); public Airplane(String name, String id, String flight) { this.name = name; this.id = id; this.flight = flight; } private class Wing { private String color, model; private Wing(String color, String model) { this.color = color; this.model = model; } // getters/setters } // getters/setters } Так мы создали нестатический вложенный класс Wing (крыло) внутри класса Airplane (самолет), и добавили две переменные – левое крыло и правое крыло. И у каждого крыла есть свои свойства (цвет, модель), которые мы можем изменять. Так можно укомплектовывать структуры столько, сколько нужно. И заметьте: ранее на схеме было довольно много деталей у самолета, и, по сути, мы можем все детали разбить на внутренние классы, однако не всегда такой процесс целесообразен. Такие моменты нужно прослеживать в зависимости от задачи. Возможно, вам вообще не нужны крылья для решения задачи. Тогда и незачем их делать. Это как распилить человека на ноги, руки, торс и голову – можно, но зачем, если данный класс используется только для хранения данных об людях? Особенности нестатических вложенных классов Java: Они существуют только у объектов, потому для их создания нужен объект. Другими словами: мы укомплектовали наше крыло так, чтобы оно было частью самолета, потому, чтобы создать крыло, нам нужен самолет, иначе оно нам не нужно. Внутри Java класса не может быть статических переменных. Если вам нужны какие-то константы или что-либо еще статическое, выносить их нужно во внешний класс. Это связано с тесной связью нестатического вложенного класса с внешним классом. У класса полный доступ ко всем приватным полям внешнего класса. Данная особенность работает в две стороны. Можно получить ссылку на экземпляр внешнего класса. Пример: Airplane.this – ссылка на самолет, this – ссылка на крыло. Статические классы внутри внешнего класса Данный вид классов не отличается ничем от обычного внешнего класса, кроме одного: для создания экземпляра такого класса, нужно через точку перечислить весь путь от внешнего класса до нужного. Например: Building.Plaftorm platform = new Building.Platform(); Статические классы используются для того, чтобы укомплектовать связанные классы рядышком, чтобы с логической структурой было работать проще. Например: мы можем создать внешний класс Building, где будет конкретный список классов, которые будут представлять из себя уже конкретную постройку. public abstract class Building { private String name, address, type; Building(String name, String address) { this.name = name; this.address = address; } public static class Platform extends Building { public Platform(String name, String address) { super(name, address); setType("Platform"); } // some additional logic } public static class House extends Building { public House(String name, String address) { super(name, address); setType("House"); } // some additional logic } public static class Shop extends Building { public Shop(String name, String address) { super(name, address); setType("Shop"); } // some additional logic } // getters/setters } Данный пример демонстрирует, как статические классы позволяют укомплектовывать логическую структуру в более удобный вид. Если бы их не было, нам бы понадобилось создавать 4 совершенно разных класса. Плюсы такого подхода: Количество классов уменьшилось. Все классы внутри их класса-родителя. Мы способны прослеживать всю иерархию без открытия каждого класса отдельно. Мы можем обратиться к классу Building, а IDE уже будет подсказывать весь список всех подклассов данного класса. Это будет упрощать поиск нужных классов и показывать всю картину более цело. |