1

I lately wanted to learn more about generic methods and created several examples, but the following type safety is not clear to me. Here an example:

public class GeneralMethod
{
  public static void main( String[] args )
  {
    Repository rep = new Repository();

    Set<ConcreteObject> set = rep.getObject();
  }
}


abstract class AbstractRepository
{
  public abstract <T extends SuperObject> Set<T> getObject();
}


class Repository extends AbstractRepository
{
  @Override
  public Set<ConcreteObject> getObject() //<- Type safety!
  {
    return new HashSet<ConcreteObject>();
  }
}

abstract class SuperObject
{

}

class ConcreteObject extends SuperObject
{

}

Following Type safety comes up in Repository.class in eclipse:

Type safety: The return type Set < ConcreteObject > for getObject() from the type Repository needs checked conversion to conform to Set < SuperObject > from the type AbstractRepository

Why does the compiler want to conform to Set < SuperObject > instead of Set < T extends Superobject > ?

How would you tell every Repository to implement a getObject() method with its own type with only using generics in method signature? (meaning without defining the generic in class signature).

thank you, ymene

crusam
  • 6,140
  • 6
  • 40
  • 68

5 Answers5

4

How would you tell every Repository to implement a getObject() method with its own type with only using generics in method signature? (meaning without defining the generic in class signature).

You cannot. When you say "it's own type", you would be referring to the generic type of the Repository subclass - which doesn't exist unless you are doing something like FooRepository extends AbstractRepository<Foo>.

In this situation, I would simply make the abstract class generic:

public abstract class AbstractRepository<T extends SuperObject>
      abstract Set<T> getObjects();
}

BTW, an abstract class with no non-abstract methods is probably better designed as an interface.

matt b
  • 138,234
  • 66
  • 282
  • 345
  • Idd, the reason for trying it without a generic class was, that the real abstract class already has two generics, so I didnt wonna add a third one for just a single method, because it might confuses more than it would help. Maybe I just have to reconsider the current class design for that approach. thank you! – crusam Mar 25 '11 at 13:55
1
AbstractRepository repository = new Repository();
Set<SuperObject> set = repository.getObject();

That should compile, but you would have a Set<ConcreteObject> assigned to a Set<SuperObject> variable.

Returns Set<? extends SuperObject> should compile [not tested]. You might want to make the base class generic (or not return a set at all).

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • The example already compiled. It was just not really clear to me, why there was a warning at all. Idd the better solution is probably to make the base class generic. Just wanted to avoid it, since the original base class already has two generics. – crusam Mar 25 '11 at 14:01
  • By compiled, I mean compile without warnings. – Tom Hawtin - tackline Mar 25 '11 at 14:39
1

"Why does the compiler want to conform to Set < SuperObject > instead of Set < T extends Superobject > ? "

Because you told him so! The least type that could be substituted for T is, after all Superobject.

Ingo
  • 36,037
  • 5
  • 53
  • 100
  • Oh, ok, that wasnt really clear to me, thank you. I thought that way I would have told the compiler that I explicit want to have a class which is extending SuperObject. – crusam Mar 25 '11 at 13:57
1
class AbstractRepository

  Set<? extends SuperObject> getObject();


class Repository extends AbstractRepository

  Set<    ConcreteObject   > getObject()

This works because Set<ConcreteObject> is a subtype of Set<? extends SuperObject>

see also Overriding method with generic return type

Community
  • 1
  • 1
irreputable
  • 44,725
  • 9
  • 65
  • 93
0

T extends SuperObject bounds T to any class that extends (is a subclass) of SuperObject. You are overriding AbstractRepository.getObject() method so the method signature must be the same with it's parent class.

This should be valid (untested)

class Repository extends AbstractRepository
{
  @Override
  public Set<T extends SuperObject> getObject() //Valid
  {
    return new HashSet<ConcreteObject>();
  }
}
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
  • its unfortunatly not valid, since u cant use 'T extends xxx' within the methods return type. but thank you for your effort. – crusam Mar 25 '11 at 14:05
  • @ymene, unfortunately that's how your code is setup. You can make your class generic if you want to know the specific return type. – Buhake Sindi Mar 25 '11 at 14:33