WIZARDELF
WIZARDELF

Reputation: 3885

what's wrong with my generic type casting?

I have a Student class and a StudentPool class defined as follows:

public class Student {
    public Student copy () {
        return new Student();
    } 
}

and

public class StudentPool<T extends Student> {
    public T copyStudent(T t) {
        return t.copy();
    }
}

thus, the copyStudent method cannot be compiled and I have to use un-safe type casting. I cannot understand why Java does regard this as illegal?

Edit: user845279, lcfseth, and Bohemian: I think the following revision to Student may cause the similar scenario, cast a parent class into its child class, but this version can pass compiling:

public class Student {
    public <T extends Student> T copy() {
       T rv = null; 
       return rv;
    } 
}

Edit: forget the above code: rv can be either null or un-safely casted.

Upvotes: 2

Views: 152

Answers (3)

Paul Bellora
Paul Bellora

Reputation: 55223

Let's say you had a class SmartStudent that extended Student, and a StudentPool<SmartStudent>. In this case copyStudent should take a SmartStudent and return a SmartStudent, however the implementation in Student isn't doing this - it's only returning a plain Student instance.

Edit:

In order to implement the pattern you want, you could give Student and all its subclasses a copy constructor:

public class Student {
    public Student(Student other) {
        //copy other's Student fields to this instance
    } 
}

public class SmartStudent extends Student {
    public SmartStudent(SmartStudent other) {
        super(other);
        //copy other's SmartStudent fields to this instance
    }
}

and make StudentPool abstract:

public abstract class AbstractStudentPool<T extends Student> {
    public T copyStudent(T original);
}

Each AbstractStudentPool implementation would call the appropriate copy constructor:

public class SmartStudentPool extends AbstractStudentPool<SmartStudent> {
    @Override
    public SmartStudent copyStudent(SmartStudent original) {
        return new SmartStudent(original);
    }
}

Upvotes: 4

Bohemian
Bohemian

Reputation: 425083

The problem is that although Student returns Student from copy(), subclasses would also return Student... not their own type.

Here's an approach to fix your problem:

public static interface Copyable<T> {
    public T copy();
}

public static class Student implements Copyable<Student> {
    @Override
    public Student copy() {
        return new Student();
    }
}

public static class StudentPool<T extends Student> {
    public T copyStudent(Copyable<T> t) {
        return t.copy();
    }
}

As a side note, it seems you don't need generics here.

Upvotes: 2

Samy Arous
Samy Arous

Reputation: 6814

You cannot cast a Parent Class into its Child Class. Implicit cast only works the other way around. Even by using explicit type casting this is highly likely to generate runtime error.

Upvotes: 0

Related Questions