답변:
transient
Java 의 키워드는 필드가 직렬화 ( 파일 과 같이 저장됨을 의미 함 ) 프로세스의 일부가 아니어야 함을 나타내는 데 사용됩니다 .
로부터 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
은 특정 필드의 직렬화를 막기 위해 키워드를 사용 하는 시나리오에 대해 설명하고 시나리오를 제시하는 섹션이 있습니다.
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
되므로 영구 저장소에 저장되지 않습니다.
NameFormatter
운전 하는 데 사용되는 참조를 가질 수 있습니다 toString()
. 또는 데이터와 달리 구성,보기 또는 비즈니스 로직과 관련된 기타 사항.
나의 작은 기여 :
과도 필드 란 무엇입니까?
기본적으로 transient
키워드로 수정 된 모든 필드 는 임시 필드입니다.
Java에서 임시 필드가 필요한 이유는 무엇입니까? 키워드는 당신에게 직렬화 프로세스 일부 제어를 제공하고이 과정에서 일부 개체 속성을 제외 할 수 있습니다. 직렬화 프로세스는 Java 오브젝트를 지속시키는 데 사용되며, 대부분 전송 또는 비활성 상태에서 해당 상태를 보존 할 수 있습니다. 때로는 객체의 특정 속성을 직렬화하지 않는 것이 좋습니다. 어떤 필드를 일시적으로 표시해야합니까?
이제 우리는transient
transient
키워드 및 과도 필드에서는 과도 필드를 표시 할 필드를 알아야합니다. 정적 필드도 직렬화되지 않으므로 해당 키워드도 트릭을 수행합니다. 그러나 이것은 클래스 디자인을 망칠 수 있습니다. 곳이다 transient
키워드는 구조로되어 있습니다. 다른 값에서 파생 될 수있는 값을 가진 필드를 직렬화 할 수 없도록하기 위해 일시적으로 표시합니다. 당신이라는 필드가있는 경우 interest
그 값이 다른 필드로부터 계산 (수 principal
, rate
&를 time
) 직렬화 할 필요가 없습니다.
또 다른 좋은 예는 기사 단어 수입니다. 전체 기사를 저장하는 경우 기사가 "직렬화 해제"될 때 계산 될 수 있으므로 단어 수를 저장할 필요가 없습니다. 또는 로거에 대해 생각하십시오.Logger
인스턴스를 거의 직렬화 할 필요가 없으므로 일시적으로 만들 수 있습니다.
transient
transient
transient
변수 직렬화 될 수있는 변수이다.
이것이 유용 할 때 유용한 예 중 하나는 특정 객체 인스턴스의 컨텍스트에서만 의미가 있고 객체를 직렬화하고 역 직렬화하면 유효하지 않은 변수입니다. 이 경우 null
필요할 때 유용한 데이터로 변수 를 다시 초기화 할 수 있도록 변수를 대신 사용하는 것이 좋습니다.
transient
클래스 필드를 직렬화 할 필요가 없음을 나타내는 데 사용됩니다. 아마도 가장 좋은 예는 Thread
필드입니다. Thread
상태가 '흐름에 따라' 다르기 때문에 일반적으로를 직렬화 할 이유가 없습니다 .
A
참조합니다하지 직렬화 클래스 B
(같은 Thread
귀하의 예제에서), 다음 A
과 같이 하나의 기준을 표시해야합니다 transient
합리적인 뭔가 할하기 위해 XOR 기본 직렬화 프로세스를 재정의해야 B
만 직렬화 서브 클래스를 가정 XOR을의 B
실제로 참조하는 (실제 서브 클래스는 "나쁜"부모를 돌봐야한다 B
) XOR은 직렬화가 실패한다는 것을 받아 들인다. 단 하나의 경우 (일시적으로 표시됨) B
는 자동으로 자동 건너 뜁니다.
원시 Java 이외의 직렬화 시스템도이 수정자를 사용할 수 있습니다. 예를 들어, 최대 절전 모드는 @Transient 또는 transient 수정 자로 표시된 필드를 유지하지 않습니다 . 테라코타는이 수정자를 존중합니다.
수정 자의 비유적인 의미는 "이 필드는 메모리 내에서만 사용하기위한 것입니다. 어떤 방식 으로든이 특정 VM 외부로 유지하거나 옮기지 마십시오. 이식성이 없습니다"라고 생각합니다. 즉, 다른 VM 메모리 공간에서 그 값에 의존 할 수 없습니다. 휘발성 과 매우 흡사 하다는 것은 특정 메모리 및 스레드 의미에 의존 할 수 없음을 의미합니다.
transient
현재 설계 되었다면 키워드가 아닐 것이라고 생각합니다 . 아마도 주석을 사용했을 것입니다.
이 질문에 답하기 전에 SERIALIZATION을 설명해야합니다 . 과학 컴퓨터에서 직렬화가 무엇을 의미하는지 이해하면이 키워드를 쉽게 이해할 수 있기 때문입니다.
직렬화
개체가 네트워크를 통해 전송되거나 실제 미디어 (파일, ...)에 저장된 경우 개체는 "직렬화"되어야합니다. 직렬화는 바이트 상태 객체 시리즈를 변환합니다. 이 바이트는 네트워크로 전송 / 저장되고 객체는이 바이트에서 다시 생성됩니다.
예
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
그렇지하려면 지금 TRANSFERT / 저장된 객체의 필드를 SO , 당신이 사용할 수있는 키워드 transient
private transient attr2;
직렬화와 관련된 중요한 데이터를 공유하지 않으려는 경우에 필요합니다.
Thread
(예를 들어 @AH로 신용 을) 직렬화하고 싶지 않을 것입니다 .이 경우 일시적으로 표시합니다. 그러나 스레드는 그 자체로 민감한 데이터가 아니며 직렬화하는 논리적 의미가 없으며 직렬화 할 수 없습니다.
간단히 말해서, 일시적인 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;
}
}
임시 키워드에 대한 간단한 예제 코드.
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);
}
}
@DoNotSerialize
입니까?