Есть ли способ отправить экземпляры разных подклассов сериализуемого класса? - PullRequest
1 голос
/ 08 мая 2019

Я создал клиент-серверное приложение с работающей настройкой и обработкой соединения.Я хотел бы, чтобы клиент отправлял запросы разных типов, каждый с уникальными полями, но все они наследуются от суперкласса «Запрос».Есть ли способ сделать это?

Например, у меня есть класс Foo, который реализует сериализуемый

class Foo implements Serializable{

public String name;

public Foo() {
    this.name = "Default";
}

public Foo(String name) {
    this.name = name;
}
}

и два подкласса, которые расширяют его

class BarOne extends Foo {

public String name;
public int id;

public Bar(String name, int id) {
    super(name);
    this.id = id;
}
}

class BarTwo extends Foo {

public String name;
public String lastName;

public Bar(String name, String lastName) {
    super(name);
    this.lastName = lastName;
}
}

Есть ли способ, чтобы клиент отправлял экземпляры BarOne и BarTwo через ObjectOutputStream и заставлял сервер выяснять, является ли то, что он получает, экземпляром одного или другого?

1 Ответ

1 голос
/ 08 мая 2019

Здесь нет никаких ограничений, вы можете без затруднений сериализовать подкласс.

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

Абстрактный класс.

public abstract class Pojo implements Serializable {

    private static final long serialVersionUID = -4947411931465651278L;

    protected int id;

    public Pojo() {
        // TODO Auto-generated constructor stub
    }

    public Pojo(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

Первый подкласс Person

class Person extends Pojo {

    private static final long serialVersionUID = -7814628079202659483L;

    private String name;
    private int age;

    public Person(int id, String name, int age) {
        super(id);
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", id=" + id + "]";
    }
}

Второй подкласс Address

class Address extends Pojo {

    private static final long serialVersionUID = -8266402026827561883L;

    private String address;
    private String city;

    public Address(int id, String address, String city) {
        super(id);
        this.address = address;
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address [address=" + address + ", city=" + city + ", id=" + id
                + "]";
    }
}

Затем можно создать коллекцию дляэтот пример, который будет содержать оба типа экземпляра:

List<Pojo> pojos = new ArrayList<>();
pojos.add(new Address(1, "Address 1", "city1"));
pojos.add(new Address(2, "Address 2", "city2"));
pojos.add(new Person(1, "Name1", 5));
pojos.add(new Person(2, "Name2", 10));
pojos.add(new Person(3, "Name3", 15));

Вы можете использовать файл для сериализации (потому что у меня нет времени на создание системы сокетов;)), используя:

private static void serialize(String filename, Serializable data)
        throws IOException {
    try (OutputStream outStream = new FileOutputStream(filename);
            ObjectOutputStream fileObjectOut = new ObjectOutputStream(
                    outStream)) {
        fileObjectOut.writeObject(data);
    }
}

private static Object deserialize(String filename) throws IOException,
        ClassNotFoundException {
    try (InputStream inStream = new FileInputStream(filename);
            ObjectInputStream fileObjectIn = new ObjectInputStream(inStream)) {
        return fileObjectIn.readObject();
    }
}

Позвольте сериализовать и десериализовать список, чтобы увидеть, будет ли восстановлен тип:

serialize("data.ser", pojos);
List<Pojo> tmp = deserialize("data.ser");
System.out.println(tmp);

И вы увидите результат с правильным типом экземпляра:

[
    Address [address=Address 1, city=city1, id=1], 
    Address [address=Address 2, city=city2, id=2], 
    Person [name=Name1, age=5, id=1], Person [name=Name2, age=10, id=2], 
    Person [name=Name3, age=15, id=3]
]

ИтакВы можете сделать то же самое с любым, сериализовав просто Person, вам нужно сначала восстановить Object и использовать instanceof, чтобы увидеть, какой тип восстановлен.

Pojo p1 = new Person(1, "Name1", 10);
serialize("person.ser", p1);
Object o1 = deserialize("person.ser");

System.out.println(o1);
System.out.println(o1.getClass());
System.out.println(o1 instanceof Person);

Output

Person [name=Name1, age=10, id=1]
class serial.Person
true
...