Reputation: 2878
I'm trying to understand bounded types in Java. I think that my reasoning is almost correct but I get an error and I don't understand why it gives me that error if A (JsonPerson) is a subclass of T (Person). The error is the following (also commented in the code):
Error:(22, 16) error: incompatible types: JsonPerson cannot be converted to A
where A is a type-variable:
A extends Person declared in method <A>fromJson(JSONObject)
The error "happens" in the return line.
I've made a simple example, here is the code
Person.java
public class Person {
private String name;
private String surname1;
private String surname2;
private String phone;
private String email;
public Person(String name, String surname1, String surname2, String phone, String email) {
this.name = name;
this.surname1 = surname1;
this.surname2 = surname2;
this.phone = phone;
this.email = email;
}
public String getName() {
return name;
}
public String getSurname1() {
return surname1;
}
public String getSurname2() {
return surname2;
}
public String getPhone() {
return phone;
}
public String getEmail() {
return email;
}
}
JsonPerson.Java
public class JsonPerson extends Person implements JSONSerializableInterface<Person> {
public JsonPerson(String name, String surname1, String surname2, String phone, String email) {
super(name, surname1, surname2, phone, email);
}
/**
* Error:(22, 16) error: incompatible types: JsonPerson cannot be converted to A
* where A is a type-variable:
* A extends Person declared in method <A>fromJson(JSONObject)
* */
@Override
public <A extends Person> A fromJson(JSONObject json) throws JSONException {
String name = json.getString("name");
String surname1 = json.getString("surname1");
String surname2 = json.getString("surname2");
String phone = json.getString("phone");
String email = json.getString("email");
return new JsonPerson(name, surname1, surname2, phone, email);
}
@Override
public JSONObject toJson(Person object) {
return null;
}
}
JSONSerializableInterdace.java
public interface JSONSerializableInterface<T> {
public <A extends T> A fromJson(JSONObject json) throws JSONException;
public JSONObject toJson(T object);
}
Upvotes: 3
Views: 273
Reputation: 37655
Signatures like
public <A extends T> A fromJson(JSONObject json)
don't really make a lot of sense. This says that the type of the object returned is decided by the caller. The caller could supply a type witness e.g. <CleverPerson>
to the method, and expect a CleverPerson
to be returned, but there's no way this could work unless the type is explicitly passed to the method (otherwise the type A
is not even available at runtime). Something like this would make sense:
public <A extends T> A fromJson(Class<A> clazz, JSONObject json)
However, I think it may be preferable to go for this instead:
public T fromJson(JSONObject json)
Upvotes: 3
Reputation: 22651
The problem is that somebody might call your method like this:
new JSONPerson().fromJSON<SpecialPerson>(json);
where SpecialPerson
extends Person
. This would be valid (because A
extends Person
), but the JSONPerson
returned by the method is not a SpecialPerson
.
Upvotes: 4