User Эллеонора Керри
Эллеонора Керри
41 уровень

Кофе-брейк #123. Java Constructor — вопросы и ответы на техническом собеседовании

Статья из группы Random
Источник: Hackenoon

Что такое Constructor?

Constructor — это специальный метод, определенный в классе с именем, совпадающим с именем класса. Конструктор Java подобен методу, не имеющему возвращаемого типа. Кофе-брейк #123. Java Constructor — вопросы и ответы на техническом собеседовании - 1Конструкторы играют наиболее важную роль при инициализации объектов, и в этой статье мы перечислим примерные вопросы на интервью, которые затрагивают конструкторы в Java. Также вы узнаете о важности конструкторов в Java, увидите примеры кода и другие важные детали, которые помогут вам ответить на вопросы о Java-конструкторах на собеседовании.

Зачем нужны конструкторы? Объясните подробно

Предположим, у нас есть класс с именем Student. И у нас есть имя переменной экземпляра и roll_number.

class Student{
String name;
int rollNo;
}
Теперь, если мы создадим 1000 объектов, то JVM инициализирует эти значения своим типом по умолчанию Name = null и rollNo = 0. Идентификация этих отдельных объектов невозможна, а присвоение значений каждому из объектов увеличит объем кода, что считается плохой практикой в программировании. Поэтому, чтобы этого избежать, используются конструкторы. То есть, цель конструктора в Java состоит в том, чтобы инициализировать значение переменных экземпляра класса.

Какие типы конструкторов существуют в Java?

В Java есть три различных типа конструкторов:
  • Default Constructor (Конструктор по умолчанию)
  • No-Argument Constructor (Конструктор без аргументов)
  • Parameterized Constructor (Параметризованный конструктор)

Что такое Default Constructor в Java?

Конструктор по умолчанию (Default Constructor) — это конструктор, созданный JVM во время выполнения, если конструктор не определен в классе. Основная задача конструктора по умолчанию — инициализировать значения экземпляров в соответствии с их типом по умолчанию. Пример конструктора по умолчанию в Java:

class DefaultConstructor{
int id;
String name;
}
Теперь для этого класса, если мы создадим объект, то внутри JVM появится конструктор по умолчанию, которому присвоено значение по умолчанию.

DefaultConstructor df= new DefaultConstructor();
Теперь, если мы напечатаем значение, то получим:
Print = df.id = 0.df.name = null.

Что такое No-Argument Constructor (Конструктор без аргументов)?

Конструктор без аргументов — это конструктор, который можно явно определить для инициализации значения экземпляров. Например:

class NoArgConstuctor{ int a; int b;

//No Argument Constructor
NoArgConstuctor(){
a = 10;
b = 20;
}

}

Что такое Parameterized Constructor (Параметризованный конструктор)?

Параметризованный конструктор — это конструктор, который принимает параметр для инициализации экземпляров. Например:

class ParameterizedConstuctor{
String name;
int age;
//Parameterized Constructor
ParameterizedConstuctor(String name, int age){
this.name = name;
this.age = age;
}
}

Каковы правила определения конструктора?

Для определения конструкторов необходимо соблюдать несколько правил:
  • Имя конструктора должно совпадать с именем класса.

  • В Java не должно быть возвращаемого типа конструктора.

  • Единственно применяемые модификаторы для конструкторов:

    • public
    • default
    • protected
    • private
  • Конструкторы могут принимать любое количество параметров.

  • Модификаторы final, synchronized, static и abstract в конструкторе недопустимы.

  • Конструктор не поддерживает оператор return внутри своего тела.

  • В конструкторе могут быть исключения с оператором throw.

  • Допустимо использовать throws clause с конструктором.

  • Конструктор не должен формировать рекурсию.

Когда мы можем использовать private (частный) конструктор?

Если мы не хотим создавать объекты определенного класса извне, мы можем использовать закрытые или частные (private) конструкторы. Объявив конструкторы закрытыми, мы можем создавать объекты только внутри класса. Классы Singleton — хороший пример использования частных конструкторов.

Каким будет модификатор доступа конструктора по умолчанию, если мы не определим его явно?

Модификатор доступа конструктора по умолчанию всегда будет таким же, как модификатор класса. Если класс публичный, то конструктор тоже будет публичным. Если класс частный, то конструктор тоже будет частным. Аналогично будет и с другими модификаторами доступа.

Напишите вывод по приведенному ниже фрагменту кода и поясните


class InterviewBit{
InterviewBit(){
System.out.println(" Welcome to InterviewBit ");
}
}
class ScalerAcademy extends InterviewBit{
ScalerAcademy(){
System.out.println(" Welcome to Scaler Academy by InterviewBit");
}
}
class Main{
public static void main(String[] args) {
ScalerAcademy sc = new ScalerAcademy();
}
}
Приведенный выше код напечатает:
Welcome to InterviewBit. Welcome to Scaler Academy by InterviewBit.
Мы получим такой вывод, потому что если мы не укажем в конструкторе ключевое слово super() или this() в первой строке, то JVM сама автоматически поместит его во время выполнения. JVM делает это, потому что он наследуется от другого класса, и его функциональность также будет реализована в производном классе. Таким образом, присваивая экземплярам базового класса значения по умолчанию, JVM по умолчанию добавляет ключевое слово super().

Рассмотрите код и укажите, является ли он действительным (valid) или недействительным (invalid). Поясните причину


class InterviewBit{
InterviewBit(){
System.out.println(" Welcome to InterviewBit ");
}
}
class ScalerAcademy extends InterviewBit{
ScalerAcademy(){
this();
System.out.println(" Welcome to Scaler Academy by InterviewBit");
}
}
class Main{
public static void main(String[] args) {
ScalerAcademy sc = new ScalerAcademy();
}
}
Приведенный выше код недействителен, потому что он является одним и тем же конструктором внутри конструктора Scaler Academy. Это создает рекурсию в конструкторе, что недопустимо. Соответственно, мы получим ошибку времени компиляции, связанную с вызовом рекурсивного конструктора.

Можем ли мы использовать два конструктора в одном классе в Java?

Да, мы можем использовать любое количество конструкторов в одном классе с соблюдением двух условий:
  • Параметры конструкторов должны быть разными.
  • В конструкторе не должно быть рекурсии.
Пример. Рассмотрим два конструктора одного и того же класса InterviewBit:

InterviewBit(){
    this("Scaler"); // Calling parameterized constructor 
    System.out.println(" No Argument Constructor");
}
InterviewBit(String name){
    this(); // Calling no-arg constructor
    System.out.println(" Constructor with Parameters.");
}
Такой код недопустим, потому что он сформирует рекурсию. Конструктор без аргументов вызовет конструктор с параметрами, а конструктор с параметрами вызовет конструктор без аргументов.

Можем ли мы переопределить (override) конструктор в Java?

Нет, концепция перегрузки конструктора неприменима в Java.

Может ли конструктор быть окончательным (final) в Java?

Никакой конструктор не может быть окончательным (final). Это связано с тем, что ключевые слова final используются для остановки переопределения метода в производном классе. Но в конструкторе концепция переопределения неприменима, поэтому нет необходимости писать ключевое слово final. Если же мы напишем ключевое слово final в конструкторе, то получим ошибку времени компиляции под названием required return type (требуется возвращаемый тип), потому что компилятор рассматривает это как метод.

Может ли конструктор быть статическим (static) в Java?

Нет, конструктор Java не может быть статическим. Это связано с тем, что ключевые слова static используются, когда мы хотим, чтобы член принадлежал классу, а не объекту. Но конструкторы предназначены для инициализации объектов, поэтому компилятор будет рассматривать его как метод. Мы получим ошибку required return type.

Опишите разницу между super(), super и this(), this

super() и this() — это вызовы конструктора. Он используется только для вызова конструктора родительского класса или текущего класса. Учтите, что “super” и “this” — это ключевые слова, используемые для обозначения членов экземпляра собственного класса или базового класса. Рассмотрим приведенный ниже код:

class InterviewBit{
    String message = " Welcome to InterviewBit";
}
public class Scaler extends InterviewBit
{
    String message = " Welcome to Scaler Academy";
    public void printMethod(){
        //this will print the message variable of the current class.
        System.out.println(this.message);

        //this will print the message variable of Base class.
        System.out.println(super.message);
    }
	public static void main(String[] args) {
		Scaler sa = new Scaler();
		sa.printMethod();
	}
}
Во фрагменте этого кода this.message напечатает сообщение “Welcome to Scaler Academy”, а super.message напечатает “Welcome to InterviewBit”. Вот так эти два ключевых слова используются для ссылки на экземпляры членов базового и производного классов.

Что такое деструкторы? Существует ли деструктор в Java?

Destructors (Деструкторы) используются для освобождения памяти, полученной программой. Например, если память необходима программе во время ее выполнения, то деструктор освобождает эту память, чтобы ее могли использовать другие программы. В Java нет понятия деструктора, поскольку работа по освобождению памяти в Java обрабатывается сборщиком мусора.

Что такое цепь конструкторов (constructor chaining) в Java?

Когда один конструктор вызывается из другого конструктора, это можно назвать цепью конструкторов (constructor chaining). Вызов конструктора не обязательно нужно выполнять для одного и того же класса. Это можно сделать и для родительского класса. Для примера рассмотрите изображение ниже. Кофе-брейк #123. Java Constructor — вопросы и ответы на техническом собеседовании - 2Далее можно рассмотреть код для инициализации объекта со значениями значений (value values) этих переменных экземпляра:

class EmployeeAddess{
    int pinCode;
    String address;
    String mobNo;
    EmployeeAddress(int pinCode, String address, String mobNo){
        this.pinCode = pinCodel
        this.address = address;
        this.mobNo = mobNo;
    }
}
class Employees extends EmployeeAddress{
    int ID;
    String name;
    String designation;
    String department;
    Employee(int ID, String name, String designation,String department,
                    int pinCode, String address, String mobNo){
        
        //Calling Constructor for Base class to initialize the object.
        //This can be a constructor chaining.
        super(pinCode, address, mobNo);
        this.ID = ID;
        this.name = name;
        this.designation = designation;
        this.department = department;
    }
}
public class Main{
    Employee emp = new Employee(101, "XYX", "SDE", "Cloud", 123456, "no 150, xys, xys, INDIA", "999999999");
}
В приведенном выше коде мы создаем объект класса Employee с данными о сотруднике и его адресом. Класс адреса Employee наследуется классом Employee. Теперь для создания экземпляра значения объекта для адреса мы не присваиваем явное значение адреса сотрудника. Вместо этого мы используем для этого конструктор класса Employee Address. И с помощью super(arguments) мы формируем цепь конструкторов для инициализации значений. Вот что такое цепь конструкторов.

Определите вывод программы по коду и объясните свой ответ


class InterviewBit{
void InterviewBit(){
System.out.println(" Java Constructor interview questions by InterviewBit");
}
int InterviewBit(int val){
System.out.println(" Java Constructor. And Value = "+val);
}
}
public class Main{
InterviewBit ib1 = new InterviewBit();
InterviewBit ib2 = new InterviewBit();
}
Приведенный выше код ничего не напечатает, потому что InterviewBit() здесь не является конструктором. Поскольку используются ключевые слова Void и int, то он становится методом. Поэтому мы не вызываем метод. Мы не получим вывода, потому что для выполнения метода нам нужно явно вызвать его у объекта.

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


class Rectangle{
    int length;
    int breadth;
    Rectangle(int length, int breadth){
        this.length = length;
        this.breadth = breadth;
    }
    
    //Overloaded Constructor for copying the value of old Object to new object
    Rectangle(Rectangle obj){
        this.length = obj.length;
        this.breadth = obj.breadth;
    }
}
public class Main{
    Rectangle obj1 = new Rectangle(10, 5);
    
    //New Object of rectangle class will be created with the value from obj1. 
    Rectangle obj2 = new Rectangle(obj1);
}
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ