JavaRush /Java Blog /Random-KO /Java 개발자 인터뷰의 질문과 답변을 분석합니다. 2 부

Java 개발자 인터뷰의 질문과 답변을 분석합니다. 2 부

Random-KO 그룹에 게시되었습니다
다시 한번 안녕하세요 여러분! 우리는 주니어, 미들, 시니어 개발자를 위한 250개 이상의 질문 에 대한 답변을 계속 찾고 있습니다 . 질문은 매우 흥미롭고 나 자신도 그것을 분석하는 것을 좋아합니다. 그러한 순간에 이론적 지식과 가장 예상치 못한 곳에서 격차를 발견할 수 있습니다. 면접 질문과 답변을 분석합니다.  파트 2 - 1이전 부분은 이 기사에서 찾을 수 있습니다 . 하지만 시작하기 전에 다음 사항을 상기시켜드리고 싶습니다.
  1. 다시 한 번 정보가 중복되지 않도록 이 기사 시리즈 와 교차하는 질문은 건너뛰겠습니다. 이 자료에는 가장 일반적인(인기 있는) Java Core 인터뷰 질문이 포함되어 있으므로 읽어 보는 것이 좋습니다.
  2. DOU에 대한 질문은 우크라이나어로 제공되지만 여기서는 모든 내용을 러시아어로 설명하겠습니다.
  3. 답변을 더 자세히 설명할 수 있지만 그렇게 하지 않겠습니다. 왜냐하면 각 질문에 대한 답변이 전체 기사를 차지할 수 있기 때문입니다. 그리고 어떤 면접에서도 그렇게 자세히 물어보지는 않습니다.
필요하다면 더 깊은 연구를 위한 링크를 남겨두겠습니다. 날아보자!

11. Object 클래스의 모든 메소드 이름을 지정하십시오.

Object 클래스에는 11가지 메서드가 있습니다.
  • Class<?> getClass() — 현재 객체의 클래스를 가져옵니다.
  • int hashCode() — 현재 객체의 해시 코드를 가져옵니다.
  • boolean =(Object obj) - 현재 객체를 다른 객체와 비교합니다.
  • Object clone() - 현재 객체의 복사본을 생성하고 반환합니다.
  • String toString() — 객체의 문자열 표현을 가져옵니다.
  • void inform() - 이 객체의 모니터에서 대기 중인 하나의 스레드를 깨웁니다(스레드 선택은 무작위입니다).
  • void informAll() - 이 객체의 모니터에서 대기 중인 모든 스레드를 깨웁니다.
  • void wait() - 현재 모니터에서 현재 스레드를 대기 모드로 전환(고정)하고 일부 inform 또는 informAll이 스레드를 깨울 때까지 동기화된 블록에서만 작동합니다.
  • void wait(long timeout) - 또한 현재 모니터(현재 동기화된 모니터)의 현재 스레드를 고정하지만 타이머를 사용하여 이 상태를 종료합니다(또는 다시: inform 또는 informAll이 깨어날 때까지).
  • void wait(long timeout, int nanos) - 위에서 설명한 것과 유사한 방법이지만 동결을 종료하기 위한 더 정확한 타이머가 있습니다.
  • void finalize() - 이 개체를 삭제하기 전에 가비지 수집기가 이 메서드를 (마지막으로) 호출합니다. 점유된 자원을 정리하는 데 사용됩니다.
hashCode , equals​ , clone , toString 및 finalize 메소드를 올바르게 사용하려면 현재 작업과 상황을 고려하여 재정의해야 합니다.

12. 리소스를 다룰 때 try-with-resources와 try-catch-finally의 차이점은 무엇입니까?

일반적으로 try-catch-finally를 사용할 때 마지막 블록은 리소스를 닫는 데 사용되었습니다. Java 7에서는 리소스를 해제하기 위한 try-catch-finally와 유사 하지만 더 간결하고 읽기 쉬운 새로운 유형의 연산자 try-with-resources를 도입했습니다. try-catch-finally가 어떻게 생겼는지 기억해 봅시다 :
String text = "some text......";
BufferedWriter bufferedWriter = null;
try {
   bufferedWriter = new BufferedWriter(new FileWriter("someFileName"));
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
} finally {
   try {
       bufferedWriter.close();
   } catch (IOException e) {
       e.printStackTrace();
   }
}
이제 try-with-resources를 사용하여 이 코드를 다시 작성해 보겠습니다 .
String text = "some text......";
try(BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("someFileName"))) {
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
}
왠지 더 쉬워질 것 같지 않나요? 단순화 외에도 몇 가지 사항이 있습니다.
  1. try-with-resources 에서 괄호 안에 선언된 리소스(닫혀질)는 AutoCloseable 인터페이스와 해당 인터페이스의 유일한 메서드인 close() 를 구현해야 합니다 .

    close 메소드는 암시적 finally 블록 에서 실행됩니다 . 그렇지 않으면 프로그램이 주어진 리소스를 닫는 방법을 정확히 어떻게 이해할 수 있을까요?

    그러나 대부분의 경우 리소스 구현과 종료 방법을 직접 작성하는 경우는 거의 없습니다.

  2. 블록 실행 순서:

    1. 차단 해 보세요 .
    2. 암시적 finally .
    3. 이전 단계에서 예외를 포착하는 catch 블록입니다 .
    4. 드디어 명시적 .

    일반적으로 목록에서 아래쪽에 나타나는 예외는 위쪽에 나타나는 예외를 방해합니다.

try-catch-finally 를 사용할 때 try 에서 예외가 발생하는 상황을 상상해 보세요 . 따라서 특정 catch 블록이 즉시 실행되기 시작합니다 . 여기서 다른 예외(예: 오류를 더 자세히 설명하는 메시지 포함)를 작성하고 메서드에서 이 예외를 추가로 발생시키려고 합니다. 다음으로 finally 블록 이 실행되고 예외도 발생합니다. 그러나 이것은 다릅니다. 이 두 가지 예외 중 이 메서드가 궁극적으로 발생하는 예외는 무엇입니까? finally 블록 에서 예외가 발생했습니다 ! 그러나 try-with-resources 에도 한 가지 요점이 있습니다 . 이제 동일한 상황에서 try-with-resources 의 동작을 살펴보겠습니다 . close() 메서드 , 즉 암시적 finally 메서드 에서 리소스를 닫으려고 하면 try 블록 에서 예외가 발생합니다 . 다음 중 어떤 예외가 발생 합니까 ? try 블록 에 의해 던져진 것 ! 암시적 finally ( close() 메서드 의) 예외는 무시됩니다. 이러한 무시를 예외 억제라고도 합니다.

13. 비트 연산이란 무엇입니까?

비트 연산은 논리 연산과 비트 시프트를 포함하는 비트 문자열에 대한 연산입니다. 논리 연산:
  • 비트 AND - 비트 값을 비교하며, 이 과정에서 0(false)으로 설정된 비트는 결과의 해당 비트를 0으로 설정합니다. 즉, 비교되는 두 값 모두에서 비트가 1(true)인 경우 결과도 1이 됩니다.

    - AND , & 로 표시

    예: 10111101 & 01100111 = 00100101

  • 비트 OR은 이전 OR의 역연산입니다. 1로 설정된 비트는 결과에서 유사한 비트를 1로 설정합니다. 따라서 비교된 두 값 모두에서 비트가 0인 경우 결과 비트도 0이 됩니다.

    - OR , | 로 표시됩니다.

    예: 10100101 | 01100011 = 11100111

  • 비트별 NOT - 하나의 값에 적용되어 비트를 뒤집습니다(반전). 즉, 1이었던 비트는 0이 됩니다. 0이었던 것들은 1이 될 것입니다.

    - NOT , ~ 로 표시

    예: ~10100101 = 01011010

  • 비트 배타적 OR - 비트 값을 비교하여 두 값 모두에서 비트가 1이면 결과는 0이 되고, 두 값 모두에서 비트가 0이면 결과는 0이 됩니다. 즉, 결과가 1이 되려면 비트 중 하나만 1이어야 하고 두 번째 비트는 0이어야 합니다.

    - XOR , ^ 로 표시됩니다.

    예: 10100101 ^ 01100011 = 11000110

비트 단위 이동 - >> 또는 << 값의 비트를 지정된 방향으로 지정된 숫자만큼 이동합니다. 비어 있는 자리는 0으로 채워집니다. 예를 들어:
  1. 01100011 >> 4 = 00000110
  2. 01100011 << 3 = 00011000
음수를 오른쪽으로 이동하는 경우에도 예외가 있습니다. 기억하는 것처럼 첫 번째 비트는 부호를 담당하고 이 비트가 1이면 숫자는 음수입니다. 음수를 이동하면 부호 비트를 유지해야 하기 때문에 비어 있는 위치는 더 이상 0이 아닌 1로 채워집니다. 예: 10100010 >> 2 = 11101000 동시에 Java에는 부호 없는 오른쪽 이동 연산자가 추가로 있습니다 >>> 이 연산자는 >>와 유사합니다. 이동 시 비어 있는 위치는 여부에 관계없이 0으로 채워집니다. 숫자는 음수 또는 양수입니다. 예: 10100010 >>> 2 = 00101000 여기에서 비트 연산에 대해 자세히 알아보세요 . 면접 질문과 답변을 분석합니다.  파트 2 - 2Java에서 비트 단위 이동을 사용하는 예로 키에 대한 특수 내부 해시 코드를 결정하는 데 사용되는 HashMap의 hash()면접 질문과 답변을 분석합니다.  파트 2 - 3 메서드를 인용할 수 있습니다. 이 메서드를 사용하면 HashMap에 데이터를 균등하게 분산하여 최소화할 수 있습니다. 충돌 횟수.

14. Java의 객체는 어떤 표준 불변 클래스입니까?

Immutable 은 원래 매개변수를 변경할 수 없는 객체입니다. 변경하려는 매개변수와 함께 특정 유형의 새 객체를 반환하는 메서드가 있을 수 있습니다. 일부 표준 불변 객체:
  • Java에서 가장 유명한 불변 객체는 String입니다.
  • 표준 유형(Boolean, Character, Byte, Short, Integer, Long, Double, Float)을 래핑하는 래퍼 클래스 인스턴스.
  • 특히 큰 숫자(BigInteger 및 BigDecimal)에 일반적으로 사용되는 객체;
  • 스택 추적의 단위인 객체(예: 예외 스택 추적) StackTraceElement;
  • File 클래스의 객체 - 파일을 변경할 수 있지만 동시에 파일 자체는 변경할 수 없습니다.
  • UUID - 요소의 고유 ID로 자주 사용됩니다.
  • java.time 패키지의 모든 클래스 객체;
  • 로캘 - 지리적, 정치적 또는 문화적 지역을 정의하는 데 사용됩니다.

15. 일반 객체에 비해 불변 객체의 장점은 무엇입니까?

  1. 이러한 개체는 다중 스레드 환경에서 사용될 때 안전 합니다 . 이를 사용하면 스레드 경쟁 조건으로 인한 데이터 손실에 대해 걱정할 필요가 없습니다. 일반 개체로 작업하는 것과는 달리 이 경우에는 매우 신중하게 생각하고 병렬 환경에서 개체를 사용하기 위한 메커니즘을 해결해야 합니다.
  2. 불변 객체는 맵에서 좋은 키입니다. 왜냐하면 가변 객체를 사용한 다음 객체의 상태가 변경되면 HashMap을 사용할 때 혼란스러울 수 있기 때문입니다. 객체는 여전히 존재하지만, containKey()를 사용하면 객체 가 존재하지 않을 수 있습니다. 찾을 수 있습니다.
  3. 불변 객체는 프로그램이 실행되는 동안 절대 변경되어서는 안 되는 불변(상수) 데이터를 저장하는 데 적합합니다.
  4. "실패에 대한 원자성" - 불변 객체가 예외를 발생시키는 경우에도 원치 않는(깨진) 상태로 남아 있지 않습니다.
  5. 이러한 클래스는 테스트하기 쉽습니다.
  6. 복사 생성자 및 복제 구현과 같은 추가 메커니즘은 필요하지 않습니다.

OOP에 대한 질문

면접 질문과 답변을 분석합니다.  파트 2 - 4

16. 절차적 프로그래밍과 비교하여 일반적으로 OOP의 장점은 무엇입니까?

따라서 OOP의 장점은 다음과 같습니다.
  1. 복잡한 애플리케이션은 절차적 프로그래밍보다 작성하기가 더 쉽습니다. 모든 것이 작은 모듈(서로 상호 작용하는 개체)로 나누어지고 결과적으로 프로그래밍이 개체 간의 관계로 귀결되기 때문입니다.
  2. OOP를 사용하여 작성된 애플리케이션은 수정하기가 훨씬 쉽습니다(디자인 개념을 따르는 한).
  3. 이에 대한 데이터와 작업은 단일 엔터티를 형성하므로 애플리케이션 전체에 번지지 않습니다(절차적 프로그래밍에서 흔히 발생함).
  4. 정보 캡슐화는 사용자의 가장 중요한 데이터를 보호합니다.
  5. 클래스를 사용하면 각각 고유한 속성 값을 갖는 많은 개체를 만들 수 있으므로 동일한 코드를 다른 데이터로 재사용할 수 있습니다.
  6. 상속과 다형성을 사용하면 유사한 기능을 복제하는 대신 기존 코드를 재사용하고 확장할 수도 있습니다.
  7. 절차적 접근 방식보다 애플리케이션 확장이 더 쉽습니다.
  8. OOP 접근 방식을 사용하면 구현 세부 사항을 추상화할 수 있습니다.

17. OOP에 어떤 단점이 있는지 알려주세요

불행히도 다음과 같은 항목도 있습니다.
  1. OOP에는 무엇이든 작성하기 전에 숙달해야 하는 많은 이론적 지식이 필요합니다.면접 질문과 답변을 분석합니다.  파트 2 - 5
  2. OOP의 아이디어는 실제로 이해하고 적용하기가 쉽지 않습니다(마음속으로 철학자가 되어야 합니다).
  3. OOP를 사용하면 시스템 구성이 더욱 복잡해지기 때문에 소프트웨어 성능이 약간 저하됩니다.
  4. OOP 접근 방식은 모든 것이 일반 변수보다 훨씬 더 많은 메모리를 차지하는 클래스, 인터페이스, 메서드로 구성되므로 더 많은 메모리가 필요합니다.
  5. 초기 분석에 필요한 시간은 절차적 분석보다 더 깁니다.

18. 정적 다형성과 동적 다형성이란 무엇입니까?

다형성을 통해 객체는 동일한 클래스나 인터페이스에 대해 다르게 동작할 수 있습니다. 다형성에는 초기 바인딩 과 후기 바인딩 이라고도 알려진 두 가지 유형이 있습니다 . 정적 다형성 또는 이전 바인딩:
  • 컴파일 타임(프로그램 라이프사이클 초기)에 발생합니다.
  • 컴파일 타임에 실행할 메소드를 결정합니다.
  • 메소드 오버로딩은 정적 다형성의 한 예입니다.
  • 초기 바인딩에는 개인용, 정적 및 터미널 메서드가 포함됩니다.
  • 상속은 초기 바인딩에 관여하지 않습니다.
  • 정적 다형성에는 특정 개체가 포함되지 않지만 클래스에 대한 정보가 포함되며 해당 유형은 변수 이름 왼쪽에 표시됩니다.
동적 다형성 또는 후기 바인딩:
  • 런타임에 발생합니다(프로그램이 실행되는 동안).
  • 동적 다형성은 런타임 시 메서드가 어떤 특정 구현을 갖게 될지 결정합니다.
  • 메서드 재정의는 동적 다형성의 예입니다.
  • 후기 바인딩은 특정 객체, 해당 유형의 참조 또는 해당 슈퍼클래스를 할당하는 것입니다.
  • 상속은 동적 다형성과 연관되어 있습니다.
이 기사에서 초기 바인딩과 후기 바인딩의 차이점에 대해 자세히 알아볼 수 있습니다 .

19. OOP의 추상화 원칙 정의

OOP의 추상화는 중요하지 않은 세부 사항을 제외하고 개체의 중요한 특성 집합을 강조하는 방법입니다. 즉, OOP 접근 방식으로 프로그램을 설계할 때 구현의 세부 사항을 조사하지 않고 일반적인 모델에 중점을 둡니다. Java에서는 인터페이스가 추상화를 담당합니다 . 예를 들어, 기계가 있고 이것이 인터페이스가 될 것입니다. 그리고 엔진 시동, 기어박스 사용 등 다양한 상호 작용은 구현 세부 사항을 다루지 않고도 사용하는 기능입니다. 결국, 자동차를 운전하는 순간에는 기어박스가 그 목적을 정확히 어떻게 수행하는지, 키가 어떻게 엔진을 시동하는지, 스티어링 휠이 바퀴를 어떻게 돌리는지에 대해 생각하지 않습니다. 그리고 이 기능 중 하나(예: 엔진)의 구현이 대체되더라도 이를 눈치채지 못할 수도 있습니다. 이것은 당신에게 중요하지 않습니다. 구현에 대한 세부 사항을 다루지 않습니다. 조치가 수행되는 것이 중요합니다. 실제로 이는 구현 세부 사항의 추상화입니다. 오늘은 여기서 멈출 것입니다. 계속하세요!면접 질문과 답변을 분석합니다.  파트 2 - 6
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION