JavaRush /Java Blog /Random-KO /인터뷰 속 연재에 관한 상위 13가지 질문
Dmitry Vasilyev
레벨 26
Саратов

인터뷰 속 연재에 관한 상위 13가지 질문

Random-KO 그룹에 게시되었습니다
기사 번역 https://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html Java에서 직렬화란 무엇입니까? 직렬화는 프로그램 상태를 저장하는 솔루션으로 거의 사용되지 않는 중요한 개념 중 하나이므로 개발자가 이 API를 간과하는 경우가 많습니다. 그러나 내 경험에 따르면 직렬화는 모든 기본 Java 인터뷰에서 매우 중요한 주제입니다. 제가 접한 거의 모든 인터뷰에는 연재에 대한 질문이 한두 가지 있었는데, 지원자들이 이 주제에 대해 몇 가지 질문을 한 후 이 분야에 대한 경험이 부족하다고 불편해하는 것을 보았습니다. 그들은 Java에서 객체를 직렬화하는 방법을 모르고 직렬화의 예에 익숙하지 않으며 해당 작업의 메커니즘, 임시 변수와 휘발성 변수의 차이점을 설명할 수 없으며 직렬화 가능 인터페이스에 얼마나 많은 메서드가 있는지 모릅니다. 가지다. 마커 인터페이스란 무엇입니까? 그 목적은 무엇입니까? Java에서 외부화 가능 구현과 직렬화 가능 구현의 차이점은 무엇입니까? 주석을 도입한 후 Java가 Serialized를 @Serialized로 바꾸지 않은 이유는 무엇입니까? 이 글에서는 초보자와 고급 개발자 모두를 위한 질문을 다룰 것입니다. 이는 주니어 개발자부터 시니어 개발자까지 모든 사람에게 똑같이 유용할 수 있습니다. 대부분의 상용 프로젝트는 더 큰 견고성을 제공하기 위해 데이터베이스, 메모리 매핑 파일 또는 일반 플랫 파일을 사용하지만 Java의 직렬화 프로세스에 의존하는 프로젝트는 거의 없습니다. 어쨌든 이 게시물은 튜토리얼이 아닙니다. 오히려 Java 인터뷰에 가기 전에 스스로 명확히 하고 자신이 모르는 용어에 놀라기 전에 스스로 명확히 할 가치가 있는 질문에 관한 것입니다. Java 직렬화에 전혀 익숙하지 않은 분들을 위해: “Java의 직렬화 는 객체의 상태를 .ser 확장자를 가진 파일에 저장하고 객체의 상태를 다시 생성하여 Java에서 객체를 직렬화하는 데 사용되는 프로세스입니다. 이 파일에서. 이 역방향 프로세스를 역직렬화라고 합니다. 세풀카 Java 직렬화 API는 개발자에게 직렬화 가능 및 외부화 가능 인터페이스를 사용하여 객체를 직렬화하기 위한 표준 메커니즘을 제공합니다. 그런데 이 글은 저의 (저, 번역가가 아닌 영어 원문의 저자) 이전 글의 연속입니다 : 디자인 패턴 에 대한 인터뷰 질문 20개와 ​​Java의 싱글턴 패턴에 대한 인터뷰 질문 10개 . 자, 가자! Java의 직렬화란 무엇입니까? Java의 객체 직렬화는 객체를 디스크에 저장하거나 네트워크를 통해 실행 중인 다른 Java 가상 머신으로 보낼 수 있는 바이너리 형식으로 변환하는 데 사용되는 프로세스입니다. 이진 스트림에서 개체를 만드는 역과정을 역직렬화라고 합니다. Java는 java.io.Serialized, java.io.Externalized, ObjectInputStream 및 ObjectOutputStream 등을 포함하는 API를 제공합니다. 프로그래머는 클래스 구조를 기반으로 Java가 사용하는 기본 직렬화 메커니즘을 자유롭게 사용할 수 있지만 자체 사용자 정의 바이너리 형식을 사용할 수도 있습니다. 이는 직렬화된 바이너리 형식이 클래스에서 내보낸 API의 일부가 되기 때문에 종종 직렬화 모범 사례로 권장됩니다. 비공개 및 패키지 비공개 필드 에서 제공하는 Java의 캡슐화를 잠재적으로 중단할 수 있습니다 . 일반적으로 이 정보는 시작하기에 충분합니다. Java 클래스를 직렬화하는 방법은 무엇입니까? 많이 쉽다. 클래스는 java.io.Serialized 인터페이스를 구현하기만 하면 JVM이 기본 형식으로 객체를 직렬화하는 작업을 처리합니다. 직렬화 가능 클래스를 생성하는 결정은 단기적으로 이루어져야 합니다. 왜냐하면 직렬화 가능 클래스를 생성하는 데 드는 단기 비용은 낮지만 장기적 비용은 상당하고 잠재적으로 구현을 추가로 수정하는 능력을 제한할 수 있기 때문입니다. 이는 공개 API와 마찬가지로 객체의 직렬화된 형식이 공개 API의 일부가 되고, 추가 인터페이스를 구현하여 클래스 구조를 변경할 때 필드를 추가하거나 제거하면 잠재적으로 기본 직렬화가 중단될 수 있기 때문에 발생합니다. 그러나 사용자 정의 바이너리 형식을 사용하면 이를 최소화할 수 있지만 이전 버전과의 호환성을 보장하려면 여전히 많은 노력이 필요합니다. 직렬화가 클래스 수정 기능을 제한하는 방법에 대한 한 가지 예는 SerialVersionUID 필드입니다. SerialVersionUID를 명시적으로 선언하지 않으면 가상 머신은 클래스에 의해 구현된 인터페이스와 변경될 수 있는 기타 여러 요소에 따라 달라지는 클래스 구조를 기반으로 이를 생성합니다. JVM이 아닌 다른 인터페이스를 구현하여 새 버전의 클래스 파일에 대해 다른 SerialVersionUID를 생성하고 이전 버전의 프로그램에서 직렬화된 이전 개체를 로드하려고 하면 다음과 같은 메시지가 표시된다고 가정해 보겠습니다. 잘못된클래스예외. 질문 1) Java에서 직렬화 가능 인터페이스와 외부화 가능 인터페이스의 차이점은 무엇입니까? 가장 자주 묻는 Java 직렬화 인터뷰 질문입니다. 외부화 가능 인터페이스는 기본 메커니즘에 의존하는 대신 직렬화를 제어할 수 있는 유연성을 제공하는 writeExternal() 및 readExternal() 메소드를 제공합니다. 외부화 가능 인터페이스를 적절하게 구현하면 애플리케이션 성능이 크게 향상될 수 있습니다. 질문 2) 직렬화 가능 메소드는 몇 개인가요? 메소드가 없다면 직렬화 가능 인터페이스의 목적은 무엇입니까? 직렬화 가능 인터페이스는 java.io 패키지에 존재하며 Java 직렬화 엔진의 핵심을 형성합니다. 메소드가 없으며 Java에서는 마커 인터페이스 라고도 합니다. 클래스가 java.io.Serialized 인터페이스를 구현하면 직렬화 가능해집니다. 간단 해. 질문 3) serialVersionUID가 무엇인가요? 정의하지 않으면 어떻게 되나요? 제가 가장 좋아하는 Java 직렬화 인터뷰 질문 중 하나입니다. SerialVersionUID는 직렬화될 때 객체에 추가되는 식별자로, 일반적으로 객체의 해시 코드입니다. serialver 도구를 사용하여 직렬화된 개체의 serialVersionUID를 가져올 수 있습니다. SerialVersionUID는 객체 버전 제어에 사용됩니다. 클래스 파일에 serialVersionUID를 수동으로 지정할 수도 있습니다. serialVersionUID를 지정하지 않으면 클래스의 필드를 추가하거나 변경하는 경우 새 클래스에 대해 생성된 serialVersionUID가 이전 직렬화된 개체의 동일한 필드와 다르기 때문에 이미 직렬화된 클래스를 복구할 수 없습니다. Java 직렬화 프로세스는 올바른 serialVersionUID를 사용하여 직렬화된 객체의 상태를 복원하고 불일치가 있는 경우 java.io.InvalidClassException을 발생시킵니다. serialversionuid에 대한 자세한 내용은 여기를 참조하세요 . 질문4) 연재시 일부 멤버가 연재되지 않도록 하시겠습니까? 이것을 달성하는 방법은 무엇입니까? 또 다른 자주 묻는 연재 인터뷰 질문입니다. 때때로 사람들은 임시 변수가 어떻게 사용되는지, 임시 및 정적 변수가 직렬화되는지 여부 등을 묻습니다. 따라서 어떤 필드도 객체 상태의 일부로 포함하지 않으려면 이를 정적 또는 임시 변수로 선언하세요. 필요에 따라 Java 직렬화 프로세스에 포함되지 않습니다. 질문 5) 클래스 멤버 중 하나가 직렬화 가능 인터페이스를 구현하지 않으면 어떻게 됩니까? Java의 직렬화 프로세스에 대한 간단한 질문 중 하나입니다. 직렬화 가능을 구현하는 클래스의 객체를 직렬화하려고 하지만 객체에 직렬화 가능하지 않은 클래스에 대한 참조가 포함되어 있으면 런타임에 NotSerializedException이 발생합니다. 이것이 제가 항상 SerializedAlert(주석 섹션에 있는 주석 섹션)를 넣는 이유입니다 . 암호), 최고의 코드 주석 기술 중 하나는 개발자에게 직렬화 가능 클래스에 새 필드를 추가할 때 이 사실을 기억하도록 지시하는 것입니다. 질문 6) 클래스가 직렬화 가능하지만 슈퍼클래스가 그렇지 않은 경우, 직렬화 해제 후 슈퍼클래스에서 상속된 인스턴스 변수의 상태는 어떻게 되나요? Java 직렬화 프로세스는 클래스가 직렬화 가능 인터페이스를 구현하고 슈퍼클래스에서 상속된 변수의 값이 역직렬화 프로세스 중에 직렬화 가능하지 않은 슈퍼클래스의 생성자를 호출하여 초기화되는 한 객체 계층 구조에서만 계속됩니다. 생성자 체인이 시작되면 이를 중지 할 방법이 없으므로 계층 구조의 상위 클래스가 직렬화 가능 인터페이스를 구현하지 않더라도 생성자가 실행됩니다. 이번 연재 면접 질문은 굉장히 어려워 보일 수도 있지만, 핵심 개념을 숙지하고 있다면 어렵지 않을 것입니다. 질문 7) Java에서 직렬화 프로세스를 사용자 정의하거나 기본 직렬화 프로세스를 재정의할 수 있습니까? 대답은 '예, 가능합니다'입니다. 우리 모두는 객체를 직렬화하기 위해 ObjectOutputStream.writeObject(saveThisObject)가 호출되고 객체를 읽으려면 ObjectInputStream.readObject()가 호출된다는 것을 알고 있습니다. 그러나 Java Virtual Machine이 제공하는 것이 한 가지 더 있습니다. 바로 이 두 메소드를 정의하는 것입니다. 네 수업 시간에. 클래스에서 정의하면 JVM은 기본 직렬화 메커니즘을 사용하는 대신 이 두 메서드를 호출합니다. 여기서 전처리 또는 후처리 작업을 수행하여 객체의 직렬화 및 역직렬화 동작을 구성할 수 있습니다. 상속, 재정의 또는 오버로드를 방지하려면 이러한 메서드를 비공개로 설정해야 한다는 점에 유의하는 것이 중요합니다. Java Virtual Machine만이 개인 메소드를 호출할 수 있으므로 클래스의 무결성이 유지되고 직렬화가 평소대로 작동합니다. 제 생각에는 이것은 Java 직렬화 인터뷰에서 물어볼 수 있는 최고의 질문 중 하나입니다. 좋은 후속 질문은 다음과 같습니다. 개체에 대해 사용자 정의 직렬화된 형식을 제공해야 하는 이유는 무엇입니까? 질문 8) 새 클래스의 슈퍼클래스가 직렬화 가능 인터페이스를 구현한다고 가정해 보겠습니다. 새 클래스의 직렬화를 어떻게 피할 수 있습니까? Java Serialization에 관한 어려운 인터뷰 질문 중 하나입니다. 클래스의 슈퍼클래스가 이미 Java에서 직렬화 가능 인터페이스를 구현한 경우 상위 클래스의 인터페이스를 구현할 수 없고 실제로 비직렬화 가능 클래스로 만드는 것이 불가능하기 때문에 하위 클래스도 직렬화 가능합니다. 그러나 이 새 클래스에 대한 직렬화를 방지하는 방법이 있습니다. 이렇게 하려면 writeObject() 및 readObject() 메서드를 구현하고 이러한 메서드에서 NotSerializedException을 발생시켜야 합니다. 이 질문은 대개 면접이 진행되면서 추가 질문으로 제기됩니다. 질문 9) Java에서 직렬화 및 역직렬화 프로세스에 사용되는 방법은 무엇입니까? 이것은 직렬화에서 매우 일반적인 질문입니다. 이 경우 면접관은 무엇을 알아내려고 합니까? readObject(), writeObject(), readExternal() 및 writeExternal() 사용에 익숙한지 여부. Java 직렬화는 java.io.ObjectOutputStream 클래스에 의해 수행됩니다. 이 클래스는 직렬화 엔진을 처리하기 위해 하위 수준 바이트 스트림을 래핑하는 필터링된 스트림입니다. 직렬화 메커니즘을 사용하여 개체를 저장하려면 ObjectOutputStream.writeObject(saveThisObject)를 호출하고 해당 개체를 역직렬화하려면 ObjectInputStream.readObject() 메서드를 호출합니다. writeObject() 메서드를 호출하면 직렬화 프로세스가 시작됩니다. readObject() 메서드에 대해 주목해야 할 중요한 점 중 하나는 이 메서드가 바이트를 읽고 해당 바이트에서 객체를 생성 및 반환하는 데 사용된다는 것입니다. 이 객체는 올바른 유형으로 캐스팅되어야 합니다. 질문 10) 직렬화하여 저장한 클래스가 있고 해당 클래스를 수정하여 새 필드를 추가한다고 가정해 보겠습니다. 이미 직렬화된 개체를 역직렬화하면 어떻게 되나요? 클래스에 자체 serialVersionUID가 있는지 여부에 따라 다릅니다. 위의 질문에서 알 수 있듯이 코드에 serialVersionUID를 제공하지 않으면 Java 컴파일러는 이를 자체적으로 생성하며 일반적으로 해당 객체의 해시 코드와 동일합니다. 새 필드를 추가한 후 해당 클래스 버전에 대해 생성된 새 serialVersionUID가 이미 직렬화된 개체와 일치하지 않을 가능성이 있으며, 이 경우 API는 java.io.InvalidClassException을 발생시킵니다. 이러한 이유로 코드에 동일한 클래스에 대해 항상 동일한 자체 serialVersionUID를 갖는 것이 좋습니다. 질문 11) Java 직렬화 메커니즘의 호환 가능한 변경 사항과 호환되지 않는 변경 사항은 무엇입니까? 실제 문제는 필드, 메소드를 추가하거나 이미 직렬화된 객체가 있는 필드 또는 메소드를 제거하여 클래스의 구조를 변경하는 것입니다. Java 직렬화 사양에 따르면 필드나 메소드를 추가하는 것은 호환 가능한 변경 및 클래스 계층 구조 또는 UN 구현 직렬화 가능 인터페이스 일부가 호환되지 않는 변경 사항에 따라 발생합니다. 호환 가능한 변경 사항과 호환되지 않는 변경 사항의 전체 목록을 보려면 Java 직렬화 사양을 읽어 보시기 바랍니다. 질문 12) 직렬화된 객체를 네트워크를 통해 전송할 수 있나요? 예, Java 직렬화된 객체는 어떤 방식으로든 전달될 수 있는 바이트 모음이므로 네트워크를 통해 직렬화된 객체를 전달할 수 있습니다. 직렬화된 개체를 디스크나 데이터베이스에 Blob으로 저장할 수도 있습니다. 질문 13) Java 직렬화 중에 직렬화되지 않는 변수 유형은 무엇입니까? 이 질문은 때때로 다르게 요청되었지만 목표는 동일합니다. 즉, Java 개발자가 정적 및 임시 변수 직렬화의 세부 사항을 알고 있는지 알아내는 것입니다. 정적 변수는 객체가 아닌 클래스에 속하므로 객체 상태의 일부가 아니므로 Java 직렬화 프로세스 중에 지속되지 않습니다. Java 직렬화는 객체 자체가 아닌 객체의 상태만 저장하므로 임시 변수도 직렬화 프로세스에 포함되지 않으며 객체의 직렬화된 상태의 일부가 아닙니다. 이 질문 후에 아마도 면접관은 다음과 같이 질문할 것입니다. 이 변수의 값을 저장하지 않으면 이 개체를 역직렬화하고 다시 만든 후에 이 변수의 값은 어떻게 됩니까? 그리고 동료 여러분, 스스로 생각해 보세요. :) 원본 기사는 여기에 있습니다 .
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION