Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在构造函数中调用虚方法-更好的设计_Java_Oop_Design Patterns - Fatal编程技术网

Java 在构造函数中调用虚方法-更好的设计

Java 在构造函数中调用虚方法-更好的设计,java,oop,design-patterns,Java,Oop,Design Patterns,我用java声明了一个ISerializable接口 我基本上有两种方法:serialize(),和反序列化(byte[]buffer) 下面是一个实现此接口的类的示例: public class MySerializableClass implements ISerializable{ byte[] serialize(){bla bla} deserialize(byte[] buffer){bla bla}; } 理想情况下,我希望对deserialize的调用是隐

我用java声明了一个ISerializable接口

我基本上有两种方法:
serialize()
,和
反序列化(byte[]buffer)

下面是一个实现此接口的类的示例:

public class MySerializableClass implements ISerializable{   
    byte[] serialize(){bla bla}
    deserialize(byte[] buffer){bla bla};
}
理想情况下,我希望对
deserialize
的调用是隐式的。i、 e.当调用构造函数
MySerializableClass(byte[]buffer)
时,它将在传递缓冲区的情况下调用正确的
反序列化。就像这样:

public abstract class AbstractSerializable {
    public abstract byte[] serialize();
    public abstract void deserialize(byte[] buffer);
    public AbstractSerializable (){}
    public AbstractSerializable (byte[] buffer){
        deserialize();
    }
}

public class MySerializableClass extends AbstractSerializable {
    byte[] serialize(){bla bla}
    deserialize(byte[] buffer){bla bla};
}
AFAIK在构造函数中调用虚拟方法是有问题的,这可能会导致未定义的行为。 因此,目前,我正在做以下工作:

MySerializableClass myClass = new MySerializableClass();
myClass.deserialize(buffer);
或者使用为扩展接口的每个类定义的专用静态方法(基本上只需执行上述两行代码):

我的问题是:有没有一种优雅的方法可以做到这一点,而不需要为每个实现ISerializable的类定义一个专用的静态方法?有没有解决这个问题的设计模式


注意:我的序列化是唯一的,因此我需要自己编写,而且出于技术原因,我只能使用Java的非常基本的功能。(无注释、模板元数据等),因此我需要一个非常基本的OOP解决方案。

另一个解决方案是删除
无参数构造函数
,因此您的具体类必须使用参数构造函数初始化

我觉得您的解决方案足够优雅,您所做的是一个,这是解决您的问题的优雅方式。您可以将构造函数保持私有,并始终通过工厂检索对象

public class MySerializableClass extends AbstractSerializable {

    private MySerializableClass(){

    }

    public static MySerializableClass CreateMySerializableClass(final byte[] buffer){
        MySerializableClass result = new MySerializableClass();
        result.deserialize(buffer)
        return result;
    }

    byte[] serialize(){bla bla}

    deserialize(byte[] buffer){bla bla};
}

在进行序列化时,我不会传递字节数组,而是使用and。然后可以声明接口
ISerializable
,例如:

public interface ISerializable{   
    void serialize(DataOutput out) throws IOException;
    void deserialize(DataInput in) throws IOException;
}
然后,您可以提供静态实用程序方法,当提供一些DataOutput/DataInput时,这些方法能够序列化和反序列化
ISerializable
的实例。静态反序列化方法还可以调用可能的构造函数,该构造函数接受DataInput作为其唯一参数

以下是此方法的完整示例代码,其中还包括用于测试序列化的主要方法:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;


public class SerializableTest {

    public interface ISerializable{   
        void serialize(DataOutput out) throws IOException;
        void deserialize(DataInput in) throws IOException;
    }

    /**
     * Writes the given ISerializable to the given DataOutput.
     */
    public static void writeSerializable(ISerializable s, DataOutput out) throws IOException{
        writeClass(out, s.getClass());
        s.serialize(out);
    }

    /**
     * Reads an ISerializable from the given DataInput.
     */
    public static ISerializable readSerializable(DataInput in, ClassLoader cl) throws IOException{
        ISerializable element = null;
        Class<?> c;
        try {
            c = readClass(in, cl);
        } catch (ClassNotFoundException e) {
            throw new IOException(e);
        }
        try {
            try {
                // see if the class has a constructor that accepts a DataInput
                Constructor<?> constructor= c.getDeclaredConstructor(DataInput.class);
                constructor.setAccessible(true);
                return (ISerializable)constructor.newInstance(in);
            } catch (NoSuchMethodException e) {
                //ignore
            }
            element = (ISerializable) newInstance(c);
            element.deserialize(in);
        } catch (Exception e) {
            throw new IOException("Could not deserialize the class" + c.getName());
        }
        return element;

    }

    private static <T> T newInstance(Class<T> c) throws IOException {
        T element = null;
        Constructor<T> constructor;
        try {
            constructor = c.getDeclaredConstructor();
            if (!constructor.isAccessible()) {
                constructor.setAccessible(true);
            }
            element = constructor.newInstance();
        } catch (NoSuchMethodException | InstantiationException |
                IllegalAccessException | IllegalArgumentException | 
                InvocationTargetException e) {
                throw new IOException(e);
        }
        return element;
    }

    private static void writeClass(DataOutput out, Class<?> c) throws IOException {
        out.writeUTF(c.getName());
    }

    private static Class<?> readClass(DataInput in, ClassLoader cl) throws IOException, ClassNotFoundException {
        String name = in.readUTF();
        return cl.loadClass(name);
    }


    // some test classes for testing serialization in the main method

    public static class TestClass implements ISerializable{
        private String data;

        protected TestClass() {
            // ISerializable no argument constructor
            super();
        }

        public TestClass(String data) {
            super();
            this.data = data;
        }

        @Override
        public void serialize(DataOutput out) throws IOException {
            out.writeUTF(data);
        }

        @Override
        public void deserialize(DataInput in) throws IOException {
            this.data = in.readUTF();
        }
    }

    public static class TestClass2 implements ISerializable{
        private final String data;

        protected TestClass2(DataInput in) throws IOException {
            // ISerializable DataInput constructor
            super();
            this.data = in.readUTF();
        }

        public TestClass2(String data) {
            super();
            this.data = data;
        }

        @Override
        public void serialize(DataOutput out) throws IOException {
            out.writeUTF(data);
        }

        @Override
        public void deserialize(DataInput in) throws IOException {
            throw new UnsupportedOperationException();
        }
    }

    // tests serialization and deserialization of two test classes
    public static void main(String[] args) {
        TestClass t1 = new TestClass("TestClass 1");
        TestClass2 t2 = new TestClass2("TestClass 2");

        File file = new File("testfile");
        if (file.exists()) {
            file.delete();
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        DataOutputStream out = null;
        try {
            out  = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
            writeSerializable(t1, out);
            writeSerializable(t2, out);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }finally{
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {}
            }
        }

        DataInputStream in = null;
        try {
            in  = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
            ClassLoader cl = SerializableTest.class.getClassLoader();
            TestClass loadedClass1 = (TestClass) readSerializable(in, cl);
            TestClass2 loadedClass2 = (TestClass2) readSerializable(in, cl);

            System.out.println("loadedClass1.data: " + loadedClass1.data);
            System.out.println("loadedClass2.data: " + loadedClass2.data);

        } catch (IOException e) {
            e.printStackTrace();
            return;
        } finally{
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {}
            }
        }
    }
}
import java.io.BufferedInputStream;
导入java.io.BufferedOutputStream;
导入java.io.DataInput;
导入java.io.DataInputStream;
导入java.io.DataOutput;
导入java.io.DataOutputStream;
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.lang.reflect.Constructor;
导入java.lang.reflect.InvocationTargetException;
公共类SerializableTest{
公共接口ISerializable{
void序列化(DataOutput out)抛出IOException;
void反序列化(DataInput-in)抛出IOException;
}
/**
*将给定的ISerializable写入给定的DataOutput。
*/
公共静态void writeSerializable(ISerializable s,DataOutput out)引发IOException{
writeClass(out,s.getClass());
s、 序列化(输出);
}
/**
*从给定的数据输入读取ISerializable。
*/
公共静态ISerializable readSerializable(DataInput in,ClassLoader cl)引发IOException{
ISerializable元素=null;
丙级;;
试一试{
c=读级(in,cl);
}catch(classnotfounde异常){
抛出新的IOException(e);
}
试一试{
试一试{
//查看类是否具有接受数据输入的构造函数
构造函数=c.getDeclaredConstructor(DataInput.class);
constructor.setAccessible(true);
返回(ISerializable)构造函数.newInstance(in);
}捕获(无此方法例外){
//忽略
}
元素=(ISerializable)newInstance(c);
元素。反序列化(在中);
}捕获(例外e){
抛出新IOException(“无法反序列化类”+c.getName());
}
返回元素;
}
私有静态T newInstance(类c)引发IOException{
T元素=null;
建造师;
试一试{
构造函数=c.getDeclaredConstructor();
如果(!constructor.isAccessible()){
constructor.setAccessible(true);
}
element=constructor.newInstance();
}catch(NoSuchMethodException |实例化异常|
IllegalAccessException | IllegalArgumentException |
调用目标异常(e){
抛出新的IOException(e);
}
返回元素;
}
私有静态void writeClass(DataOutput out,类c)引发IOException{
writeUTF(c.getName());
}
私有静态类readClass(DataInput in,ClassLoader cl)引发IOException,ClassNotFoundException{
字符串名称=in.readUTF();
返回cl.loadClass(名称);
}
//在main方法中测试序列化的一些测试类
公共静态类TestClass实现ISerializable{
私有字符串数据;
受保护的TestClass(){
//ISerializable无参数构造函数
超级();
}
公共测试类(字符串数据){
超级();
这个数据=数据;
}
@凌驾
public void serialize(DataOutput out)引发IOException{
out.writeUTF(数据);
}
@凌驾
public void反序列化(DataInput in)引发IOException{
this.data=in.readUTF();
}
}
公共静态类TestClass2实现ISerializable{
私有最终字符串数据;
受保护的TestClass2(DataInput in)引发IOException{
//ISerializable数据输入构造函数
超级();
this.data=in.readUTF();
}
聚氨基甲酸酯
public interface ISerializable{   
    void serialize(DataOutput out) throws IOException;
    void deserialize(DataInput in) throws IOException;
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;


public class SerializableTest {

    public interface ISerializable{   
        void serialize(DataOutput out) throws IOException;
        void deserialize(DataInput in) throws IOException;
    }

    /**
     * Writes the given ISerializable to the given DataOutput.
     */
    public static void writeSerializable(ISerializable s, DataOutput out) throws IOException{
        writeClass(out, s.getClass());
        s.serialize(out);
    }

    /**
     * Reads an ISerializable from the given DataInput.
     */
    public static ISerializable readSerializable(DataInput in, ClassLoader cl) throws IOException{
        ISerializable element = null;
        Class<?> c;
        try {
            c = readClass(in, cl);
        } catch (ClassNotFoundException e) {
            throw new IOException(e);
        }
        try {
            try {
                // see if the class has a constructor that accepts a DataInput
                Constructor<?> constructor= c.getDeclaredConstructor(DataInput.class);
                constructor.setAccessible(true);
                return (ISerializable)constructor.newInstance(in);
            } catch (NoSuchMethodException e) {
                //ignore
            }
            element = (ISerializable) newInstance(c);
            element.deserialize(in);
        } catch (Exception e) {
            throw new IOException("Could not deserialize the class" + c.getName());
        }
        return element;

    }

    private static <T> T newInstance(Class<T> c) throws IOException {
        T element = null;
        Constructor<T> constructor;
        try {
            constructor = c.getDeclaredConstructor();
            if (!constructor.isAccessible()) {
                constructor.setAccessible(true);
            }
            element = constructor.newInstance();
        } catch (NoSuchMethodException | InstantiationException |
                IllegalAccessException | IllegalArgumentException | 
                InvocationTargetException e) {
                throw new IOException(e);
        }
        return element;
    }

    private static void writeClass(DataOutput out, Class<?> c) throws IOException {
        out.writeUTF(c.getName());
    }

    private static Class<?> readClass(DataInput in, ClassLoader cl) throws IOException, ClassNotFoundException {
        String name = in.readUTF();
        return cl.loadClass(name);
    }


    // some test classes for testing serialization in the main method

    public static class TestClass implements ISerializable{
        private String data;

        protected TestClass() {
            // ISerializable no argument constructor
            super();
        }

        public TestClass(String data) {
            super();
            this.data = data;
        }

        @Override
        public void serialize(DataOutput out) throws IOException {
            out.writeUTF(data);
        }

        @Override
        public void deserialize(DataInput in) throws IOException {
            this.data = in.readUTF();
        }
    }

    public static class TestClass2 implements ISerializable{
        private final String data;

        protected TestClass2(DataInput in) throws IOException {
            // ISerializable DataInput constructor
            super();
            this.data = in.readUTF();
        }

        public TestClass2(String data) {
            super();
            this.data = data;
        }

        @Override
        public void serialize(DataOutput out) throws IOException {
            out.writeUTF(data);
        }

        @Override
        public void deserialize(DataInput in) throws IOException {
            throw new UnsupportedOperationException();
        }
    }

    // tests serialization and deserialization of two test classes
    public static void main(String[] args) {
        TestClass t1 = new TestClass("TestClass 1");
        TestClass2 t2 = new TestClass2("TestClass 2");

        File file = new File("testfile");
        if (file.exists()) {
            file.delete();
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        DataOutputStream out = null;
        try {
            out  = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
            writeSerializable(t1, out);
            writeSerializable(t2, out);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }finally{
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {}
            }
        }

        DataInputStream in = null;
        try {
            in  = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
            ClassLoader cl = SerializableTest.class.getClassLoader();
            TestClass loadedClass1 = (TestClass) readSerializable(in, cl);
            TestClass2 loadedClass2 = (TestClass2) readSerializable(in, cl);

            System.out.println("loadedClass1.data: " + loadedClass1.data);
            System.out.println("loadedClass2.data: " + loadedClass2.data);

        } catch (IOException e) {
            e.printStackTrace();
            return;
        } finally{
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {}
            }
        }
    }
}
interface ISerializer
{
    byte[] serialize(ISerializable serializable);
    ISerializable deserialize(byte[] buffer);
}