Любой вариант использования, который может быть разрешен только с помощью Externalizable и не может быть разрешен с помощью Serializable и наоборот [duplicate]

Название функции ужасно, и код был быстро создан, но он должен работать. Обратите внимание, что это изменяет исходный объект, я не уверен, что вы хотите создать новый объект, который является расширенной версией старого.

(function(){

    function parseDotNotation( str, val, obj ){
    var currentObj = obj,
        keys = str.split("."), i, l = keys.length - 1, key;

        for( i = 0; i < l; ++i ) {
        key = keys[i];
        currentObj[key] = currentObj[key] || {};
        currentObj = currentObj[key];
        }

    currentObj[keys[i]] = val;
    delete obj[str];
    }

    Object.expand = function( obj ) {

        for( var key in obj ) {
        parseDotNotation( key, obj[key], obj );
        }
    return obj;
    };

})();



var expanded = Object.expand({
    'ab.cd.e' : 'foo',
        'ab.cd.f' : 'bar',
    'ab.g' : 'foo2'
});



JSON.stringify( expanded );  


//"{"ab":{"cd":{"e":"foo","f":"bar"},"g":"foo2"}}"
254
задан Michael Myers 4 May 2009 в 15:56
поделиться

9 ответов

Интерфейс Externalizable фактически не предоставлялся для оптимизации производительности процесса сериализации! но для предоставления средств для реализации собственной пользовательской обработки и обеспечения полного контроля над форматом и содержимым потока для объекта и его супер-типов!

Примерами этого является реализация AMF (ActionScript Message Format) удалять для передачи собственных объектов сценария действия по сети.

6
ответ дан Ali Joudeh 27 August 2018 в 18:10
поделиться

Существует так много различий между Serializable и Externalizable, но когда мы сравниваем разницу между пользовательскими Serializable (overrided writeObject () & amp; readObject ()) и Externalizable, тогда мы обнаруживаем, что пользовательская реализация тесно связана с классом ObjectOutputStream, где, как и в Externalizable case, мы сами обеспечиваем реализацию ObjectOutput, которая может быть классом ObjectOutputStream или может быть другим, например org.apache.mina.filter.codec.serialization.ObjectSerializationOutputStream

В случае интерфейса Externalizable

@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();
            }

Я добавил пример кода, чтобы лучше объяснить. пожалуйста, проверьте в / из объекта случай Externalizable. Они не связаны с какой-либо реализацией напрямую. Где, поскольку Outstream / Instream тесно связаны с классами. Мы можем расширять ObjectOutputStream / ObjectInputStream, но это будет немного сложно использовать.

1
ответ дан Ashish Sharma 27 August 2018 в 18:10
поделиться
  • 1
    Не могли бы вы рассказать о нем больше? Когда я прочитал это, я не понимаю, что вы пытаетесь сказать. Кроме того, если вы можете отформатировать текст с некоторыми параграфами и примерами, это может быть отличным ответом. – Shirkam 11 October 2017 в 10:56

Чтобы добавить к другим ответам, реализовав java.io.Serializable, вы получаете возможность «автоматической» сериализации для объектов вашего класса. Нет необходимости реализовывать какую-либо другую логику, она будет работать. Java-среда выполнения использует рефлексию для определения того, как маршалировать и де-маршалировать ваши объекты.

В более ранней версии Java отражение было очень медленным, и поэтому сериализация крупных графиков объектов (например, в клиент-серверных приложениях RMI) было немного проблем с производительностью. Чтобы справиться с этой ситуацией, был предоставлен интерфейс java.io.Externalizable, который похож на java.io.Serializable, но с настраиваемыми механизмами для выполнения функций маршаллинга и развязывания (вам нужно реализовать методы readExternal и writeExternal в вашем классе). Это дает вам возможность обойти узкое место производительности отражения.

В последних версиях Java (начиная с версии 1.3, конечно) производительность отражения намного лучше, чем раньше, и поэтому это гораздо менее проблематично. Я подозреваю, что вам будет трудно получить значимую выгоду от Externalizable с современной JVM.

Кроме того, встроенный механизм сериализации Java не является единственным, вы можете получить сторонние замены, такие как JBoss Serialization, что значительно быстрее и является заменой для замены default.

Большой недостаток Externalizable заключается в том, что вы должны сами поддерживать эту логику - если вы добавляете, удаляете или изменяете поле в своем классе, вы должны изменить свой writeExternal / readExternal методы для его учета.

Таким образом, Externalizable является реликвией Java 1.1 дней. В этом нет необходимости.

246
ответ дан Craig P. Motlin 27 August 2018 в 18:10
поделиться
  • 1
    Не в соответствии с этими критериями: [ code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking] , ручная сериализация (с использованием externizable) намного, намного быстрее, чем использование сериализации по умолчанию Java. Если скорость имеет значение для вашей работы, определенно напишите свой собственный сериализатор. – volni 12 December 2010 в 16:53
  • 2
    обновление до новой ссылки github.com/eishay/jvm-serializers/wiki , предложенной @Jack – noquery 18 June 2011 в 18:18
  • 3
    "Java-manual" в github.com/eishay/jvm-serializers/wiki использует not использование Externalizable, что подразумевает использование ObjectOutputStream. См. github.com/eishay/jvm-serializers/wiki/ToolBehavior для ссылки на код. Вместо этого это рукописный код, который использует DataOutputStream, поэтому он не страдает от вещей, которые делают ObjectOutputStream медленными (например, отслеживание экземпляров объектов и поддерживающих циклов объектов). – Esko Luontola 23 May 2012 в 22:56
  • 4
    Почему я не могу дать ответы на подобные вопросы в Джавадоке? – Phillip 9 May 2013 в 20:13
  • 5
    Необходимость поддерживать логику - это только недостаток, если класс никогда не меняется, и вам никогда не придется читать в старых версиях старых данных. Если вы хотите изменить свой класс без необходимости писать адский код для десериализации старых версий, Externalizable помогает много . – Tim Boudreau 28 August 2013 в 22:56

При рассмотрении вариантов повышения производительности не забывайте о специальной сериализации. Вы можете позволить Java делать то, что она делает хорошо или, по крайней мере, достаточно хорошо, бесплатно , и предоставлять пользовательскую поддержку для того, что она делает плохо. Обычно это намного меньше кода, чем полная поддержка Externalizable.

1
ответ дан Ed Staub 27 August 2018 в 18:10
поделиться

Сериализация предоставляет функции по умолчанию для хранения и последующего воссоздания объекта. Он использует подробный формат для определения всего графика объектов, которые нужно сохранить, например. предположим, что у вас есть связанныйList, и вы код, как показано ниже, то сериализация по умолчанию обнаружит все объекты, которые связаны и будут сериализованы. В сериализации по умолчанию объект полностью построен из его сохраненных битов без вызовов конструктора.

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

Но если вы хотите ограничить сериализацию или не хотите, чтобы часть вашего объекта была сериализована, используйте Externalizable , Интерфейс Externalizable расширяет интерфейс Serializable и добавляет два метода: writeExternal () и readExternal (). Они автоматически вызывается при сериализации или десериализации. Во время работы с Externalizable мы должны помнить, что конструктор по умолчанию должен быть открытым, иначе код будет генерировать исключение. Пожалуйста, следуйте приведенному ниже коду:

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.

Мы можем наблюдать, что пароль является конфиденциальной информацией , поэтому я не сериализую его в методе writeExternal (ObjectOutput oo) и не устанавливаю его значение в readExternal (ObjectInput oi). Это гибкость, предоставляемая Externalizable.

Вывод вышеуказанного кода приведен ниже:

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

Мы можем наблюдать, поскольку мы не устанавливаем значение passWord так, чтобы оно было нулевым.

То же самое можно достичь, объявив поле пароля как переходное.

private transient String passWord;

Надеюсь, что это поможет. Прошу прощения, если я допустил ошибки. Спасибо.

31
ответ дан feeling unwelcome 27 August 2018 в 18:10
поделиться

Просто для полноты ключевое слово transient также закрывает промежуток между ними.

Если вы хотите сериализовать часть своего объекта, просто установите определенные поля как transient, отметив их как не сохраняемые, и реализуйте Serializable.

23
ответ дан Petr Janeček 27 August 2018 в 18:10
поделиться

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

Сериализация по умолчанию несколько многословна и предполагает максимально возможный сценарий использования сериализованного объекта, и, соответственно, формат по умолчанию (Serializable) аннотирует результирующий поток с информацией о классе сериализованного объекта.

Внешняя подача дает разработчику полный поток объектов точные метаданные класса (если таковые имеются) за минимально необходимой идентификацией класса (например, его имя). Это явно желательно в определенных ситуациях, таких как закрытые среды, в которых сопоставляются производитель потока объектов и его потребителя (который подтверждает объект из потока), а дополнительные метаданные о классе не имеют никакой цели и ухудшают производительность.

Дополнительно (как указано Uri) экстернализация также обеспечивает полный контроль над кодированием данных в потоке, соответствующем типам Java. Для (надуманного) примера вы можете записать логическое значение true, как «Y», а false - «N». Вы можете сделать это вовне.

18
ответ дан Ravindra babu 27 August 2018 в 18:10
поделиться
  • 1
    (3) неверно. Существует большой репертуар изменений, которые вы можете внести в класс, не нарушая де-сериализации существующих объектов, и, конечно же, одним из них является добавление сериализуемых элементов. Удаление их - другое. См. Главу Object Versioning Спецификация сериализации объектов Java. – user207421 15 September 2017 в 05:51
  • 2
    Повторное предложение. – Ravindra babu 15 September 2017 в 16:21

Сериализация использует определенное поведение по умолчанию для хранения и последующего воссоздания объекта. Вы можете указать, в каком порядке или как обрабатывать ссылки и сложные структуры данных, но в конечном итоге это сводится к использованию поведения по умолчанию для каждого примитивного поля данных.

Экстернализация используется в редких случаях, которые вы действительно хотите для хранения и восстановления вашего объекта совершенно по-другому и без использования механизмов сериализации по умолчанию для полей данных. Например, представьте, что у вас есть своя уникальная схема кодирования и сжатия.

18
ответ дан Uri 27 August 2018 в 18:10
поделиться
  • 1
    Мы использовали Externalizable для больших наборов «выбранных идентификаторов». - это было гораздо более эффективным внешним, поскольку более или менее счетчик и amp; массив примитивных ints, чем сериализация по умолчанию. Это очень простая утилита, ничего «особенного». или "уникальный". – Thomas W 1 September 2013 в 00:57

Сериализация объектов использует интерфейсы Serializable и Externalizable. Объект Java является сериализуемым. если класс или любой из его суперклассов реализует либо интерфейс java.io.Serializable, либо его подчиненный интерфейс, java.io.Externalizable. Большая часть класса java является сериализуемым .

  • NotSerializableException : packageName.ClassName «Чтобы принять участие в Объект класса в процессе сериализации. Класс должен реализовывать интерфейс Serializable или Externalizable.


Последовательный интерфейс

Сериализация объекта создает поток с информацией о классах Java для сохраняемых объектов. Для сериализуемых объектов сохраняется достаточная информация для восстановления этих объектов, даже если присутствует другая (но совместимая) версия реализации класса. Интерфейс Serializable определен для идентификации классов, которые реализуют сериализуемый протокол:

package java.io;

public interface Serializable {};
  • Интерфейс сериализации не имеет методов или полей и служит только для идентификации семантики сериализации. Для сериализации / десериализации класса мы можем использовать методы writeObject по умолчанию и методы readObject (или), мы можем переопределять методы writeObject и readObject из класса.
  • JVM будет иметь полный контроль над сериализацией объекта. используйте ключевое слово переходного процесса , чтобы предотвратить сериализацию члена данных.
  • Здесь сериализуемые объекты восстанавливаются непосредственно из потока без выполнения
  • InvalidClassException «В процессе десериализации, если значение локального класса serialVersionUID отличается от соответствующего класса отправителя. то результат конфликтует как java.io.InvalidClassException: com.github.objects.User; local class incompatible: stream classdesc serialVersionUID = 5081877, local class serialVersionUID = 50818771
  • Значения непереходных и нестатических полей класса становятся сериализованными.

Интерфейс внешнего управления

Для объектов Externalizable в контейнере сохраняется только идентификатор класса объекта; класс должен сохранять и восстанавливать содержимое. Интерфейс 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 имеет два метода: внешний объект должен реализовывать методы writeExternal и readExternal для сохранения / восстановления состояния объекта.
  • Программист должен заботиться о том, какие объекты должны быть сериализованы. Как программист позаботится о сериализации Итак, ключевое слово transient не будет ограничивать какой-либо объект в процессе Serialization.
  • Когда объект Externalizable восстанавливается, экземпляр создается с использованием конструктора public no-arg, затем readExternal вызванный метод. Сериализуемые объекты восстанавливаются путем чтения их из ObjectInputStream.
  • OptionalDataException «Поля ДОЛЖНЫ БЫТЬ В ОДНОМ ЗАКАЗЕ И ТИПЕ , как мы их написали вне. Если в потоке есть какое-то несоответствие типа, это генерирует Необязательное исключение DataDataException.
    @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, сериализуются.

Пример «Реализует Serializable

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;
}

Пример « реализует Externalizable

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();
        }
    }
}

@see

6
ответ дан Yash 27 August 2018 в 18:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: