여러분, 안녕하세요! 오늘은 Java 개발자 인터뷰 질문에 대한 검토를 계속하겠습니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 4 - 1

29. 생성자에서 return을 사용할 수 있나요?

예, 하지만 return 키워드 오른쪽에 값이 없는 경우에만 가능합니다 . 반환을 사용할 수 있습니다 . 추가 코드 실행을 긴급하게 종료(중단)하고 객체 초기화를 완료하기 위한 생성자의 도우미 문으로 사용됩니다. 예를 들어 Cat 클래스가 있고 Cat이 노숙자 인 경우 ( isHomeless = true ) 초기화를 종료하고 다른 필드를 채우지 않기를 원합니다(결국 고양이가 노숙자이므로 해당 필드는 우리에게 알려지지 않습니다). :
public Cat(int age, String name, boolean isHomeless) {
   if (isHomeless){
       this.isHomeless = isHomeless;
       return;
   }
   this.isHomeless = isHomeless;
   this.age = age;
   this.name = name;
}
그러나 구체적인 값에 대해 이야기하는 경우 return 키워드는 다음과 같은 이유로 특정 값을 반환할 수 없습니다.
  • 생성자를 선언하면 반환 유형과 같은 것이 없습니다.
  • 일반적으로 생성자는 인스턴스화 중에 암시적으로 호출됩니다.
  • 생성자는 메소드가 아닙니다. 이는 인스턴스 변수를 초기화하는 것이 유일한 목적인 별도의 메커니즘입니다. 즉, 객체를 생성하기 위해 new 연산자 를 사용하고 있습니다 .
Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 4 - 2

30. 생성자에서 예외가 발생할 수 있나요?

생성자는 메서드와 동일한 방식으로 예외를 처리합니다. 메소드를 사용하면 메소드 헤더에 <ExceptionType> 발생을 작성하여 예외를 발생시킬 수 있습니다 . 그리고 생성자를 사용하면 우리도 같은 일을 할 수 있습니다. 하위 클래스의 생성자를 상속하고 정의할 때 예외 유형을 확장할 수 있습니다(예: IOException -> Exception(그러나 그 반대는 아님)). 예외를 발생시키는 생성자의 예로 Cat 클래스 의 생성자를 사용해 보겠습니다 . 객체를 생성할 때 콘솔에서 이름과 나이를 입력한다고 가정해 보겠습니다.
public Cat() throws IOException {
   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   this.name = reader.readLine();
   this.age = Integer.parseInt(reader.readLine());
}
reader.readLine()은 IOException을 발생 시키므로 이를 발생 가능한 예외로 헤더에 기록합니다.

31. 클래스 헤더의 요소는 무엇입니까? 예시 작성

클래스 헤더를 구성하는 요소를 설명하기 위해 작은 스키마를 살펴보겠습니다.
  • 필수 요소는 괄호 <> 안에 표시됩니다.
  • 선택적 요소는 {}에 있습니다.
{access modifier}{static}{final}{abstract}<class name>{상위 클래스의 상속}{인터페이스 구현} 그래서 우리가 가진 것은 다음과 같습니다: {access modifier}공개기본 액세스 한정자만 클래스에 사용할 수 있습니다. 수업. {static}static 한정자는 이 클래스가 정적임을 나타냅니다. 이는 내부 클래스(다른 클래스 내부의 클래스)에만 적용됩니다. {final} — 물론 이것은 클래스를 상속할 수 없게 만드는 최종 수정자입니다(기본적인 예는 String 입니다 ). {abstract} — 클래스에 구현되지 않은 메서드가 있을 수 있음을 나타내는 추상 수정자입니다 . 이 수정자는 최종 수정자와 충돌합니다. 추상 수정자는 클래스가 상속되고 해당 추상 요소가 구현된다는 의미이므로 클래스 헤더에는 그 중 하나만 가질 수 있습니다 . 그러나 final은 이것이 클래스의 최종 버전이며 상속될 수 없음을 나타냅니다. 실제로 두 수식어를 동시에 사용하는 것은 터무니없는 일입니다. 컴파일러는 우리가 이것을 하도록 허용하지 않습니다. <class> 는 클래스 선언을 나타내는 필수 키워드입니다. <클래스 이름>은 특정 Java 클래스의 식별자가 되는 간단한 클래스 이름입니다. 정규화된 클래스 이름은 정규화된 패키지 이름과 '.'로 구성됩니다. 간단한 클래스 이름을 추가합니다. {상위 클래스의 상속}은 확장 키워드를 사용하는 상위 클래스(있는 경우)를 나타냅니다 . 예를 들어 ...는 ParentClass를 확장합니다 . {인터페이스 구현} — Implements 키워드 를 사용하여 이 클래스가 구현하는(있는 경우) 인터페이스 목록입니다 . 예를 들면 다음과 같습니다. ... Implements FirstInterface, SecondInterface ... 예를 들어 Cat을 상속 하고 WildAnimal 인터페이스를 구현하는 Lion 클래스 의 클래스 제목을 생각해 보세요 .
public final class Lion extends Cat implements WildAnimal
Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 4 - 3

32. 메소드 헤더의 요소는 무엇입니까? 예시 작성

메소드 헤더를 구성하는 요소를 고려할 때 작은 스키마를 다시 고려해 보겠습니다.
  • 필수 요소는 괄호 <> 안에 표시됩니다.
  • 선택적 요소는 {}에 있습니다.
{access modifier}{static}{abstract}{final}{synchronized} {native} <반환 값><메서드 이름> <(>{메서드 매개변수}<}>{예외 발생} {access modifier} — 모든 액세스 한정자 는 메소드에 사용 가능 — public , protected , default , private {static} — 메소드가 정적이므로 객체가 아닌 클래스와 연관되어 있음을 나타내는 static 한정자 {abstract} — 다음을 나타내는 추상 한정자 메소드에 구현(본문)이 없습니다. 올바르게 작동하려면 메소드를 선언하는 클래스에도 추상 수정 자가 있어야 합니다 . 클래스 헤더에서와 같이 이 수정자는 최종 수정자와 충돌하며 정적 수정자 와도 충돌합니다. 추상 메서드는 하위 항목의 메서드 재정의를 의미하며 정적 메서드는 재정의할 수 없습니다. {finale} — 이 메서드를 재정의할 수 없음을 나타내는 최종 수정자 {synchronized} — 메서드가 다음으로부터 보호됨을 의미하는 동기화된 수정자 다른 스레드에서 동시에 액세스할 수 있습니다. 메서드가 정적이 아닌 경우 개체의 this 뮤텍스에 대해 닫힙니다. 메서드가 정적이면 현재 클래스의 뮤텍스에 대해 닫힙니다. {native}기본 수정자는 메서드가 다른 프로그래밍 언어로 작성되었음을 나타냅니다. <return type> — 메서드가 반환해야 하는 값의 유형입니다. 메서드가 아무것도 반환하지 않으면 void 입니다 . <메소드 이름> — 메소드 이름의 이름, 즉 시스템의 식별자입니다. {메소드 매개변수} - 메소드가 허용하는 매개변수: 해당 기능을 구현하는 데 필요합니다. {thrown 예외}<ExceptionType> 발생 — 이 메서드가 발생시킬 수 있는 확인된 예외 목록입니다. 메소드 헤더의 예로 다음을 제공하겠습니다.
public static void main(String[] args) throws IOException

33. 기본 클래스에 기본 생성자가 정의되어 있지 않은 경우(그러나 다른 생성자가 정의된 경우) 하위 클래스에 기본 생성자를 생성합니다.

질문을 완전히 이해했는지는 모르겠지만 아마도 상위 클래스에 다음과 같은 생성자가 있다는 의미일 수 있습니다.
public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
이 경우 부모 클래스에서 부모를 초기화할 생성자를 정의해야 합니다(즉, 부모 생성자를 호출).
public class Lion extends Cat {

   public Lion(int age, String name) {
       super(age, name);
   }
}
Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 4 - 4

34. this 키워드는 언제 사용되나요?

Java에서 이는 두 가지 다른 의미를 갖습니다. 1. 현재 객체에 대한 참조입니다(예: this.age = 9 ). 즉, this는 이것이 사용되는 개체와 this 가 포함된 코드가 참조하는 개체를 나타냅니다. 주요 목적은 코드 가독성을 높이고 모호성을 방지하는 것입니다. 예를 들어 인스턴스 필드와 메서드 인수의 이름이 같은 경우:
public void setName(String name) {
   this.name = name;
}
즉, this.name 은 객체의 필드이고 name 은 메서드 매개변수입니다. this 참조 정적 메서드에서 사용할 수 없습니다. 2. 생성자에서 this (value) 와 같이 메서드처럼 호출할 수 있습니다 . 이 경우에는 동일한 클래스의 다른 생성자를 호출하게 됩니다. 기본적으로 객체를 생성하는 과정에서 두 개의 생성자를 호출할 수 있습니다.
public Cat(int age, String name) {
   this(name);
   this.age = age;
}

public Cat(String name) {
   this.name = name;
}
Cat 객체를 생성하기 위해 첫 번째 생성자를 호출하면 두 인스턴스 필드가 모두 성공적으로 초기화됩니다. 여기에는 몇 가지 뉘앙스가 있습니다.
  1. this()는 생성자에서만 작동합니다.
  2. 다른 생성자에 대한 참조는 생성자 블록(본문)의 첫 번째 줄에 있어야 합니다. 이는 생성자가 해당 클래스의 생성자를 두 개 이상 호출할 수 없음을 의미합니다.
Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 4 - 5

35. 이니셜라이저란 무엇입니까?

내가 아는 한, 이 질문은 일반 및 정적 초기화 블록에 관한 것입니다. 먼저 초기화가 무엇인지 기억해 봅시다. 초기화는 필드의 생성, 활성화, 준비 및 정의입니다. 사용할 수 있도록 프로그램이나 구성 요소를 준비합니다. 객체를 생성할 때 클래스 변수가 선언되는 즉시 초기화될 수 있다는 것을 기억하실 것입니다.
class Cat {
   private int age = 9;
   private String name = "Tom";
또는 생성자를 통해 사실 뒤에 설정합니다.
class Cat {
   private int age;
   private String name;

   public Cat(int age, String name) {
       this.age = age;
       this.name = name;
   }
하지만 또 다른 방법이 있습니다. 초기화 블록을 사용하여 인스턴스 변수를 설정할 수 있습니다. 초기화 블록은 이름 없이(예: 이름 없는 메서드나 생성자) 클래스 내에서 중괄호 {} 형식을 취합니다.
class Cat {
   private int age;
   private String name;

   {
       age = 10;
       name = "Tom";
   }
초기화 블록은 객체가 생성될 때 로드되는 코드 조각입니다. 이러한 블록은 일반적으로 클래스가 로드될 때 필요한 특정 복잡한 계산을 수행하는 데 사용됩니다. 이러한 계산 결과는 변수 값으로 설정될 수 있습니다. 일반적인 초기화 블록 외에도 정적 초기화 블록이 있습니다. 동일해 보이지만 여는 중괄호 앞에 static 키워드가 있습니다.
class Cat {
   private static int age;
   private static String name;

   static{
       age = 10;
       name = "Tom";
   }
이 블록은 이전 블록과 동일합니다. 그러나 일반 객체가 각 객체가 초기화될 때 실행된다면 정적 객체는 클래스가 로드될 때 한 번만 실행됩니다. 일반적으로 특정 복잡한 계산은 정적 클래스 변수를 초기화하는 데 사용되는 정적 블록에서 수행됩니다. 정적 메서드에 적용되는 정적 블록에도 동일한 제한 사항이 적용됩니다. 즉, 정적 블록의 현재 개체( this )에 대한 참조와 같은 비정적 데이터를 사용할 수 없습니다 . Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 4 - 6이제 초기화 블록이 호출되는 시기를 더 잘 이해하기 위해 클래스의 초기화 순서(상위 클래스와 함께)를 살펴볼 수 있습니다.

36. Parent를 확장하는 공개 Child 클래스가 주어지면 객체의 초기화 순서를 작성합니다.

Child 클래스를 로드할 때 초기화 순서는 다음과 같습니다.
  1. 상위 클래스 의 정적 클래스 필드입니다 .
  2. Parent 클래스 의 정적 초기화 블록입니다 .
  3. Сhild 클래스 의 정적 필드입니다 .
  4. Child 클래스 의 정적 초기화 블록입니다 .
  5. Parent 클래스 의 비정적 필드입니다 .
  6. Parent 클래스 의 비정적 초기화 블록입니다 .
  7. 상위 클래스 생성자.
  8. Сhild 클래스 의 비정적 필드입니다 .
  9. Сhild 클래스 의 비정적 초기화 블록입니다 .
  10. Сhild 클래스 의 생성자입니다 .
Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 4 - 7

37. 클래스(객체) 간의 어떤 관계를 알고 있나요?

Java에는 기본 유형과 본격적인 객체에 대한 참조라는 두 가지 종류의 변수가 있습니다.
  • IS-A 관계
OOP의 IS-A 원칙은 클래스 상속 또는 인터페이스 구현을 기반으로 합니다. 예를 들어 Lion 클래스가 Cat 을 상속받는 경우 Lion은 Cat 이라고 말합니다 .
Lion IS-A Cat
(그러나 모든 고양이사자 는 아닙니다 ) 인터페이스에도 동일한 상황이 존재합니다. Lion 클래스가 WildAnimal 인터페이스를 구현하는 경우 해당 인터페이스도 관계에 존재합니다.
Lion IS-A WildAnimal
  • HAS-A 관계
이러한 유형의 관계는 한 클래스가 "연관"이라고도 하는 다른 클래스를 사용하는 경우입니다. 연관은 다른 클래스를 참조하는(또는 서로에 대한 상호 참조) 하나의 클래스입니다. 예를 들어 Car 클래스는 Passenger 클래스를 참조할 수 있으며 이는 다음 관계를 구성합니다.
Car HAS-A Passenger
반대의 경우도 마찬가지입니다. Passenger가 Car 에 대한 참조를 갖고 있는 경우 다음과 같은 관계가 됩니다.
Passenger HAS-A Car

38. 당신은 어떤 연관 객체 관계를 알고 있습니까?

집합과 구성은 연합의 특별한 경우에 지나지 않습니다. 집계는 한 개체가 다른 개체의 일부인 관계입니다. 예를 들어, 승객이 자동차 안에 있을 수 있습니다. 게다가 승객이 여러 명일 수도 있고 전혀 없을 수도 있습니다(그리고 Tesla에 관해 이야기하고 있다면 운전자가 없을 수도 있습니다). 예를 들어:
public class Car {
   private List passengers = new ArrayList<>();

 void setPassenger(Passenger passenger) {
     passengers.add(passenger);
 }

   void move() {
       for (Passenger passenger : passengers) {
           System.out.println("Transporting passenger - " + passenger.toString());
       }
       passengers.clear();
   }
}
즉, 승객 수는 우리에게 중요하지 않습니다. Car 클래스의 기능은 이에 의존하지 않습니다. 또한 집계는 다른 개체가 하나의 개체를 사용할 때 첫 번째 개체를 다른 개체에서 사용할 수 있음을 의미합니다. 예를 들어, 같은 학생이 뜨개질 클럽과 록 밴드에 동시에 속해 있고 동시에 스페인어 수업에 참석할 수도 있습니다. 상상할 수 있듯이 집계는 클래스 간의 보다 느슨한 연관 관계입니다. 구성은 개체가 다른 개체의 일부일 뿐만 아니라 한 개체의 작업이 다른 개체에 크게 의존하는 훨씬 더 긴밀한 관계입니다. 예를 들어, 자동차에는 엔진이 있습니다. 자동차 없이도 엔진은 존재할 수 있지만 자동차 밖에서는 쓸모가 없습니다. 그리고 자동차는 엔진 없이는 작동할 수 없습니다.
public class Car {
   private Engine engine;

   public Car(Engine engine) {
       this.engine = engine;
   }

   void startMoving() {
       engine.start();
           ...
   }
또한 합성은 다른 개체가 개체를 사용할 때 첫 번째 개체가 다른 개체에 속할 수 없음을 의미합니다. 우리의 예로 돌아가면, 엔진은 동시에 두 대 이상의 자동차에 속할 수 없고 한 대의 자동차에만 속할 수 있습니다. 오늘은 이 정도면 충분할 것 같으니 여기서 그만 두겠습니다.