Java restricted types

I am trying to understand restricted types in Java. I think my reasoning is almost correct, but I am getting an error and I don’t understand why it is giving me this error if A (JsonPerson) is a subclass of T (Person). The error is as follows (also commented out 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" on the return line.

I 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);
}

      

+3


source to share


2 answers


Signatures such as

public <A extends T> A fromJson(JSONObject json)

      

don't really make a lot of sense. This suggests that the type of the object returned is determined by the caller. The caller can provide a type witness, for example. <CleverPerson>

to the method and expect a to CleverPerson

be returned, but it cannot work in any way 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 is preferable to use this instead of:

public T fromJson(JSONObject json)

      

+3


source


The problem is, someone might call your method like this:

new JSONPerson().fromJSON<SpecialPerson>(json);

      



where it SpecialPerson

continues Person

. That would be fair (because A

extends Person

), but the JSONPerson

returned method is not SpecialPerson

.

+4


source







All Articles