2012-02-29 4 views
1

우리가 같은 노드와 포인터로 표시되는 임의의 그래프를 가정하자. 또한 검색 알고리즘 + 연관 배열을 사용하여이 작업을 수행 할 수 있음을 알고 있습니다. 그리고이 방법은 swizzling이라고합니다.자동 포인터 Swizzling by Java?</p> <pre><code>class Node { public ValueType data; public ArrayList<Node> adj; } </code></pre> <p>지금, 나는 (AKA 직렬화/역 직렬화)의 복사본을하거나/쓰기 디스크에 읽고 싶은 :

내가 자바 클래스로 직렬화 선언함으로써,이 기능이 자동으로 제공되는 것을 들었습니다 :

여기 내 질문에갑니다. (나에게 마술처럼 들린다!)

이 성명은 맞습니까? 자바가 자동으로 BFS를 실행하여 그래프를 탐색하고 포인터를 뒤 흔드는가? 즉, 나를 위해 개체를 serialize/deserialize 복제합니까? (동일한 구조이지만 새로운 노드와 업데이트 된 포인터를 가진 완전히 새로운 새로운 객체)

그렇다면 어떤 경우에 포인터를 복사하고 싶습니까? 원래 포인터를 유지하기 위해 객체를 직렬화하려면 어떻게해야합니까?

감사합니다. :-)

+0

Java에 원시 포인터가 없습니다. 실제 메모리 주소에 액세스 할 권한이 없습니다. 당신은 객체에 대한 참조를 가지고있다. (실제로 포인터이지만, 아무에게도 말하지 말고, C++ 레퍼런스와 혼동하지 않는다.) –

+0

읽어보십시오. 보시면 설명서에 모두 나와 있습니다. –

+0

@BrianRoach : 실수해서 죄송합니다. 나는 C++ 사고 방식을 사용했다. – Nima

답변

1

먼저 마지막 질문에 답변 해 드리겠습니다. 직렬화의 목적은 객체 그래프를 메모리에 복제하는 것이 아닙니다. 그것은 파일에 저장하거나 전선을 통해 보내는 것과 같은 일을하기 위해 객체 그래프를 바이트 스트림으로 변환하는 것입니다. 비 직렬화 프로세스는 다른 컴퓨터에서, 다른 시간에, 다른 프로세스에서 또는 비 Java 프로그램을 통해 수행 될 수 있으므로 이전과 동일한 객체에 대한 참조를 얻는 것이 합리적 인 기대는 아닙니다. 객체 그래프의 구조와 내용은 메모리에 저장되는 것이 아니라 저장되고 나중에 복원됩니다. 정확하게이 이유 때문에 모든 객체가 직렬화 될 수는 없습니다. 예를 들어, Thread을 직렬화하는 것은 현재의 프로그램 인스턴스 외부에서는 의미가 없기 때문에 유용하지 않을 것입니다.

자동 직렬화 뒤의 마법은 그리 복잡하지 않습니다.직렬화 및 직렬화 해제 동작을 정확하게 제어하기 위해 클래스에 대해 작성할 수있는 사용자 정의 직렬화 메서드를 무시하면 시스템은 효과적으로 바이트 스트림을 생성하기 위해 개체 그래프를 탐색합니다. 이 통과는 일반적으로 BFS가 아닌 DFS로 수행됩니다. 기본적으로 Java에 오브젝트에 대한 참조를 전달하여 오브젝트를 직렬화하도록 요청합니다. 이 참조는 객체 그래프의 루트 역할을합니다. 거기에서 Java는 해당 객체의 필드를 재귀 적으로 직렬화합니다. 물론, 순환 참조를 추적하고 출력 스트림에 적절한 표식을 작성하여 디시리얼라이저가 포인터를 연결하고 이전과 같은 구조를 다시 만들 수 있습니다.

+1

C++은 "how ?! : O"라는 궁금증을 가지고 걷고 있었고 Java는 윙크했습니다. 기적적! 나는 최근에 문자열에 스위치 케이스를 추가 한 언어를 의미합니다. – Nima

1

나는 그것이 당신이 그것을 어떻게 생각하고 있는지 생각하지 않는다. 그러나 꽤 많이 생각한다. Java의 직렬화는 상당히 불투명 한 프로세스입니다. 클래스와 모든 멤버 유형을 가정하고 Serializable을 구현한다고 가정 할 때 Java는이를 바이트 스트림으로 변환하는 방법과 해당 스트림에서 객체의 인스턴스를 다시 만드는 방법을 알고 있습니다. 당신은 비유 화하기를 요구합니다.

C++에서 왔을 때 처음에는 흑 마법처럼 보였습니다. 나는 전체 과정에 다소 회의적이었고 C++에서는 이것을 수행하기위한 평범한 객체에 대해 충분히 알지 못하기 때문에 JVM이 나를 돌볼 것을 정말로 신뢰하지 않았습니다. 그러나 실제로는 Java에서 데이터에 액세스해야한다고 가정 할 때 실제로 매우 좋습니다.

기본적으로 포인터 나 그 아래에서 어떤 알고리즘을 사용하는지 걱정할 필요가 없습니다. 객체를 작성한 다음 나중에 다시 읽으라고 말하면, 이전과 똑같은 메모리 구조를 갖게됩니다.

한 가지 더 : 변수를 transient으로 선언하면 저장되지 않으므로 직접 복원해야합니다. 공간을 낭비하지 않으려는 특정 값을 캐시하는 필드가 있거나 주위에 거짓말을 원하지 않는 중요한 데이터가있는 필드가있는 경우에 유용합니다. 그러나 당신은 그것을 스스로 복원해야한다는 것을 기억해야합니다.