programing

Java에서 Serializable과 Externalizable의 차이점은 무엇입니까?

javaba 2022. 8. 27. 21:57
반응형

Java에서 Serializable과 Externalizable의 차이점은 무엇입니까?

Java의 와의 차이점은 무엇입니까?

구현하여 다른 답변에 추가하려면java.io.Serializable클래스 오브젝트의 「자동」시리얼라이제이션 기능을 이용할 수 있습니다.하다을 사용하다Java 런타임은 리플렉션을 사용하여 오브젝트의 마샬링 및 마샬링 해제 방법을 결정합니다.

Java의 이전 버전에서는 리플렉션이 매우 느렸기 때문에 (클라이언트 서버 RMI 애플리케이션 등) 큰 객체 그래프를 시리얼화하는 것은 퍼포먼스의 문제가 있었습니다.하려면 , 「 」를 참조해 주세요.java.io.Externalizable은, 「이러다」와 것입니다.을 사용하다java.io.Serializable, 및 기능을 작성 (「」, 「마샬링」의 기능을 실장할 가 있습니다).readExternal ★★★★★★★★★★★★★★★★★」writeExternal메서드)를 사용합니다.이를 통해 반사 성능 병목 현상을 방지할 수 있습니다.

Java의 최신 버전(1.3 이상)에서는 리플렉션 성능이 이전보다 크게 향상되어 문제가 훨씬 적습니다.의미 것 같습니다.ExternalizableJVM을 사용하다

또한 내장된 Java 직렬화 메커니즘만 있는 것이 아닙니다. JBoss 직렬화 등의 타사 대체품을 얻을 수 있습니다. JBoss 직렬화는 훨씬 빠르고 기본 대체품입니다.

★★★★의 큰 Externalizable 할 , 를 변경해야 .writeExternal/readExternal설명 방법을 참조하십시오.

「」입니다.ExternalizableJava 1.1 의의의다다 。더 이상 그럴 필요 없어요.

직렬화는 개체를 저장하고 나중에 다시 생성하는 기본 기능을 제공합니다.예를 들어 linkedList가 있고 다음과 같이 코드화한다고 가정하면 디폴트시리얼라이제이션에서는 링크되어 시리얼화되는 모든 오브젝트가 검출됩니다.디폴트 시리얼라이제이션에서는 오브젝트는 컨스트럭터 호출 없이 완전히 저장된 비트로 구성됩니다.

  ObjectOutputStream oos = new ObjectOutputStream(
      new FileOutputStream("/Users/Desktop/files/temp.txt"));
  oos.writeObject(linkedListHead); //writing head of linked list
  oos.close();

그러나 제한된 직렬화를 원하거나 개체의 일부를 직렬화하지 않으려면 Externalizable을 사용하십시오.Externalizable 인터페이스는 Serializable 인터페이스를 확장하고 쓰기라는 두 가지 방법을 추가합니다.External() 및 readExternal()입니다.이것들은, 시리얼화 또는 역직렬화중에 자동적으로 호출됩니다.Externalizable을 사용하는 동안 기본 생성자는 public이어야 합니다.그렇지 않으면 코드가 예외를 발생시킵니다.다음 코드를 따르십시오.

public class MyExternalizable implements Externalizable
{

private String userName;
private String passWord;
private Integer roll;

public MyExternalizable()
{
}

public MyExternalizable(String userName, String passWord, Integer roll)
{
    this.userName = userName;
    this.passWord = passWord;
    this.roll = roll;
}

@Override
public void writeExternal(ObjectOutput oo) throws IOException 
{
    oo.writeObject(userName);
    oo.writeObject(roll);
}

@Override
public void readExternal(ObjectInput oi) throws IOException, ClassNotFoundException 
{
    userName = (String)oi.readObject();
    roll = (Integer)oi.readObject();
}

public String toString()
{
    StringBuilder b = new StringBuilder();
    b.append("userName: ");
    b.append(userName);
    b.append("  passWord: ");
    b.append(passWord);
    b.append("  roll: ");
    b.append(roll);
   
    return b.toString();
}
public static void main(String[] args)
{
    try
    {
        MyExternalizable m  = new MyExternalizable("nikki", "student001", 20);
        System.out.println(m.toString());
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/Desktop/files/temp1.txt"));
        oos.writeObject(m);
        oos.close();
        
        System.out.println("***********************************************************************");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/Desktop/files/temp1.txt"));
        MyExternalizable mm = (MyExternalizable)ois.readObject();
        mm.toString();
        System.out.println(mm.toString());
    } 
    catch (ClassNotFoundException ex) 
    {
        Logger.getLogger(MyExternalizable.class.getName()).log(Level.SEVERE, null, ex);
    }
    catch(IOException ex)
    {
        Logger.getLogger(MyExternalizable.class.getName()).log(Level.SEVERE, null, ex);
    }
}
}

여기서 기본 생성자에 주석을 달면 코드는 다음과 같은 예외를 발생시킵니다.

 java.io.InvalidClassException: javaserialization.MyExternalizable;     
 javaserialization.MyExternalizable; no valid constructor.

패스워드는 기밀정보이므로 서면으로 연재하지 않습니다.External(ObjectOutput OO) 메서드로 readExternal(ObjectInput oi)에서 동일한 값을 설정하지 않았습니다.이것이 바로 Externalizable이 제공하는 유연성입니다.

상기 코드의 출력은 다음과 같습니다.

userName: nikki  passWord: student001  roll: 20
***********************************************************************
userName: nikki  passWord: null  roll: 20

passWord의 값을 설정하지 않았기 때문에 null로 할 수 있습니다.

비밀번호 필드를 임시로 선언하는 경우에도 마찬가지입니다.

private transient String passWord;

도움이 됐으면 좋겠다.제가 실수를 했다면 사과드립니다.고마워요.

「 」의 Serializable ★★★★★★★★★★★★★★★★★」Externalizable

  1. 마커 인터페이스:Serializable메메가없없없없없없없마마마마Externalizable에는 interface の 음음음음 の : methods methods methods의 두 메서드가 .writeExternal() ★★★★★★★★★★★★★★★★★」readExternal().
  2. 시리얼화 프로세스:디폴트 시리얼라이제이션프로세스는 구현된 클래스에 대해 킥인됩니다.Serializable인터페이스입니다.는, 「Serialization Process」를 실장하는 킥 인 .Externalizable인터페이스입니다.
  3. 유지 보수:호환되지 않는 변경으로 인해 일련화가 중단될 수 있습니다.
  4. 하위 호환성제어:여러 버전을 지원해야 하는 경우,Externalizable인터페이스입니다.다양한 버전의 개체를 지원할 수 있습니다.「 」를 실장했을 Externalizable하는 것은super 표시
  5. 퍼블릭 비아그 컨스트럭터:Serializable는 리플렉션을 사용하여 객체를 생성하며 arg 컨스트럭터가 필요하지 않습니다. ★★★★★★★★★★★★★★★★★.Externalizable공공 건설업자를 필요로 합니다.

블로그 참조:Hitesh Garg세한것 、 을을해해요요 。

직렬화는 특정 기본 동작을 사용하여 개체를 저장하고 나중에 다시 생성합니다.참조 및 복잡한 데이터 구조를 처리하는 순서 또는 방법을 지정할 수 있지만, 결국 각 원시 데이터 필드에 대해 기본 동작을 사용해야 합니다.

외부화는 데이터 필드의 기본 직렬화 메커니즘을 사용하지 않고 완전히 다른 방식으로 개체를 저장하고 재구축하려는 드문 경우에 사용됩니다.예를 들어 고유한 인코딩 및 압축 방식이 있다고 가정합니다.

오브젝트 시리얼화는 Serializable 인터페이스와 Externalizable 인터페이스를 사용합니다.Java 객체는 클래스 또는 해당 슈퍼클래스가 java.io 중 하나를 구현하는 경우에만 직렬화할 수 있습니다.시리얼 대응 인터페이스 또는 그 서브 인터페이스(java.io).외장 가능.대부분의 Java 클래스는 직렬화할 수 있습니다.

  • : § 클래스 오브젝트를 시리얼화 프로세스에 참여시키려면 클래스는 Serializable 또는 Externalizable 인터페이스를 구현해야 합니다NotSerializableException.

여기에 이미지 설명 입력


시리얼 가능한 인터페이스

개체 직렬화는 저장 중인 개체의 Java 클래스에 대한 정보를 포함하는 스트림을 생성합니다.시리얼 가능한 객체의 경우 클래스 구현의 다른 버전(호환성이 있는)이 존재하는 경우에도 이러한 객체를 복원하기에 충분한 정보가 유지됩니다.Serializable 인터페이스는 Serializable 프로토콜을 구현하는 클래스를 식별하기 위해 정의됩니다.

package java.io;

public interface Serializable {};
  • 시리얼라이제이션인터페이스에는 메서드나 필드가 없으며 시리얼라이제이션이 가능한 의미만을 식별하기 위한 것입니다.클래스를 시리얼화/비직렬화하려면 기본 writeObject 메서드와 readObject 메서드를 사용하거나 클래스에서 writeObject 메서드와 readObject 메서드를 덮어쓸 수 있습니다.
  • JVM은 오브젝트의 시리얼화를 완전하게 제어할 수 있습니다.데이터 멤버가 시리얼화되지 않도록 하려면 transient 키워드를 사용합니다.
  • 여기서 직렬화 가능한 개체는 실행하지 않고 스트림에서 직접 재구성됩니다.
  • InvalidClassException § 디시리얼라이제이션프로세스에서 로컬클래스 serialVersion의 경우UID 값이 해당 발송인 클래스와 다릅니다.결과적으로 갈등하게 된다java.io.InvalidClassException: com.github.objects.User; local class incompatible: stream classdesc serialVersionUID = 5081877, local class serialVersionUID = 50818771
  • 클래스의 비가변 필드 및 비정적 필드의 값이 직렬화됩니다.

외부 대응 인터페이스

Externalizable 객체의 경우 객체의 클래스의 ID만 컨테이너에 저장됩니다.클래스는 내용을 저장하고 복원해야 합니다.Externalizable 인터페이스는 다음과 같이 정의됩니다.

package java.io;

public interface Externalizable extends Serializable
{
    public void writeExternal(ObjectOutput out)
        throws IOException;

    public void readExternal(ObjectInput in)
        throws IOException, java.lang.ClassNotFoundException;
}
  • Externalizable 인터페이스에는 두 가지 메서드가 있습니다. Externalizable 객체는 쓰기를 구현해야 합니다.External 메서드 및 readExternal 메서드를 사용하여 오브젝트 상태를 저장/복원합니다.
  • 프로그래머는 어떤 오브젝트를 연속화할지를 처리해야 합니다.프로그래머가 시리얼라이제이션에 주의하기 때문에 여기서 transient 키워드는 시리얼라이제이션프로세스의 오브젝트를 제한하지 않습니다.
  • Externalable 객체가 재구성되면 퍼블릭 no-arg 생성자를 사용하여 인스턴스가 생성되고 readExternal 메서드가 호출됩니다.직렬화 가능한 개체는 ObjectInputStream에서 읽으면 복원됩니다.
  • OptionalDataException § 필드는 기재한 순서와 타입이 같아야 합니다.스트림에서 유형이 일치하지 않으면 OptionalDataException이 느려집니다.

    @Override public void writeExternal(ObjectOutput out) throws IOException {
        out.writeInt( id );
        out.writeUTF( role );
        out.writeObject(address);
    }
    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.id = in.readInt();
        this.address = (Address) in.readObject();
        this.role = in.readUTF();
    }
    
  • 에 기입(표시)한 클래스의 인스턴스 필드ObjectOutput재되되


: 시리얼 가능 구현

class Role {
    String role;
}
class User extends Role implements Serializable {

    private static final long serialVersionUID = 5081877L;
    Integer id;
    Address address;

    public User() {
        System.out.println("Default Constructor get executed.");
    }
    public User( String role ) {
        this.role = role;
        System.out.println("Parametarised Constructor.");
    }
}

class Address implements Serializable {

    private static final long serialVersionUID = 5081877L;
    String country;
}

imp 외부 대응 구현

class User extends Role implements Externalizable {

    Integer id;
    Address address;
    // mandatory public no-arg constructor
    public User() {
        System.out.println("Default Constructor get executed.");
    }
    public User( String role ) {
        this.role = role;
        System.out.println("Parametarised Constructor.");
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeInt( id );
        out.writeUTF( role );
        out.writeObject(address);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.id = in.readInt();
        this.address = (Address) in.readObject();
        this.role = in.readUTF();
    }
}

public class CustomClass_Serialization {
    static String serFilename = "D:/serializable_CustomClass.ser";

    public static void main(String[] args) throws IOException {
        Address add = new Address();
        add.country = "IND";

        User obj = new User("SE");
        obj.id = 7;
        obj.address = add;

        // Serialization
        objects_serialize(obj, serFilename);
        objects_deserialize(obj, serFilename);

        // Externalization
        objects_WriteRead_External(obj, serFilename);
    }

    public static void objects_serialize( User obj, String serFilename ) throws IOException{
        FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );

        // java.io.NotSerializableException: com.github.objects.Address
        objectOut.writeObject( obj );
        objectOut.flush();
        objectOut.close();
        fos.close();

        System.out.println("Data Stored in to a file");
    }
    public static void objects_deserialize( User obj, String serFilename ) throws IOException{
        try {
            FileInputStream fis = new FileInputStream( new File( serFilename ) );
            ObjectInputStream ois = new ObjectInputStream( fis );
            Object readObject;
            readObject = ois.readObject();
            String calssName = readObject.getClass().getName();
            System.out.println("Restoring Class Name : "+ calssName); // InvalidClassException

            User user = (User) readObject;
            System.out.format("Obj[Id:%d, Role:%s] \n", user.id, user.role);

            Address add = (Address) user.address;
            System.out.println("Inner Obj : "+ add.country );
            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void objects_WriteRead_External( User obj, String serFilename ) throws IOException {
        FileOutputStream fos = new FileOutputStream(new File( serFilename ));
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );

        obj.writeExternal( objectOut );
        objectOut.flush();

        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            // create a new instance and read the assign the contents from stream.
            User user = new User();

            FileInputStream fis = new FileInputStream(new File( serFilename ));
            ObjectInputStream ois = new ObjectInputStream( fis );

            user.readExternal(ois);

            System.out.format("Obj[Id:%d, Role:%s] \n", user.id, user.role);

            Address add = (Address) user.address;
            System.out.println("Inner Obj : "+ add.country );
            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

@ 참조

Externalizable 인터페이스는 실제로는 시리얼라이제이션 프로세스의 퍼포먼스를 최적화하기 위해 제공된 것이 아니라 사용자 고유의 커스텀 처리를 구현하고 객체 및 그 슈퍼타입의 스트림 형식과 내용을 완전히 제어할 수 있도록 하기 위해 제공되었습니다.

예를 들어 네트워크상에서 네이티브액션스크립트 오브젝트를 전송하기 위한 AMF(ActionScript Message Format) 리모트 구현이 있습니다.

https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html

디폴트 시리얼라이제이션은 다소 상세하고 시리얼라이제이션오브젝트의 가능한 한 광범위한 사용 시나리오를 상정하고 있습니다.따라서 디폴트 포맷(시리얼라이제이션 가능)은 결과 스트림에 시리얼라이제이션오브젝트의 클래스에 관한 정보를 부가합니다.

외부화를 통해 오브젝트 스트림의 생산자는 클래스의 최소한의 필수 식별(예를 들어 이름)을 넘어 정밀한 클래스 메타 데이터(있는 경우)를 완전히 제어할 수 있습니다.이는 객체 스트림의 생산자와 그 소비자(스트림에서 객체를 재현하는)가 일치하고 클래스에 대한 추가 메타데이터가 아무런 목적도 제공하지 않고 성능을 저하시키는 폐쇄 환경 등 특정 상황에서 분명히 바람직합니다.

또한 (URI가 지적한 바와 같이) 외부화를 통해 Java 유형에 대응하는 스트림 내의 데이터 인코딩을 완전히 제어할 수 있습니다.(조작된) 예에서는 부울 true를 'Y'로, false를 'N'으로 기록할 수 있습니다.외부화를 사용하면 그렇게 할 수 있습니다.

퍼포먼스 향상을 위한 옵션을 검토할 때는 커스텀 시리얼화를 잊지 마십시오.Java가 잘하거나 적어도 충분히 좋은 작업을 무료로 수행하도록 할 수 있으며, 잘못된 작업에 대한 사용자 지정 지원을 제공할 수 있습니다.이것은 일반적으로 완전한 외부 지원보다 훨씬 적은 코드입니다.

많은 차이 Serializable과 Externalizable 사이에서 존재하지만 우리가 사용자 지정 Serializable(overrided writeObject()및 차이점을 비교, readObject()cm이고Externalizable 있다면 사용자 지정 구현하게 어디서Externalizable 경우처럼, 나 자신을 우리는 implementat을 제공한다 ObjectOutputStream 클래스와 함께 bind 것을 발견하게 됩니다.이온ObjectOutputStream 클래스 또는 org.apache.mina.filter.codec과 같은 다른 클래스일 수 있습니다.시리얼화오브젝트 시리얼화출력 스트림

외부 지원 인터페이스의 경우

@Override
public void writeExternal(ObjectOutput out) throws IOException {
    out.writeUTF(key);
    out.writeUTF(value);
    out.writeObject(emp);
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    this.key = in.readUTF();
    this.value = in.readUTF();
    this.emp = (Employee) in.readObject();
}





**In case of Serializable interface**


        /* 
             We can comment below two method and use default serialization process as well
             Sequence of class attributes in read and write methods MUST BE same.
        // below will not work it will not work . 
        // Exception = java.io.StreamCorruptedException: invalid type code: 00\
              private void writeObject(java.io.ObjectOutput stream) 
              */
            private void writeObject(java.io.ObjectOutputStream Outstream)
                    throws IOException {

                System.out.println("from writeObject()");
                /*     We can define custom validation or business rules inside read/write methods.
 This way our validation methods will be automatically 
    called by JVM, immediately after default serialization 
    and deserialization process 
    happens.
                 checkTestInfo();
                */

                stream.writeUTF(name);
                stream.writeInt(age);
                stream.writeObject(salary);
                stream.writeObject(address);
            }

            private void readObject(java.io.ObjectInputStream Instream)
                    throws IOException, ClassNotFoundException {
                System.out.println("from readObject()");
                name = (String) stream.readUTF();
                age = stream.readInt();
                salary = (BigDecimal) stream.readObject();
                address = (Address) stream.readObject();
                // validateTestInfo();
            }

더 잘 설명하기 위해 샘플 코드를 추가했습니다.외부화 가능 '/외부 대응 가능.이것들은, 어떠한 실장에도 직접 구속되지 않습니다.
Outstream/Instream을 사용합니다.Object Output Stream / Object Input Stream 을 object 。

으로는 ★★★★★★★★★★★★★★★★★」Serializable는 클래스가 시리얼라이제이션에 안전함을 나타내는 마커 인터페이스로, JVM이 시리얼라이제이션 방법을 결정합니다. Externalizable에는 2가지 즉 2가지 방법이 .readExternal ★★★★★★★★★★★★★★★★★」writeExternalExternalizable할 수 서는 오브젝트의 시리얼화 방법을 지정합니다.Serializable는 오브젝트를 디폴트 방식으로 시리얼화합니다.

몇 가지 차이점:

  1. 직렬화의 경우 JVM이 Reflection API를 사용하여 동일한 개체를 구성하기 때문에 해당 클래스의 기본 생성자가 필요하지 않습니다.arg가 없는 Externalization 컨스트럭터가 필요한 경우, 컨트롤은 programmar가 담당하며 나중에 setters를 통해 deserialized data를 객체에 할당하기 때문입니다.

  2. 시리얼라이제이션에서 사용자가 시리얼라이제이션할 특정 속성을 건너뛸 경우 해당 속성을 일시적 속성으로 표시해야 합니다.외부화에는 그 반대가 필요하지 않습니다.

  3. 어떤 클래스에 대해서도 하위 호환성이 지원되어야 할 경우 Externalizable을 선택하는 것이 좋습니다.직렬화는 defaultObject 지속을 지원하며 개체 구조가 손상된 경우 직렬 해제 중에 문제가 발생합니다.

언급URL : https://stackoverflow.com/questions/817853/what-is-the-difference-between-serializable-and-externalizable-in-java

반응형