Java에 왜 일시적인 필드가 있습니까?


답변:


1673

transientJava 의 키워드는 필드가 직렬화 ( 파일 과 같이 저장됨을 의미 함 ) 프로세스의 일부가 아니어야 함을 나타내는 데 사용됩니다 .

로부터 Java 언어 사양, 자바 SE 7 판 , 제 8.3.1.3. transient분야 :

변수는 transient객체의 영속 상태에 속하지 않음을 나타내도록 표시 될 수 있습니다 .

예를 들어, 다른 필드에서 파생 된 필드가있을 수 있으며 직렬화를 통해 상태를 유지하지 않고 프로그래밍 방식으로 만 수행해야합니다.

다음 GalleryImage은 이미지와 이미지에서 파생 된 썸네일을 포함하는 클래스입니다.

class GalleryImage implements Serializable
{
    private Image image;
    private transient Image thumbnailImage;

    private void generateThumbnail()
    {
        // Generate thumbnail.
    }

    private void readObject(ObjectInputStream inputStream)
            throws IOException, ClassNotFoundException
    {
        inputStream.defaultReadObject();
        generateThumbnail();
    }    
}

이 예제에서는 메소드 thumbnailImage를 호출하여 생성 된 썸네일 이미지입니다 generateThumbnail.

thumbnailImage필드는로 표시 transient되므로 image원본 이미지와 축소판 이미지를 모두 유지하지 않고 원본 만 직렬화됩니다. 이는 직렬화 된 객체를 저장하는 데 필요한 스토리지가 적다는 것을 의미합니다. (물론 이것은 시스템의 요구 사항에 따라 바람직하거나 바람직하지 않을 수 있습니다. 이것은 단지 예일뿐입니다.)

직렬화 해제시, readObject메소드는 직렬화가 발생한 상태로 오브젝트 상태를 다시 복원하는 데 필요한 조작을 수행하기 위해 호출됩니다. 여기에서 썸네일을 생성해야하므로 readObject메소드를 호출하여 썸네일이 생성되도록 메소드를 대체합니다 generateThumbnail.

추가 정보를 위해 , Java Serialization API 기사 (Sun Developer Network에서 원래 사용 가능) 의 비밀 발견transient 은 특정 필드의 직렬화를 막기 위해 키워드를 사용 하는 시나리오에 대해 설명하고 시나리오를 제시하는 섹션이 있습니다.


221
그러나 왜 키워드가 아닌 주석 @DoNotSerialize입니까?
Elazar Leibovich

333
Java에 주석이 없었던 시간에 소유 된 것 같습니다.
피터 위퍼 만

46
직렬화가 Java 내부에 있다는 것이 이상합니다. 사용자가 read 및 write 메소드를 대체해야하는 인터페이스 또는 추상 클래스로 구현 될 수 있습니다.
caleb

7
@MJafar : readObject는 일반적으로 역 직렬화 메커니즘에 연결되어 자동으로 호출됩니다. 또한 많은 경우에이를 재정의 할 필요가 없습니다. 기본 구현은 트릭을 수행합니다.
Mike Adler

13
@caleb 아마도 바이너리 형식을 다루는 것이 부호없는 정수의 부족으로 인해 Java에서 엄청나게 고통스럽기 때문일 것입니다.
rightfold

435

transient키워드를 이해하기 전에 직렬화 개념을 이해해야합니다. 독자가 직렬화에 대해 알고 있다면 첫 번째 단계를 건너 뛰십시오.

직렬화 란 무엇입니까?

직렬화는 객체의 상태를 지속시키는 프로세스입니다. 이는 객체의 상태가 지속 (예 : 파일에 바이트 저장) 또는 전송 (예 : 네트워크를 통해 바이트 전송)에 사용되는 바이트 스트림으로 변환됨을 의미합니다. 같은 방식으로 역 직렬화를 사용하여 객체의 상태를 바이트에서 다시 가져올 수 있습니다. 직렬화는 주로 네트워킹 프로그래밍에 사용되므로 Java 프로그래밍에서 중요한 개념 중 하나입니다. 네트워크를 통해 전송해야하는 객체는 바이트로 변환되어야합니다. 이를 위해 모든 클래스 또는 인터페이스가 인터페이스를 구현해야합니다 Serializable. 메소드가없는 마커 인터페이스입니다.

이제 transient키워드와 목적은 무엇입니까?

기본적으로 모든 객체 변수는 지속적 상태로 변환됩니다. 경우에 따라 일부 변수를 유지할 필요가 없기 때문에 일부 변수를 유지하지 않을 수도 있습니다. 따라서 해당 변수를로 선언 할 수 있습니다 transient. 변수가로 선언 transient되면 지속되지 않습니다. 이것이 transient키워드 의 주요 목적입니다 .

다음 예제로 위의 두 가지 사항을 설명하고 싶습니다.

package javabeat.samples;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class NameStore implements Serializable{
    private String firstName;
    private transient String middleName;
    private String lastName;

    public NameStore (String fName, String mName, String lName){
        this.firstName = fName;
        this.middleName = mName;
        this.lastName = lName;
    }

    public String toString(){
        StringBuffer sb = new StringBuffer(40);
        sb.append("First Name : ");
        sb.append(this.firstName);
        sb.append("Middle Name : ");
        sb.append(this.middleName);
        sb.append("Last Name : ");
        sb.append(this.lastName);
        return sb.toString();
    }
}

public class TransientExample{
    public static void main(String args[]) throws Exception {
        NameStore nameStore = new NameStore("Steve", "Middle","Jobs");
        ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("nameStore"));
        // writing to object
        o.writeObject(nameStore);
        o.close();

        // reading from object
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore"));
        NameStore nameStore1 = (NameStore)in.readObject();
        System.out.println(nameStore1);
    }
}

출력은 다음과 같습니다.

First Name : Steve
Middle Name : null
Last Name : Jobs

중간 이름 은으로 선언 transient되므로 영구 저장소에 저장되지 않습니다.

출처


26
이 예제는이 코드에서 가져온 것입니다. 여기에서 읽을 수 있습니다. javabeat.net/2009/02/what-is-transient-keyword-in-java
Krishna

11
이 부분은 저를 이상하고 혼란스럽게 생각합니다. "이것은 객체의 상태가 바이트 스트림으로 변환되어 파일에 저장 된다는 것을 의미합니다 ." 대부분의 시간 직렬화는 파일에 쓰는 것을 포함하지 않는 것 같습니다 (
정확한

5
중간 이름이 일시적인 속성이 아니기 때문에이 예는 좋지 않습니다 .
Raphael

1
@Raphael 저에게있어, 예제는 도움이되고 최소한 개념을 설명합니다. 잘 알고 있다면 더 좋은 예를 들어 주시겠습니까?
Chaklader Asfak Arefe

@Yoda 우리는 NameFormatter운전 하는 데 사용되는 참조를 가질 수 있습니다 toString(). 또는 데이터와 달리 구성,보기 또는 비즈니스 로직과 관련된 기타 사항.
Raphael

84

직렬화하지 않을 변수를 정의 할 수 있습니다.

객체에는 직렬화 / 유지하지 않으려는 정보 (아마도 부모 팩토리 객체에 대한 참조)가 있거나 직렬화하는 것이 의미가 없습니다. 이를 '일시적'으로 표시하면 직렬화 메커니즘이이 필드를 무시합니다.


36

나의 작은 기여 :

과도 필드 란 무엇입니까?
기본적으로 transient키워드로 수정 된 모든 필드 는 임시 필드입니다.

Java에서 임시 필드가 필요한 이유는 무엇입니까? 키워드는 당신에게 직렬화 프로세스 일부 제어를 제공하고이 과정에서 일부 개체 속성을 제외 할 수 있습니다. 직렬화 프로세스는 Java 오브젝트를 지속시키는 데 사용되며, 대부분 전송 또는 비활성 상태에서 해당 상태를 보존 할 수 있습니다. 때로는 객체의 특정 속성을 직렬화하지 않는 것이 좋습니다. 어떤 필드를 일시적으로 표시해야합니까? 이제 우리는
transient


transient키워드 및 과도 필드에서는 과도 필드를 표시 할 필드를 알아야합니다. 정적 필드도 직렬화되지 않으므로 해당 키워드도 트릭을 수행합니다. 그러나 이것은 클래스 디자인을 망칠 수 있습니다. 곳이다 transient키워드는 구조로되어 있습니다. 다른 값에서 파생 될 수있는 값을 가진 필드를 직렬화 할 수 없도록하기 위해 일시적으로 표시합니다. 당신이라는 필드가있는 경우 interest그 값이 다른 필드로부터 계산 (수 principal, rate&를 time) 직렬화 할 필요가 없습니다.

또 다른 좋은 예는 기사 단어 수입니다. 전체 기사를 저장하는 경우 기사가 "직렬화 해제"될 때 계산 될 수 있으므로 단어 수를 저장할 필요가 없습니다. 또는 로거에 대해 생각하십시오.Logger 인스턴스를 거의 직렬화 할 필요가 없으므로 일시적으로 만들 수 있습니다.


63
당신의 '간단한 문장'은 단지 팽팽한 설명 일뿐입니다. 아무것도 설명하지 않습니다. 그것 없이는 더 나아질 것입니다.
user207421

1
이 필드가 어디에 있어야 좋은 설명입니다transient
Chaklader Asfak Arefe

1
관심 분야 필드 및 단어 수는 과도 필드의 좋은 예입니다.
Tarun

1
또 다른 좋은 사용 사례 : 객체에 소켓과 같은 구성 요소가 있고 직렬화하려는 경우 소켓은 어떻게됩니까? 계속된다면 소켓이 무엇을 직렬화 해제 한 후에? 소켓 객체를 다음과 같이 만드는 것이 합리적입니다.transient
Mohammed Siddiq

28

transient변수 직렬화 될 수있는 변수이다.

이것이 유용 할 때 유용한 예 중 하나는 특정 객체 인스턴스의 컨텍스트에서만 의미가 있고 객체를 직렬화하고 역 직렬화하면 유효하지 않은 변수입니다. 이 경우 null필요할 때 유용한 데이터로 변수 를 다시 초기화 할 수 있도록 변수를 대신 사용하는 것이 좋습니다.


예, 클래스의 "암호 또는 crediCardPin"필드 멤버와 같은 것.
Mateen

17

transient클래스 필드를 직렬화 할 필요가 없음을 나타내는 데 사용됩니다. 아마도 가장 좋은 예는 Thread필드입니다. Thread상태가 '흐름에 따라' 다르기 때문에 일반적으로를 직렬화 할 이유가 없습니다 .


내가 틀렸다면 수정하지만 Thread는 직렬화 할 수 없으므로 어쨌든 건너 ​​뛸 것입니까?
TFennis

3
@TFennis : 직렬화 클래스의 경우 A참조합니다하지 직렬화 클래스 B(같은 Thread귀하의 예제에서), 다음 A과 같이 하나의 기준을 표시해야합니다 transient합리적인 뭔가 할하기 위해 XOR 기본 직렬화 프로세스를 재정의해야 B만 직렬화 서브 클래스를 가정 XOR을의 B실제로 참조하는 (실제 서브 클래스는 "나쁜"부모를 돌봐야한다 B) XOR은 직렬화가 실패한다는 것을 받아 들인다. 단 하나의 경우 (일시적으로 표시됨) B는 자동으로 자동 건너 뜁니다.
AH

3
@TFennis 아니요, 예외가 발생합니다.
user207421

1
@AH : 왜 XOR인가? 나는 그것들의 조합을 수행 한 코드가 작동한다고 생각할 것이고, 일부 조합이 유용 할 수 있습니다 (예 : B의 ​​직렬화 가능한 서브 클래스 만 참조되고 그 반대의 경우에도 기본 직렬화 프로세스를 재정의하는 것이 유용 할 수 있습니다).
supercat

15

원시 Java 이외의 직렬화 시스템도이 수정자를 사용할 수 있습니다. 예를 들어, 최대 절전 모드는 @Transient 또는 transient 수정 자로 표시된 필드를 유지하지 않습니다 . 테라코타는이 수정자를 존중합니다.

수정 자의 비유적인 의미는 "이 필드는 메모리 내에서만 사용하기위한 것입니다. 어떤 방식 으로든이 특정 VM 외부로 유지하거나 옮기지 마십시오. 이식성이 없습니다"라고 생각합니다. 즉, 다른 VM 메모리 공간에서 그 값에 의존 할 수 없습니다. 휘발성 과 매우 흡사 하다는 것은 특정 메모리 및 스레드 의미에 의존 할 수 없음을 의미합니다.


14
나는 이것이 transient현재 설계 되었다면 키워드가 아닐 것이라고 생각합니다 . 아마도 주석을 사용했을 것입니다.
Joachim Sauer


7

이 질문에 답하기 전에 SERIALIZATION을 설명해야합니다 . 과학 컴퓨터에서 직렬화가 무엇을 의미하는지 이해하면이 키워드를 쉽게 이해할 수 있기 때문입니다.

직렬화 개체가 네트워크를 통해 전송되거나 실제 미디어 (파일, ...)에 저장된 경우 개체는 "직렬화"되어야합니다. 직렬화는 바이트 상태 객체 시리즈를 변환합니다. 이 바이트는 네트워크로 전송 / 저장되고 객체는이 바이트에서 다시 생성됩니다.

public class Foo implements Serializable 
{
 private String attr1;
 private String attr2;
 ...
}

그렇지하려면 지금 TRANSFERT / 저장된 객체의 필드를 SO , 당신이 사용할 수있는 키워드 transient

private transient attr2;


6

직렬화와 관련된 중요한 데이터를 공유하지 않으려는 경우에 필요합니다.


7
필드를 직렬화하지 않으려는 민감한 데이터 이외의 사용 사례가 있습니다. 예를 들어, 아마도 Thread(예를 들어 @AH로 신용 을) 직렬화하고 싶지 않을 것입니다 .이 경우 일시적으로 표시합니다. 그러나 스레드는 그 자체로 민감한 데이터가 아니며 직렬화하는 논리적 의미가 없으며 직렬화 할 수 없습니다.
glen3b

1
@ glen3b이 경우는이 답변에서 제외되지 않습니다. 포스터가 언급 한 경우에 서있을 때 분명히 필요합니다.
user207421

3

구글에 따르면 일시적인 의미 == 짧은 시간 동안 만 지속됩니다. 영구적이지 않은.

이제 자바에서 일시적인 것을 만들고 싶다면 transient 키워드를 사용하십시오.

Q : 과도기를 어디에 사용합니까?

A : 일반적으로 Java에서는 변수로 데이터를 가져 와서 변수를 파일에 쓰면 파일에 데이터를 저장할 수 있습니다.이 프로세스를 직렬화라고합니다. 변수 데이터가 파일에 기록되는 것을 피하려면 해당 변수를 일시적으로 만듭니다.

transient int result=10;

참고 : 임시 변수는 로컬 일 수 없습니다.


0

간단히 말해서, 일시적인 java 키워드는 필드가 비 일시적 필드 대응 부분으로 직렬화되지 않도록 필드를 보호합니다.

이 코드 스 니펫에서 추상 클래스 BaseJob은 Serializable 인터페이스를 구현하고 BaseJob에서 확장하지만 원격 및 로컬 데이터 소스를 직렬화 할 필요는 없습니다. organizationName 및 isSynced 필드 만 직렬화하십시오.

public abstract class BaseJob implements Serializable{
   public void ShouldRetryRun(){}
}

public class SyncOrganizationJob extends BaseJob {

   public String organizationName;
   public Boolean isSynced

   @Inject transient RemoteDataSource remoteDataSource;
   @Inject transient LocalDaoSource localDataSource;

   public SyncOrganizationJob(String organizationName) {
     super(new 
         Params(BACKGROUND).groupBy(GROUP).requireNetwork().persist());

      this.organizationName = organizationName;
      this.isSynced=isSynced;

   }
}

0

임시 키워드에 대한 간단한 예제 코드.

import java.io.*;

class NameStore implements Serializable {
    private String firstName, lastName;
    private transient String fullName;

    public NameStore (String fName, String lName){
        this.firstName = fName;
        this.lastName = lName;
        buildFullName();
    }

    private void buildFullName() {
        // assume building fullName is compuational/memory intensive!
        this.fullName = this.firstName + " " + this.lastName;
    }

    public String toString(){
        return "First Name : " + this.firstName
            + "\nLast Name : " + this.lastName
            + "\nFull Name : " + this.fullName;
    }

    private void readObject(ObjectInputStream inputStream)
            throws IOException, ClassNotFoundException
    {
        inputStream.defaultReadObject();
        buildFullName();
    }
}

public class TransientExample{
    public static void main(String args[]) throws Exception {
        ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("ns"));
        o.writeObject(new NameStore("Steve", "Jobs"));
        o.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ns"));
        NameStore ns = (NameStore)in.readObject();
        System.out.println(ns);
    }
}

0

임시 수정 자로 선언 된 필드는 직렬화 된 프로세스에 참여하지 않습니다. 객체가 직렬화되면 (임의의 상태로 저장 됨), 과도 필드 이외의 필드가 직렬화 프로세스에 참여하는 동안 과도 필드의 값은 직렬 표현에서 무시됩니다. 이것이 transient 키워드의 주요 목적입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.