Вопросы на собеседовании по Java: Топ-50 примеров с ответами

Вопросы на собеседовании по Java: Топ-50 примеров с ответами
4 Сентября, 2023
912

Есть ли у вас все необходимое, чтобы успешно пройти собеседование по Java? Мы здесь, чтобы помочь вам закрепить ваши знания и концепции Java. Прежде чем мы начнем, давайте разберемся, что такое Java.

Что такое Java? 

Java - это язык программирования высокого уровня, разработанный Джеймсом Гослингом в 1982 году. Он основан на принципах объектно-ориентированного программирования и может использоваться для разработки крупномасштабных приложений. 

В этой статье мы рассмотрим все популярные вопросы для собеседований по Java Core, обработке строк, Java 8, многопоточности Java, ООП, обработке исключений, коллекциям и многие другие часто задаваемые вопросы.

Содержание [скрыть] [показать]

Вопросы для собеседования по Java для начинающих

1. Почему Java является платформонезависимым языком?

Язык Java был разработан таким образом, что он не зависит от какого-либо аппаратного или программного обеспечения, поскольку компилятор компилирует код, а затем преобразует его в независимый от платформы байт-код, который можно запускать на нескольких системах.

  • Единственное условие для запуска этого байт-кода — наличие на компьютере установленной среды выполнения (JRE).

2. Почему Java не является чисто объектно-ориентированным языком?

Java поддерживает примитивные типы данных — byte, boolean, char, short, int, float, long и double и, следовательно, не является чисто объектно-ориентированным языком.

3. Можно ли назвать Java полноценным объектно-ориентированным языком программирования?

Мы не ошибемся, если заявим, что Java — это полноценный объектно-ориентированный язык программирования. Потому что все в Java находится под классами. И мы можем получить к этому доступ, создав объекты.

Но также если мы скажем, что Java не является полностью объектно-ориентированным языком программирования, поскольку он поддерживает примитивные типы данных, такие как int, float, char, boolean, double и т. д.

Теперь вопрос: является ли Java полностью объектно-ориентированным языком программирования? Можно сказать, что — Java не является чистым объектно-ориентированным языком программирования, поскольку имеет прямой доступ к примитивным типам данных. И эти примитивные типы данных не принадлежат напрямую классам Integer.

4. Чем Java отличается от C++?

  • C++ — это только компилируемый язык, тогда как Java компилируется и интерпретируется.
  • Программы Java не зависят от машины, тогда как программа C++ может выполняться только на той машине, на которой она скомпилирована. 
  • C++ позволяет пользователям использовать указатели в программе. В то время как Java этого не позволяет. Java внутренне использует указатели. 
  • C++ поддерживает концепцию множественного наследования, тогда как Java ее не поддерживает. И именно из-за того, что мы избегаем сложности двусмысленности названий, которая вызывает проблему с бриллиантами.

5. Указатели используются в C/C++. Почему Java не использует указатели?

Указатели довольно сложны и небезопасны для использования начинающими программистами. Java фокусируется на простоте кода, и использование указателей может усложнить его. Использование указателя также может вызвать потенциальные ошибки. Более того, безопасность также подвергается риску при использовании указателей, поскольку пользователи могут напрямую обращаться к памяти с помощью указателей.

Таким образом, отсутствие указателей в Java обеспечивает определенный уровень абстракции. Более того, использование указателей может сделать процедуру сборки мусора довольно медленной и ошибочной. Java использует ссылки, поскольку ими нельзя манипулировать, в отличие от указателей.

6. Что вы понимаете под переменной экземпляра и локальной переменной?

Переменные экземпляра — это те переменные, которые доступны всем методам класса. Они объявляются вне методов и внутри класса. Эти переменные описывают свойства объекта и остаются привязанными к нему любой ценой.

Все объекты класса будут иметь свои копии переменных для использования. Если в эти переменные будет внесена какая-либо модификация, то это повлияет только на этот экземпляр, а все остальные экземпляры класса останутся незатронутыми.

Пример:

class Athlete {
public String athleteName;
public double athleteSpeed;
public int athleteAge;
}

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

Пример:

public void athlete() {
String athleteName;
double athleteSpeed;
int athleteAge;
}

7. Какие значения по умолчанию присваиваются переменным и экземплярам в Java?

  • В Java переменным не присвоены значения по умолчанию. Нам необходимо инициализировать значение перед его использованием. В противном случае будет выдана ошибка компиляции ( возможно, переменная не инициализирована ). 
  • Но, например, если мы создаем объект, значение по умолчанию будет инициализировано конструктором по умолчанию в зависимости от типа данных. 
  • Если это ссылка, то ей будет присвоено значение null. 
  • Если он числовой, ему будет присвоено значение 0.
  • Если это логическое значение, ему будет присвоено значение false. И т. д.

8. Что вы подразумеваете под инкапсуляцией данных?

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

9. Расскажите нам что-нибудь о JIT-компиляторе.

  • JIT означает «точно в срок» и используется для повышения производительности во время выполнения. Он выполняет задачу одновременной компиляции частей байт-кода, имеющих схожую функциональность, тем самым сокращая время компиляции для выполнения кода.
  • Компилятор — это не что иное, как переводчик исходного кода в машинно-исполняемый код. Но что особенного в JIT-компиляторе? Давайте посмотрим, как это работает:
    • Сначала происходит преобразование исходного кода Java (.java) в байт-код (.class) с помощью компилятора javac.
    • Затем файлы .class загружаются во время выполнения JVM и с помощью интерпретатора преобразуются в понятный машине код.
    • JIT-компилятор является частью JVM. Когда JIT-компилятор включен, JVM анализирует вызовы методов в файлах .class и компилирует их, чтобы получить более эффективный и собственный код. Это также гарантирует оптимизацию приоритетных вызовов методов.
    • После выполнения вышеуказанного шага JVM напрямую выполняет оптимизированный код вместо повторной интерпретации кода. Это увеличивает производительность и скорость выполнения.

10. Можете ли вы определить разницу между методом Equals() и оператором равенства (==) в Java?

Мы уже знаем об операторе равенства (==) . Мы использовали это для сравнения равенства значений. Но когда мы говорим о терминах объектно-ориентированного программирования, мы имеем дело со значениями в форме объектов. И этот объект может содержать несколько типов данных. Поэтому использование оператора (==) в этом случае не работает. Итак, нам нужно использовать метод Equals().

Основные функции [(==) и .equals()] предназначены для сравнения значений, но вторичные функции отличаются. 

Итак, чтобы лучше это понять, давайте рассмотрим это на примере –

String str1 = "InterviewBit";
String str2 = "InterviewBit";
 
System.out.println(str1 == str2);

Этот код выведет true. Мы знаем, что обе строки равны, поэтому будет выведено значение true. Но здесь (==) Операторы в этом случае не сравнивают каждый символ. Он сравнивает расположение памяти. А поскольку строка использует пул констант для хранения значений в памяти, строки str1 и str2 хранятся в одной и той же ячейке памяти. 

Теперь, если мы немного изменим программу с помощью -

String str1 = new String("InterviewBit");
String str2 = "InterviewBit";
 
System.out.println(str1 == str2);

Тогда в этом случае будет напечатано false. Потому что здесь больше не используются концепции постоянного пула. Здесь выделяется новая память. Итак, здесь адрес памяти другой, поэтому ( == ) оператор возвращает false. Но особенность в том, что значения в обеих строках одинаковы. Так как же сравнить значения? Здесь используется метод .equals().

Метод .equals() сравнивает значения и возвращает результат соответственно. Если мы изменим приведенный выше код с помощью - 

System.out.println(str1.equals(str2));

Затем он возвращает true.

equals()  ==
Это метод, определенный в классе Object.  Это бинарный оператор в Java.
Метод .equals() присутствует в классе Object, поэтому мы можем переопределить наш собственный метод .equals() в пользовательском классе для сравнения объектов. Его нельзя изменить. Они всегда сравнивают HashCode.
Этот метод используется для проверки равенства содержимого двух объектов согласно указанной бизнес-логике. Этот оператор используется для сравнения адресов (или ссылок), т.е. проверяет, указывают ли оба объекта на одну и ту же ячейку памяти.

Примечание:

  • В тех случаях, когда метод равенства не переопределен в классе, класс использует реализацию метода равенства по умолчанию, наиболее близкую к родительскому классу.
  • Класс объекта считается родительским классом для всех классов Java. Реализация метода равенства в классе Object использует оператор == для сравнения двух объектов. Эту реализацию по умолчанию можно переопределить в соответствии с бизнес-логикой.

11. Как в Java объявляется бесконечный цикл?

Бесконечные циклы — это циклы, которые выполняются бесконечно без каких-либо условий прерывания. Некоторые примеры сознательного объявления бесконечного цикла:

  • Использование цикла For:
for (;;)
{
   // Business logic
   // Any break logic
}
  • Использование цикла while:
while(true){
   // Business logic
   // Any break logic
}
  • Использование цикла do- while:
do{
   // Business logic
   // Any break logic
}while(true);

12. Кратко объясните концепцию перегрузки конструктора.

Перегрузка конструктора — это процесс создания в классе, состоящем из нескольких одноимённых конструкторов, с разницей в параметрах конструктора. В зависимости от количества параметров и соответствующих им типов компилятор различает разные типы конструкторов.

class Hospital {
int variable1, variable2;
double variable3;
public Hospital(int doctors, int nurses) {
 variable1 = doctors;
 variable2 = nurses;
}
public Hospital(int doctors) {
 variable1 = doctors;
}
public Hospital(double salaries) {
 variable3 = salaries
}
}

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

13. Определите конструктор копирования в Java.

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

class InterviewBit{
   String department;
   String service;
   InterviewBit(InterviewBit ib){
       this.departments = ib.departments;
       this.services = ib.services;
   }
}

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

14. Можно ли перегрузить основной метод?

Да, основной метод можно перегрузить. Мы можем создать столько перегруженных основных методов, сколько захотим. Однако у JVM есть предопределенный метод вызова, который JVM будет вызывать только основной метод с определением - 

public static void main(string[] args)

Рассмотрим приведенные ниже фрагменты кода: 

class Main {
    public static void main(String args[]) {
        System.out.println(" Main Method");
    }
    public static void main(int[] args){
        System.out.println("Overloaded Integer array Main Method");
    }
    public static void main(char[] args){
        System.out.println("Overloaded Character array Main Method");
    }
    public static void main(double[] args){
        System.out.println("Overloaded Double array Main Method");
    }
    public static void main(float args){
        System.out.println("Overloaded float Main Method");
    }
}

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

В Java перегрузка методов становится возможной за счет введения разных методов в один и тот же класс с одинаковым именем. Тем не менее, все функции различаются количеством или типом параметров. Это происходит внутри класса и повышает читаемость программы.

Единственное различие в типе возвращаемого значения метода не способствует перегрузке метода. Следующий пример даст вам четкое представление об этом.

class OverloadingHelp {
   public int findarea (int l, int b) {
           int var1;
           var1 = l * b;
           return var1;
   }
   public int findarea (int l, int b, int h) {
           int var2;
           var2 = l * b * h;
           return var2;
   }
}

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

Переопределение метода — это концепция, в которой два метода, имеющие одну и ту же сигнатуру метода, присутствуют в двух разных классах, в которых присутствуют отношения наследования. Конкретная реализация метода (уже присутствующая в базовом классе) возможна для производного класса с использованием переопределения метода.
Давайте посмотрим на этот пример:

class HumanBeing {
       public int walk (int distance, int time) {
               int speed = distance / time;
               return speed;
       }
}
class Athlete extends HumanBeing {
       public int walk(int distance, int time) {
               int speed = distance / time;
               speed = speed * 2;
               return speed;
       }
}

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

16. В Java-программе могут сосуществовать один блок try и несколько блоков catch. Объяснять.

Да, может существовать несколько блоков catch, но конкретные подходы должны предшествовать общему подходу, поскольку выполняется только первый блок catch, удовлетворяющий условию catch. Данный код иллюстрирует то же самое:

public class MultipleCatch {
public static void main(String args[]) {
 try {
  int n = 1000, x = 0;
  int arr[] = new int[n];
  for (int i = 0; i <= n; i++) {
   arr[i] = i / x;
  }
 }
 catch (ArrayIndexOutOfBoundsException exception) {
  System.out.println("1st block = ArrayIndexOutOfBoundsException");
 }
 catch (ArithmeticException exception) {
  System.out.println("2nd block = ArithmeticException");
 }
 catch (Exception exception) {
  System.out.println("3rd block = Exception");
 }
}
}

Здесь второй блок catch будет выполнен из-за деления на 0 (i/x). В случае, если x было больше 0, будет выполнен первый блок catch, потому что цикл for выполняется до тех пор, пока i = n, а индекс массива не будет равен n-1.

17. Объясните использование ключевого слова Final в переменной, методе и классе.

В Java ключевое слово Final используется для определения чего-либо как константы/final и представляет собой модификатор запрета доступа.

  • конечная переменная:
    • Когда переменная объявлена в Java как окончательная, значение не может быть изменено после того, как оно было присвоено.
    • Если этой переменной не присвоено какое-либо значение, то его может присвоить только конструктор класса.
  • последний метод:
    • Метод, объявленный как окончательный, не может быть переопределен его дочерними классами.
    • Конструктор не может быть помечен как окончательный, поскольку при наследовании класса конструкторы не наследуются. Следовательно, отмечать его окончательным не имеет смысла. Java выдает ошибку компиляции, говоря:modifier final not allowed here
  • последний урок:
    • Никакие классы не могут быть унаследованы от класса, объявленного как окончательный. Но этот последний класс может расширять другие классы для его использования.

18. Имеют ли ключевые слова Final, Final и Finalize одну и ту же функцию?

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

Final: если для классов, переменных или методов требуются какие-либо ограничения, вам пригодится ключевое слово Final. Наследование класса Final и переопределение метода Final ограничивается использованием ключевого слова Final. Значение переменной становится фиксированным после добавления ключевого слова Final. Пример:

final int a=100;
a = 0;  // error

Второй оператор выдаст ошибку.

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

try {
int variable = 5;
}
catch (Exception exception) {
System.out.println("Exception occurred");
}
finally {
System.out.println("Execution of finally block");
}

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

public static void main(String[] args) {
String example = new String("InterviewBit");
example = null;
System.gc(); // Garbage collector called
}
public void finalize() {
// Finalize called
} 

19. Возможно ли, что блок «Finally» не будет выполнен? Если да, то перечислите случай.

 Да. Возможно, что блок «finally» не будет выполнен. Случаи такие-

  • Предположим, мы используем System.exit() в приведенном выше выражении.
  • Если есть фатальные ошибки, такие как переполнение стека, ошибка доступа к памяти и т. д.

20. Определите выходные данные Java-программы и укажите причину.

1. public class InterviewBit
2. {
3.	 public static void main(String[] args) {
4.	 	 final int i;
5.		 i = 20;
6.		 int j = i+20;
7.		 i = j+30;
8.	     System.out.println(i + " " + j);
9.	 }
10. }

Приведенный выше код сгенерирует ошибку времени компиляции в строке 7, говорящую - [ошибка: переменная i, возможно, уже была инициализирована] . Это потому, что переменная «i» является последней переменной. А конечные переменные можно инициализировать только один раз, и это уже было сделано в строке № 5.

21. Когда можно использовать ключевое слово super?

  • Ключевое слово super используется для доступа к скрытым полям и переопределенным методам или атрибутам родительского класса.
  • Ниже приведены случаи, когда можно использовать это ключевое слово:
    • Доступ к членам данных родительского класса, когда имена членов класса и его дочерних подклассов совпадают.
    • Чтобы вызвать параметризованный конструктор по умолчанию родительского класса внутри дочернего класса.
    • Доступ к методам родительского класса, когда дочерние классы переопределили их.
  • В следующем примере показаны все три случая использования ключевого слова super.
class Parent{
       protected int num = 1;
       
       Parent(){
           System.out.println("Parent class default constructor.");
       }
       
       Parent(String x){
           System.out.println("Parent class parameterised constructor.");
       }
       
       public void foo(){
           System.out.println("Parent class foo!");
       }
   }
class Child extends Parent{
       private int num = 2;
       
       Child(){
           //super constructor call should always be in the first line
           // super();              // Either call default super() to call default parent constructor OR
           super("Call Parent");    // call parameterised super to call parameterised parent constructor.
           System.out.println("Child class default Constructor");
       }
       
       void printNum(){
           System.out.println(num);
           System.out.println(super.num); //prints the value of num of parent class
       }
       
       @Override
       public void foo(){
           System.out.println("Child class foo!");
           super.foo();    //Calls foo method of Parent class inside the Overriden foo method of Child class.
       }
   }

public class DemoClass {
    public static void main(String args[]) {
     Child demoObject=new Child();
     demoObject.foo();
     /*
      This would print - 
      Parent class parameterised constructor.
      Child class default Constructor
      Child class foo!
      Parent class foo!
     */
    }
}

22. Можно ли перегрузить статические методы?

Да! В классе может быть два или более статических метода с одинаковым именем, но с разными входными параметрами.

23. Почему основной метод в Java статический?

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

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

24. Можно ли переопределить статические методы?

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

25. Разница между статическими методами, статическими переменными и статическими классами в Java.

  • Статические методы и статические переменные — это методы и переменные, которые принадлежат классу Java-программы, а не объекту класса. Это получает память, в которой загружен класс. И их можно напрямую вызывать с помощью имен классов.
    • Например: мы использовали математические функции в Java-программе, такие как — max(), min(), sqrt(), pow() и т. д. И если мы это заметим, то обнаружим, что вызываем его напрямую из класса. имя. Например — Math.max(), Math.min() и т. д. Итак, это статический метод. Аналогичным образом мы использовали статические переменные типа (длина) для массива, чтобы получить длину. Итак, это статический метод.
  • Статические классы . Класс в Java-программе не может быть статическим, за исключением случаев, когда он является внутренним классом. Если это внутренний статический класс, то он работает точно так же, как и другие статические члены класса.

26. Какова основная цель вывоза мусора?

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

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

27. Что такое загрузчик классов?

  • Java Classloader — это программа, принадлежащая JRE (среде выполнения Java). Задача ClassLoader — загружать необходимые классы и интерфейсы в JVM, когда это необходимо. 
  • Пример. Чтобы получить ввод с консоли, нам нужен класс сканера. А класс Scanner загружается ClassLoader.

28. Какая часть памяти — стек или куча — очищается при сборке мусора?

Куча.

Вопросы для собеседования по Java для опытных разработчиков

29. Помимо аспекта безопасности, каковы причины создания неизменяемых строк в Java?

Строка становится неизменяемой по следующим причинам:

  • Пул строк. Разработчики Java знали о том, что тип данных String будет в основном использоваться программистами и разработчиками. Таким образом, они хотели оптимизации с самого начала. Они придумали идею использования пула строк (области хранения в куче Java) для хранения строковых литералов. Они намеревались уменьшить временный объект String с помощью совместного использования. Неизменяемый класс необходим для облегчения совместного использования. Совместное использование изменяемых структур двумя неизвестными сторонами невозможно. Таким образом, неизменяемая строка Java помогает реализовать концепцию пула строк.
  • Многопоточность. Безопасность потоков относительно объектов String является важным аспектом Java. Никакая внешняя синхронизация не требуется, если объекты String являются неизменяемыми. Таким образом, можно написать более чистый код для совместного использования объектов String в разных потоках. Этот метод облегчает сложный процесс параллелизма.
  • Коллекции. В случае Hashtables и HashMaps ключи представляют собой строковые объекты. Если объекты String не являются неизменяемыми, они могут быть изменены в течение периода, пока они находятся в HashMaps. Следовательно, получение нужных данных невозможно. Такие меняющиеся состояния таят в себе много рисков. Поэтому вполне безопасно сделать строку неизменяемой.

30. Что такое одноэлементный класс в Java? И как реализовать одноэлементный класс?

Классы-синглтоны — это классы, объекты которых создаются только один раз. И только с помощью этого объекта можно получить доступ к членам класса. 

Поймите это на примере:

Рассмотрим кувшин с водой в офисе: если каждому сотруднику нужна эта вода, они не будут создавать новый кувшин для питьевой воды. В качестве стакана они будут использовать существующий со своим референсом. Итак, программно это должно быть реализовано как -

class WaterJug{
   private int waterQuantity = 500;
   private WaterJug(){}
   private WaterJug object = null;
   
   // Method to provide the service of Giving Water.
   public int getWater(int quantity){
       waterQuantity -= quantity;
       return quantity;
   }
   // Method to return the object to the user.
   public static Waterjug getInstance(){
       // Will Create a new object if the object is not already created and return the object.
       if(object == null){
           object = new WaterJug();
       }
       return object;
   }
}

В приведенном выше классе конструктор является закрытым, поэтому мы не можем создать объект класса. Но мы можем получить объект, вызвав метод getInstance() . А getInstance является статическим, поэтому его можно вызывать без создания объекта. И он возвращает объект. Теперь, имея этот объект, мы можем вызвать getWater() , чтобы получить воду.

Waterjug glass1 = WaterJug.getInstance();
glass1.getWater(1);

Мы можем получить единственный объект, используя метод getInstance(). И он статический, поэтому это поточно-безопасный одноэлементный класс. Хотя существует множество способов создать потокобезопасный одноэлементный класс. Таким образом, потокобезопасные классы также могут быть:

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

31. Что из перечисленного ниже вызывает ошибку времени компиляции? Укажите причину.

  1. int[] n1 = new int[0];
  2. boolean[] n2 = new boolean[-200];
  3. double[] n3 = new double[2241423798];

В строке 3 мы получаем ошибку времени компиляции. Ошибка в строке 3 — слишком большое целое число . Это потому, что для массива требуется размер как целое число. А Integer занимает в памяти 4 байта. А число ( 2241423798 ) выходит за рамки целого числа. Максимальный размер массива, который мы можем объявить, — ( 2147483647 ).

Поскольку для массива требуется целочисленный размер, ни одна из строк (1, 2 и 4) не выдаст ошибку во время компиляции. Программа скомпилируется нормально. Но в строке 2 мы получаем исключение времени выполнения. Исключением является — NegativeArraySizeException . 

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

  1. char[] ch = new char[20];

32. Как бы вы различали String, StringBuffer и StringBuilder?

  • Область хранения: в строке областью хранения служит пул строк. Для StringBuilder и StringBuffer областью хранения является куча.
  • Изменяемость: строка является неизменяемой, тогда как StringBuilder и StringBuffer являются изменяемыми.
  • Эффективность: работать со строкой довольно медленно. Однако StringBuilder быстрее всех выполняет операции. Скорость StringBuffer больше, чем у String, и меньше, чем у StringBuilder. (Например, добавление символа происходит быстрее в StringBuilder и очень медленно в String, поскольку для новой строки с добавленным символом требуется новая память.)
  • Потокобезопасность: в случае многопоточной среды используются StringBuilder и StringBuffer, тогда как String не используется. Однако StringBuilder подходит для среды с одним потоком, а StringBuffer — для нескольких потоков.
    Синтаксис:
// String
String first = "InterviewBit";
String second = new String("InterviewBit");
// StringBuffer
StringBuffer third = new StringBuffer("InterviewBit");
// StringBuilder
StringBuilder fourth = new StringBuilder("InterviewBit");

33. Использование соответствующих свойств подчеркивает различия между интерфейсами и абстрактными классами.

  • Доступность методов. В интерфейсах доступны только абстрактные методы, тогда как неабстрактные методы могут присутствовать вместе с абстрактными методами в абстрактных классах.
  • Типы переменных . Статические и конечные переменные могут быть объявлены только в случае интерфейсов, тогда как абстрактные классы также могут иметь нестатические и нефинальные переменные.
  • Наследование. Множественное наследование облегчается интерфейсами, тогда как абстрактные классы не поддерживают множественное наследование.
  • Доступность членов данных. По умолчанию члены данных класса интерфейсов имеют открытый тип. И наоборот, члены абстрактного класса также могут быть защищенными или закрытыми.
  • Реализация: с помощью абстрактного класса легко возможна реализация интерфейса. Однако обратное неверно;

Пример абстрактного класса:

public abstract class Athlete {
public abstract void walk();
}

Пример интерфейса:

public interface Walkable {
void walk();
}

34. Что такое компаратор в Java?

Рассмотрим пример, где у нас есть ArrayList сотрудников типа (EId, Ename, Salary) и т. д. Теперь, если мы хотим отсортировать этот список сотрудников по именам сотрудников. Тогда невозможно выполнить сортировку с помощью метода Collections.sort(). Нам нужно предоставить что-то функции sort() в зависимости от того, какие значения нам нужно выполнить для сортировки. Тогда в этом случае используется компаратор.

Компаратор — это интерфейс Java, содержащий метод сравнения. А перегрузив метод сравнения, мы можем определить, на каком основании нам нужно сравнивать значения. 

35. В Java возможно переопределение как статических, так и частных методов. Так ли это.

Утверждение в контексте совершенно неверно. Статические методы не имеют никакого отношения к объектам и относятся к уровню класса. В случае дочернего класса статический метод с сигнатурой метода, точно такой же, как у родительского класса, может существовать, даже не вызывая ошибок компиляции.

Упомянутое здесь явление широко известно как сокрытие метода, и его переопределение, безусловно, невозможно. Переопределение частного метода невообразимо, поскольку видимость частного метода ограничена только родительским классом. В результате можно облегчить только сокрытие, а не переопределение.

36. Чем HashSet отличается от TreeSet?

Хотя и HashSet, и TreeSet не синхронизированы и гарантируют отсутствие дубликатов, существуют определенные свойства, которые отличают HashSet от TreeSet.

  • Реализация: для HashSet хеш-таблица используется для хранения элементов в неупорядоченном порядке. Однако TreeSet использует хэш-таблицу для хранения элементов в отсортированном виде.
  • Сложность/производительность: при добавлении, извлечении и удалении элементов амортизированная по времени сложность равна O(1) для HashSet. Временная сложность выполнения тех же операций у TreeSet немного выше и равна O(log n). В целом производительность HashSet выше, чем у TreeSet.
  • Методы: hashCode() и Equals() — это методы, используемые HashSet для сравнения объектов. И наоборот, методы CompareTo() и Compare() используются TreeSet для облегчения сравнения объектов.
  • Тип объектов: Гетерогенные и нулевые объекты можно хранить с помощью HashSet. В случае TreeSet исключение во время выполнения возникает при вставке гетерогенных объектов или нулевых объектов.

37. Почему массив символов предпочтительнее строки для хранения конфиденциальной информации?

В Java строка по сути неизменяема, то есть ее нельзя изменить. После своего объявления он продолжает оставаться в пуле строк до тех пор, пока не будет удален в виде мусора. Другими словами, строка находится в куче памяти в течение нерегулируемого и неопределенного интервала времени после выполнения обработки строкового значения.

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

38. Что мы получаем в файле JDK?

  • JDK. Для создания Java-программ нам нужны некоторые инструменты, предоставляемые JDK (Java Development Kit). JDK — это пакет, содержащий различные инструменты, компилятор, среду выполнения Java и т. д.
  • JRE. Для выполнения Java-программы нам нужна среда. (Среда выполнения Java) JRE содержит библиотеку классов Java + JVM. Что такое JAVA-классы?  Он содержит некоторые предопределенные методы, которые помогают программам Java использовать эту функцию, создавать и выполнять. Например — в java есть системный класс, содержащий метод print-stream, и с помощью него мы можем что-то напечатать на консоли.
  • JVM — (виртуальная машина Java). JVM — это часть JRE, которая в конце выполняет программу Java. На самом деле это часть JRE, но это программное обеспечение, которое преобразует байт-код в машинно-исполняемый код для выполнения на оборудовании.

39. Каковы различия между HashMap и HashTable в Java?

HashMap HashTable
HashMap не синхронизируется, что делает его более удобным для непоточных приложений. HashTable синхронизируется и, следовательно, подходит для многопоточных приложений.
Допускает только один нулевой ключ, но любое количество нулевых значений. Не допускает нулевых значений ни в ключах, ни в значениях.
Поддерживает порядок вставки, используя свой подкласс LinkedHashMap. Порядок вставки в HashTable не гарантируется.

40. Какова важность отражения в Java?

  • Этот термин reflectionиспользуется для описания возможности проверки кода на другом коде самого себя или его системы и его модификации во время выполнения.
  • Рассмотрим пример, где у нас есть объект неизвестного типа и метод fooBar(), который нам нужно вызвать для этого объекта. Система статической типизации Java не позволяет вызывать этот метод, если тип объекта не известен заранее. Этого можно добиться с помощью отражения, которое позволяет коду сканировать объект и определять, имеет ли он какой-либо метод под названием «fooBar()», и только затем вызывать этот метод при необходимости.
Method methodOfFoo = fooObject.getClass().getMethod("fooBar", null);
methodOfFoo.invoke(fooObject, null);
  • Использование отражения имеет свои минусы:
    • Скорость — вызовы методов из-за отражения примерно в три раза медленнее, чем прямые вызовы методов.
    • Безопасность типов. Когда метод вызывается через ссылку по ошибке с использованием отражения, вызов завершается неудачно во время выполнения, поскольку он не обнаруживается во время компиляции/загрузки.
    • Прослеживаемость. Всякий раз, когда рефлексивный метод дает сбой, очень сложно найти основную причину этого сбоя из-за огромной трассировки стека. Чтобы определить основную причину, необходимо глубоко погрузиться в журналы методов вызова() и прокси().
  • Следовательно, желательно следовать решениям, не требующим размышлений, и использовать этот метод в крайнем случае.

45. Каковы различные способы использования потоков?

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

  • Расширение класса Thread
class InterviewBitThreadExample extends Thread{  
   public void run(){  
       System.out.println("Thread runs...");  
   }  
   public static void main(String args[]){  
       InterviewBitThreadExample ib = new InterviewBitThreadExample();  
       ib.start();  
   }  
}
  • Реализация интерфейса Runnable
class InterviewBitThreadExample implements Runnable{  
   public void run(){  
       System.out.println("Thread runs...");  
   }  
   public static void main(String args[]){  
       Thread ib = new Thread(new InterviewBitThreadExample()); 
       ib.start();  
   }  
}
  • Реализация потока с использованием метода интерфейса Runnable более предпочтительна и выгодна, поскольку Java не поддерживает множественное наследование классов.
  • start()используется для создания отдельного стека вызовов для выполнения потока. После создания стека вызовов JVM вызывает run()метод для выполнения потока в этом стеке вызовов.

41. Каковы различные типы приоритетов потоков в Java? И каков приоритет потока по умолчанию, назначенный JVM?

Всего в Java доступно 3 различных типа приоритета. 

MIN_PRIORITY: ему присвоено целочисленное значение 1.
MAX_PRIORITY: ему присвоено целочисленное значение 10.
NORM_PRIORITY: ему присвоено целочисленное значение 5.

В Java поток с MAX_PRIORITY получает первый шанс на выполнение. Но приоритетом по умолчанию для любого потока является NORM_PRIORITY, назначенный JVM. 

42. В чем разница между программой и процессом?

  • Программу можно определить как строку кода, написанную для выполнения определенной задачи. Тогда как процесс можно определить как программы, находящиеся в стадии выполнения. 
  • Программа не выполняется непосредственно процессором. Сначала программе выделяются ресурсы, и когда она готова к выполнению, это процесс.

43. В чем разница между ключевыми словами «throw» и «throws» в Java?

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

Пример - 

class Main {
   public static int testExceptionDivide(int a, int b) throws ArithmeticException{
       if(a == 0 || b == 0)
           throw new ArithmeticException();
       return a/b;
   }
   public static void main(String args[]) {
       try{
           testExceptionDivide(10, 0);
       }
       catch(ArithmeticException e){
           //Handle the exception
       }
   }
}

Здесь, в приведенном выше фрагменте, метод testExceptionDivide генерирует исключение. Поэтому, если основной метод вызывает его, значит, он обработал исключение. В противном случае основной метод также может вызвать исключение для JVM.

А метод testExceptionDivide «выбрасывает» исключение в зависимости от условия.

43. Каковы различия между конструктором и методом класса в Java?

Конструктор Метод
Конструктор используется для инициализации состояния объекта. Метод используется для раскрытия поведения объекта.
Конструктор не имеет возвращаемого типа. Метод должен иметь возвращаемый тип. Даже если он ничего не возвращает, тип возвращаемого значения — void.
Конструктор вызывается неявно. Метод должен быть вызван для объекта явно.
Если конструктор не определен, то компилятор Java предоставляет конструктор по умолчанию. Если метод не определен, то компилятор его не предоставляет.
Имя конструктора должно совпадать с именем класса. Имя метода может иметь любое имя или имя класса.
Конструктор не может быть помечен как окончательный, поскольку при наследовании класса конструкторы не наследуются. Следовательно, отмечать его окончательным не имеет смысла. Java выдает ошибку компиляции, говоря:modifier final not allowed here Метод может быть определен как окончательный, но его нельзя переопределить в его подклассах.
Конечные экземпляры переменных возможны внутри конструктора, и это применимо ко всему классу и его объектам. Финальная переменная, если она инициализирована внутри метода, гарантирует, что переменная не может быть изменена только в пределах области действия этого метода.

44. Каково отношение IS-A в Java ООП?

Отношения IS-A — это еще одно название наследования. Когда мы наследуем базовый класс от производного класса, он формирует отношения между классами. Таким образом, эти отношения называются отношениями «Я-А».

Пример . Рассмотрим телевизор (типичный ЭЛТ-телевизор). Теперь еще один Smart TV, унаследованный от класса телевизоров. Так что можно сказать, что Smart iv — это еще и телевизор. Потому что с ЭЛТ-телевизором можно работать и на Smart TV.

45. Что из String или String Buffer следует предпочесть, если в данных необходимо выполнить множество обновлений?

StringBuffer является изменчивым и динамическим по своей природе, тогда как String является неизменяемым. Каждое обновление/модификация String создает новую String, тем самым перегружая пул строк ненужными объектами. Следовательно, в случае большого количества обновлений всегда предпочтительнее использовать StringBuffer, поскольку это уменьшит накладные расходы на создание нескольких объектов String в пуле строк.

46. Как не разрешить сериализацию атрибутов класса в Java?

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

public class InterviewBitExample { 

   private transient String someInfo; 
   private String name;
   private int id;
   // :
   // Getters setters
   // :
} 

В приведенном выше примере все поля, кроме, someInfoмогут быть сериализованы.

47. Что произойдет, если модификатор static не включен в сигнатуру основного метода в Java?

Не было бы никакой ошибки компиляции. Но затем программа запускается, поскольку JVM не может сопоставить сигнатуру основного метода, код выдает ошибку «NoSuchMethodError» во время выполнения.

48. Можем ли мы сделать поток main() потоком демона?

В многопоточности Java потоки main() всегда являются потоками, не являющимися демонами. И мы никак не можем изменить природу потока, не являющегося демоном, на поток-демона.

49. Что произойдет, если в одном классе Java имеется несколько основных методов?

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

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

Исключением являются ошибки времени выполнения. Предположим, мы создаем приложение для Android с использованием Java. И все это работает нормально, но есть исключительный случай, когда приложение пытается получить файл из хранилища, а файл не существует (это исключительный случай в Java). И если этот случай не будет обработан должным образом, приложение выйдет из строя. Это будет неприятный опыт для пользователей. Это тип ошибки, который не может контролироваться программистом. Но программисты могут предпринять некоторые шаги, чтобы избежать этого и не допустить сбоя приложения. На этом этапе можно предпринять соответствующие действия.

51. Обязательно ли следовать блоку catch после блока try?

Нет, не обязательно, чтобы блок catch присутствовал после блока try. - За блоком try должен следовать блок catch или блокfinally. Если вероятность исключений больше, их следует объявить с помощью предложения throws метода.