Reputation: 41
I've built a client-server application, with working connection setup and handling. I would like the client to send requests of different types, each with unique fields but all of which inheriting from a "Request" superclass. Is there a way to do this?
For example I have a Foo class that implements serializable
class Foo implements Serializable{
public String name;
public Foo() {
this.name = "Default";
}
public Foo(String name) {
this.name = name;
}
}
and two subclasses that extend it
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;
}
}
Is there a way to have the client send instances of BarOne and BarTwo through an ObjectOutputStream and have the server figure out whether what it receives is an intance of one or the other?
Upvotes: 1
Views: 67
Reputation: 14572
There is no restriction here, you can serialize a subclass without difficulties.
Here, I provide a quick example using a the same structure as yours (but with specific example).
The abstract class.
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;
}
}
The first subclass 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 + "]";
}
}
The second subclass 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
+ "]";
}
}
You can then create a collection for this example that will hold both type of instance :
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));
You can use a file for the serialization (because I don't have time to create a socket system ;) ) using :
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();
}
}
Let serialize and deserialize the list to see if the type are recovered :
serialize("data.ser", pojos);
List<Pojo> tmp = deserialize("data.ser");
System.out.println(tmp);
And you will see the result with the correct type of instance :
[
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]
]
So you could do the same with anything, serialize just a Person
, you will need to recover the Object
first and use an instanceof
to see what is the type recovered.
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
Upvotes: 1