Собеседование по Java — ООП (вопросы и ответы). Часть 1.
Вопросы и ответы по теме ООП (объектно ориентированное программирование) для собеседования по Java.
К списку вопросов по всем темам
Собеседование по Java – ООП (вопросы и ответы). Часть 2
Собеседование по Java – ООП (вопросы и ответы). Часть 3
Список всех вопросов по ООП
1. Назовите принципы ООП и расскажите о каждом.
2. Дайте определение понятию “класс”.
3. Что такое поле/атрибут класса?
4. Как правильно организовать доступ к полям класса?
5. Дайте определение понятию “конструктор”.
6. Чем отличаются конструкторы по умолчанию, копирования и конструктор с параметрами?
7. Какие модификации уровня доступа вы знаете, расскажите про каждый из них.
8. Расскажите об особенностях класса с единственным закрытым (private) конструктором.
9. О чем говорят ключевые слова “this”, “super”, где и как их можно использовать?
10. Дайте определение понятию “метод”.
11. Что такое сигнатура метода?
12. Какие методы называются перегруженными?
13. Могут ли нестатические методы перегрузить статические?
14. Расскажите про переопределение методов.
15. Может ли метод принимать разное количество параметров (аргументы переменной длины)?
16. Можно ли сузить уровень доступа/тип возвращаемого значения при переопределении метода?
17. Как получить доступ к переопределенным методам родительского класса?
18. Какие преобразования называются нисходящими и восходящими?
19. Чем отличается переопределение от перегрузки?
20. Где можно инициализировать статические/нестатические поля?
21. Зачем нужен оператор instanceof?
22. Зачем нужны и какие бывают блоки инициализации?
23. Каков порядок вызова конструкторов и блоков инициализации двух классов: потомка и его предка?
24. Где и для чего используется модификатор abstract?
25. Можно ли объявить метод абстрактным и статическим одновременно?
26. Что означает ключевое слово static?
27. К каким конструкциям Java применим модификатор static?
28. Что будет, если в static блоке кода возникнет исключительная ситуация?
29. Можно ли перегрузить static метод?
30. Что такое статический класс, какие особенности его использования?
31. Какие особенности инициализации final static переменных?
32. Как влияет модификатор static на класс/метод/поле?
33. О чем говорит ключевое слово final?
34. Дайте определение понятию “интерфейс”.
35. Какие модификаторы по умолчанию имеют поля и методы интерфейсов?
36. Почему нельзя объявить метод интерфейса с модификатором final или static?
37. Какие типы классов бывают в java (вложенные… и.т.д.)
38. Какие особенности создания вложенных классов: простых и статических.
39. Что вы знаете о вложенных классах, зачем они используются? Классификация, варианты использования, о нарушении инкапсуляции.
40. В чем разница вложенных и внутренних классов?
41. Какие классы называются анонимными?
42. Каким образом из вложенного класса получить доступ к полю внешнего класса?
43. Каким образом можно обратиться к локальной переменной метода из анонимного класса, объявленного в теле этого метода? Есть ли какие-нибудь ограничения для такой переменной?
44. Как связан любой пользовательский класс с классом Object?
45. Расскажите про каждый из методов класса Object.
46. Что такое метод equals(). Чем он отличается от операции ==.
47. Если вы хотите переопределить equals(), какие условия должны удовлетворяться для переопределенного метода?
48. Если equals() переопределен, есть ли какие-либо другие методы, которые следует переопределить?
49. В чем особенность работы методов hashCode и equals? Каким образом реализованы методы hashCode и equals в классе Object? Какие правила и соглашения существуют для реализации этих методов? Когда они применяются?
50. Какой метод возвращает строковое представление объекта?
51. Что будет, если переопределить equals не переопределяя hashCode? Какие могут возникнуть проблемы?
52. Есть ли какие-либо рекомендации о том, какие поля следует использовать при подсчете hashCode?
53. Как вы думаете, будут ли какие-то проблемы, если у объекта, который используется в качестве ключа в hashMap изменится поле, которое участвует в определении hashCode?
54. Чем отличается абстрактный класс от интерфейса, в каких случаях что вы будете использовать?
55. Можно ли получить доступ к private переменным класса и если да, то каким образом?
56. Что такое volatile и transient? Для чего и в каких случаях можно было бы использовать default?
57. Расширение модификаторов при наследовании, переопределение и сокрытие методов. Если у класса-родителя есть метод, объявленный как private, может ли наследник расширить его видимость? А если protected? А сузить видимость?
58. Имеет ли смысл объявлять метод private final?
59. Какие особенности инициализации final переменных?
60. Что будет, если единственный конструктор класса объявлен как final?
61. Что такое finalize? Зачем он нужен? Что Вы можете рассказать о сборщике мусора и алгоритмах его работы.
62. Почему метод clone объявлен как protected? Что необходимо для реализации клонирования?
Ответы. Часть 1
1. Назовите принципы ООП и расскажите о каждом.
Объе́ктно-ориенти́рованное программи́рование (ООП) — это методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования.
Основные принципы ООП: абстракция, инкапсуляция, наследование, полиморфизм.
Абстракция — означает выделение значимой информации и исключение из рассмотрения незначимой. С точки зрения программирования это правильное разделение программы на объекты. Абстракция позволяет отобрать главные характеристики и опустить второстепенные.
Пример: описание должностей в компании. Здесь название должности значимая информация, а описание обязанностей у каждой должности это второстепенная информация. К примеру главной характеристикой для «директор» будет то, что это должность чем-то управляет, а чем именно (директор по персоналу, финансовый директор, исполнительный директор) это уже второстепенная информация.
Инкапсуляция — свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе. Для Java корректно будет говорить, что инкапсуляция это «сокрытие реализации». Пример из жизни — пульт от телевизора. Мы нажимаем кнопочку «увеличить громкость» и она увеличивается, но в этот момент происходят десятки процессов, которые скрыты от нас. Для Java: можно создать класс с 10 методами, например вычисляющие площадь сложной фигуры, но сделать из них 9 private. 10й метод будет называться «вычислитьПлощадь()» и объявлен public, а в нем уже будут вызываться необходимые скрытые от пользователя методы. Именно его и будет вызывать пользователь.
Наследование — свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью. Класс, от которого производится наследование, называется базовым, родительским или суперклассом. Новый класс — потомком, наследником, дочерним или производным классом.
Полиморфизм — свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта. Пример (чуть переделанный) из Thinking in Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public interface Shape { void draw(); void erase(); } public class Circle implements Shape { public void draw() { System.out.println("Circle.draw()"); } } public class Triangle implements Shape { public void draw() { System.out.println("Triangle.draw()"); } } public class TestPol { public static void main(String[] args) { Shape shape1 = new Circle(); Shape shape2 = new Triangle(); testPoly(shape1); testPoly(shape2); } public static void testPoly(Shape shape) { shape.draw(); } } //Вывод в консоль: //Circle.draw() //Triangle.draw() |
Есть общий интерфейс «Фигура» и две его реализации «Треугольник» и «Круг». У каждого есть метод «нарисовать». Благодаря полиморфизму нам нет нужды писать отдельный метод для каждой из множества фигур, чтобы вызвать метод «нарисовать». Вызов полиморфного метода позволяет одному типу выразить свое отличие от другого, сходного типа, хотя они и происходят от одного базового типа. Это отличие выражается различным действием методов, вызываемых через базовый класс (или интерфейс).
Здесь приведен пример полиморфизма (также называемый динамическим связыванием, или поздним связыванием, или связыванием во время выполнения), в котором продемонстрировано как во время выполнения программы будет выполнен тот метод, который принадлежит передаваемому объекту.
Если бы не было полиморфизма и позднего связывания, то эта же программа выглядела бы примерно так:
1 2 3 4 5 6 |
public static void testPolyCircle(Circle circle) { circle.draw(); } public static void testPolyTriangle(Triangle triangle) { triangle.draw(); } |
Т.е. для каждого класса (фигуры) мы бы писали отдельный метод. Здесь их два, а если фигур (классов) сотни?
2. Дайте определение понятию “класс”.
Класс – это шаблон, описывающий общие свойства группы объектов. Этими свойствами могут быть как характеристики объектов (размер, вес, цвет и т.п.), так и поведения, роли и т.п.
3. Что такое поле/атрибут класса?
Поле (атрибут) класса — это характеристика объекта. Например для фигуры это может быть название, площадь, периметр.
1 2 3 4 5 6 7 |
public class Circle implements Shape { private String name; private Double area; private String perimeter; } |
4. Как правильно организовать доступ к полям класса?
Модификатор доступа — private. Доступ через методы get\set.
5. Дайте определение понятию “конструктор”.
Конструктор — это специальный метод, который вызывается при создании нового объекта. Конструктор инициализирует объект непосредственно во время создания. Имя конструктора совпадает с именем класса, включая регистр, а по синтаксису конструктор похож на метод без возвращаемого значения.
1 2 3 4 5 |
public class Circle implements Shape { public Circle() { } } |
6. Чем отличаются конструкторы по умолчанию, копирования и конструктор с параметрами?
Конструктор по умолчанию не принимает никаких параметров. Конструктор копирования принимает в качестве параметра объект класса. Конструктор с параметрами принимает на вход параметры (обычно необходимые для инициализации полей класса).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//конструктор по умолчанию public Circle() { } //конструктор копирования public Circle(Circle circle) { this(circle.getName(), circle.getArea(), circle.getPerimeter()); //будет вызван конструктор с параметрами ниже } //конструктор с параметрами public Circle(String name, Double area, String perimeter) { this.name = name; this.area = area; this.perimeter = perimeter; } |
Обращаю внимание, что тема копирования (clone()) достаточно глубокая с возможностью возникновения множества неявных проблем. Немного можно почитать здесь http://habrahabr.ru/post/246993/.
7. Какие модификации уровня доступа вы знаете, расскажите про каждый из них.
- private (закрытый) — доступ к члену класса не предоставляется никому, кроме методов этого класса. Другие классы того же пакета также не могут обращаться к private-членам.
- default, package, friendly, доступ по умолчанию, когда никакой модификатор не присутствует — член класса считается открытым внутри своего собственного пакета, но не доступен для кода, расположенного вне этого пакета.Т.е. если package2.Class2 extends package1.MainClass, то в Class2 методы без идентификатора из MainClass видны не будут.
- protected (защищённый) — доступ в пределах пакета и классов наследников. Доступ в классе из другого пакета будет к методам public и protected главного класса. Т.е. если package2.Class2 extends package1.MainClass, то внутри package2.Class2 методы с идентификатором protected из MainClass будут видны.
- public (открытый) — доступ для всех из любого другого кода проекта
Модификаторы в списке расположены по возрастающей видимости в программе.
8. Расскажите об особенностях класса с единственным закрытым (private) конструктором.
Невозможно создать объект класса у которого единственный private конструктор за пределами класса. Поэтому нельзя унаследоваться от такого класса. При попытке унаследоваться будет выдаваться ошибка: There is no default constructor available in имяКласса. А при попытке создать объект этого класса: ИмяКласса() has private access in ИмяКласса
9. О чем говорят ключевые слова “this”, “super”, где и как их можно использовать?
super — используется для обращения к базовому классу, а this к текущему. Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class Animal { public void eat() { System.out.println("animal eat"); } } public class Dog extends Animal { public void eat() { System.out.println("Dog eat"); } public void thisEat() { System.out.println("Call Dog.eat()"); this.eat(); } public void superEat() { System.out.println("Call Animal.eat()"); super.eat(); } } public class Test { public static void main(String[] args) { Dog dog = new Dog(); dog.eat(); dog.thisEat(); dog.superEat(); } } Dog eat Call Dog.eat() Dog eat Call Animal.eat() animal eat |
Если написать super(), то будет вызван конструктор базового класса, а если this(), то конструктор текущего класса. Это можно использовать, например, при вызове конструктора с параметрами:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public Dog() { System.out.println("Call empty constructor"); } public Dog(String name) { System.out.println("Call constructor with Name"); this.name = name; } public Dog(String name, Double weight) { this(name); this.weight = weight; System.out.println("Call constructor with Name and Weight"); } } .. public static void main(String[] args) { Dog dog1 = new Dog("name", 25.0); } //Вывод Call constructor with Name Call constructor with Name and Weight |
10. Дайте определение понятию “метод”.
Метод — это последовательность команд, которые вызываются по определенному имени. Можно сказать что это функция и процедура (в случае void метода).
11. Что такое сигнатура метода?
Сигнатура метода в Java — это имя метода плюс параметры (причем порядок параметров имеет значение).
В сигнатуру метода не входит возвращаемое значение, бросаемые им исключения, а также модификаторы.
Ключевые слова public, protected, private, abstract, static, final, synchronized, native, strictfp в т.ч. аннотации для метода — это модификаторы и не являются частью сигнатуры.
http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2
12. Какие методы называются перегруженными?
Java позволяет создавать несколько методов с одинаковыми именами, но разными параметрами. Создание метода с тем же именем, но с другим набором параметров называется перегрузкой. Какой из перегруженных методов должен выполняться при вызове, Java определяет на основе фактических параметров.
1 2 3 4 5 |
public void method() { } public void method(int a) { } public void method(String str) { } |
13. Могут ли нестатические методы перегрузить статические?
Да. Это будут просто два разных метода для программы. Статический будет доступен по имени класса.
14. Расскажите про переопределение методов. Могут ли быть переопределены статические методы?
Метод в классе-наследнике, совпадающий по сигнатуре с методом из родительского класса называется переопределенным методом. Переопределить базовый статический метод нельзя: Instance method имяМетода in классНаследник cannot override method имяМетода in родительскийКласс
15. Может ли метод принимать разное количество параметров (аргументы переменной длины)?
Да. Запись имеет вид method(type … val). Например public void method(String … strings), где strings это массив, т.е. можно записать
1 2 3 4 5 |
public void method (String ... strings) { for (String s : strings) { } } |
16. Можно ли сузить уровень доступа/тип возвращаемого значения при переопределении метода?
При переопределении метода нельзя сузить модификатор доступа к методу (например с public в MainClass до private в Class extends MainClass). Изменить тип возвращаемого значения при переопределении метода нельзя, будет ошибка attempting to use incompatible return type. Но можно сузить возвращаемое значение, если они совместимы. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class Animal { public Animal eat() { System.out.println("animal eat"); return null; } public Long calc() { return null; } } public class Dog extends Animal { public Dog eat() { return new Dog(); } /*attempting to use incompatible return type public Integer calc() { return null; } */ } |
17. Как получить доступ к переопределенным методам родительского класса?
super.method();
18. Какие преобразования называются нисходящими и восходящими?
Преобразование от потомка к предку называется восходящим, от предка к потомку — нисходящим. Нисходящее преобразование должно указываться явно с помощью указания нового типа в скобках.
Например:
1 2 3 4 |
Animal dog = new Dog(); //восходящее преобразование. Будет потерян доступ ко всем методам, которые есть только у класса Dog. int x = 100; byte y = (byte) x; //нисходящее преобразование. Должно быть указано явно |
19. Чем отличается переопределение от перегрузки?
Переопределение используется тогда, когда вы переписываете (переделываете, переопределяете) УЖЕ существующий метод. Перегрузка — это использование одного имени, но с разными входными параметрами. Например нам нужно, чтобы метод toString() для нашего класса выдавал какой-то осмысленный текст. Тогда мы переопределяем метод из класса Object и реализуем этот метод так, как нам это нужно.
1 2 3 4 |
@Override public String toString() { return "Хочу чтобы писался текст, а не название класса@2234SD!" } |
Тогда как перегрузка обычно используется, чтобы не придумывать каждый раз новое имя, когда методы отличаются только входными параметрами. При перегрузке необходимый метод определяется на этапе компиляции на основе сигнатуры вызываемого метода, тогда как при переопределении нужный метод будет выявлен во время выполнения исходя из реального типа объекта.
20. Где можно инициализировать статические/нестатические поля?
Статические поля можно инициализировать при объявлении, в статическом или динамическом блоке инициализации. Нестатические поля можно инициализировать при объявлении, в динамическом блоке инициализации или в конструкторе.
К списку вопросов по всем темам
Собеседование по Java – ООП (вопросы и ответы). Часть 2
Собеседование по Java – ООП (вопросы и ответы). Часть 3
9 thoughts on “Собеседование по Java — ООП (вопросы и ответы). Часть 1.”
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
20. Где можно инициализировать статические/нестатические поля?
«Статические поля можно инициализировать при объявлении или в статическом блоке инициализации.»
можно и в динамическом, а вот final static можно инициализировать только при объявлении или в статическом блоке инициализации.
32. Как влияет модификатор static на класс/метод/поле?
…
Создать или перезаписать такое поле повторно нельзя (инициализируется один раз). ——— это для static final(P.S. Создать повторно поле??? Возможно я чего то не знаю)
19. Чем отличается переопределение от перегрузки?
Основным отличием является то, что при перегрузке необходимый метод определяется на этапе компиляции на основе сигнатуры вызываемого метода, тогда как при переопределении нужный метод будет выявлен во время выполнения исходя из реального типа объекта.
Восходящее преобразование (от предка от потомку) выполняется неявно, нисходящее (от потомка к предку) — с указанием нового типа в скобках. Исправьте пожалуйста.
Всё правильно написано. Upcasting (восходящее) преобразование, это от SomeClass cls к Object obj (от потомка к предку). Обратно cls = (SomeClass) obj — downcasting (нисходящее преобразование). Указывается явно.
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
a = b; // нисходящее — от предка к потомку — неявно
b = (B) a; // восходящее — от потомка к предку — явно
}
}
class A {}
class B extends A {}
Попутал в своем комментарии немного. Восходящее — от потомка к предку (явно), нисходящее — от предка к потомку (неявно).
public Dog() {
System.out.println(«A»);// это должно быть в конструкторе ниже
}
public Dog(String name) {
System.out.println(«Call empty constructor»);// это в конструкторе выше
this.name = name;
}
16. Можно ли сузить уровень доступа/тип возвращаемого значения при переопределении метода?
«При переопределении метода нельзя сузить модификатор доступа к методу» — модификатор доступа можно расширить
Нельзя применить аннотацию @Override, но в классе-потомке можно определить свой метод с точно такой же сигнатурой, как и в родительском классе. Метод потомка будет «затенять» метод предка и никакой ошибки не возникнет. И если строго придерживаться понятия «Метод в классе-наследнике, совпадающий по сигнатуре с методом из родительского класса называется переопределенным методом.», то можно сказать, что статический метод переопределить можно)
А вот при попытке применить аннотацию @Override возникнет ошибка