I noticed that in Java, you can use a class which has members of types that are unavailable to you. For example, say you have a precompiled .class file for the following Person class; but not for Address, which it uses:
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String sex;
private String name;
private transient Address address;
public Person(String sex, String name) {
this.sex = sex; this.name = name;
}
public void setAddress(Address address) {
this.address = address
}
}
You can instantiate this class with Person person = Person("Male", "Andrew"); even if the type Address is not available to your Java project.
Now the problem is, if you want to serialize a Person object, you cannot do this unless the Address type is available (i.e. can be loaded by the class loader), even though the Address field is transient.
For some reason Java needs to know the type Address even though it will not need to serialize it…
Any help on how I could serialize Person anyway without having to redefine a Person class without an address? And any explanation of why Java needs to know the type of address although it will not need to serialize it?
Many thanks.
I am operating under the assumption that you have a
.classfile forPerson, but no.classfile forAddress. (PerhapsPersonis a dependency from a different project?)The reason you cannot serialize
Person(even though theAddressfield is transient) is that the serialization API uses the Java reflection API. Although the JVM will load a class without loading all of its dependencies, the reflection API is not as forgiving.The first time the reflection API is used to retrieve field information for a particular class, it retrieves and caches information for all fields in the class. To do this, it has to resolve the types for every field in the class, and thus will attempt to load the class files for every field. (You can see this in the Java source code:
ObjectOutputStreamusesObjectStreamClass, which callsClass.getDeclaredField, which calls a private methodprivateGetDeclaredFields, which resolves and caches all the field definitions for the class.)As a workaround, if your code never actually uses any objects of type
Address, you can simply create an emptyAddressclass in the correct package, compile it, and add it to your class path:For those who think it isn’t possible to use
Personat runtime without anAddressclass definition, the following three classes demonstrate what the OP is talking about:Person.java
Address.java
Test.java
Now compile
Test.java, deleteAddress.class, and runTest: