1

Ok so I know that you can't have an abstract static method, although I see this as a limitation personally. I also know that overriding static methods is useless because when I am dealing with say MyList<T extends ObjectWithId> and my object has an abstract class with a static method that gets overridden in it's subclasses, T doesn't exist at runtime so ObjectWithId's static method would be called instead of the subclass.

So here is what I have:

class PersistentList<T extends ObjectWithId> implements List<T>{

}

where ObjectWithId is:

abstract ObjectWithId{
    public abstract long getId();
}

Now the issue is that my PersistentList is meant to be stored on hard disk, hence the name, and in reality will only store ids of objects it holds. Now when I want to implement the

@Override
public T get(int index) {

}

method of PersistentList, what I want is for my program to use the id it has stored for index and call a static method objectForId(long id) which would be implemented in each subclass of ObjectWithId. It can't be a instance method because there is no instance yet, the point is to load the instance from the hard disk using the id. So how should it be implemented? One option is to have ObjectWithId have a constructor ObjectWithId(long id) implemented in each subclass, but T doesn't exist at runtime so how would I instantiate it? I know I could pass Class<T> object in the constructor of PersistentList but I would prefer if the constructor did not have any arguments, but I don't think there is a way to get the class of T without explicitly passing it in right?

I hope this is a better explanation, sorry for the ambiguous question I started with.

user1084563
  • 2,149
  • 17
  • 28
  • Is your question really: "How do I get the type of a generic parameter"? If it is, there are dozens of questions about this already, e.g. http://stackoverflow.com/questions/182636/how-to-determine-the-class-of-a-generic-type, http://stackoverflow.com/questions/1372432/how-to-obtain-class-instance-generic-argument-type, http://stackoverflow.com/questions/2223233/how-to-get-generics-class, etc. – Oliver Charlesworth Dec 09 '11 at 19:38

2 Answers2

1

While it always seems easier to start out with static methods, I've found it to usually be beneficial to avoid static methods for just this reason, and to use instance methods by default.

The advantage to this is extensibility. Besides allowing for inheritance and avoiding the "limitations" you mentioned, it provides for extensibility - without needing to redesign things and change APIs later. For example, "this class does exactly what I need, but I wish I could change only this one portion of functionality". If there are static methods calling other static methods, there is no good way to do this. If all the methods are non-static - I can subclass that class and override only the portion of functionality required.

The other (somewhat-related) limitation to static methods is that they can't be used to implement interfaces.

In summary, I prefer to reserve static methods for "utility methods" where the function that they are performing is really clear-cut, and there isn't any feasible future reason why an alternative implementation would need to be provided.

ziesemer
  • 27,712
  • 8
  • 86
  • 94
  • Thanks for the quick response, although I just updated the question to better reflect what I am looking for. The need for it to be static or a constructor is necessary because the instance doesn't exist yet and I will be using it to generate the instance. – user1084563 Dec 09 '11 at 20:11
1

While passing the Class<T> as a constructor argument, it does not really solves your problem. You then have access to the class, but to get access to the static method defined on the class you will have to use generics (unless somebody else knows a way to call a static method defined on a class from a Class object).

I would define a new generic interface which contains a generic method objectForID, something like

public interface ObjectRetriever<T>{
  public T objectForID( long aID );
}

and adjust the constructor of the PersistentList to take such a ObjectRetriever instance as parameter. This ObjectRetriever can then be used to restore the objects based on their ID.

Robin
  • 36,233
  • 5
  • 47
  • 99
  • Sorry what I meant by the passing of Class was so that I could call T's constructor that would generate the instance instead of the static method. Your method could work, but the id doesn't tell me the type of the object, just the id among the group of those objects of type T. If I use your method, I still don't know what T is at runtime so how would I then call the appropriate method for processing the object if it is based on what type T it is. – user1084563 Dec 09 '11 at 20:25
  • 1
    You wouldn't care what T is. Everywhere in your code where you create a PersistentList you know what the type of T is, and you pass an approriate 'ObjectRetriever' instance to the constructor. The PersistentList shouldn't have to care about the runtime-type of T. It should only know that when it calls that function, the function will return an object of type T which the list can store – Robin Dec 09 '11 at 20:29
  • This will work, I just wish there was a way to do this without having to pass anything into the list, I would prefer if the list functioned the same way as a regular List that way they can be simply interchanged with the existing lists I already have. Too bad you can't have abstract static methods. – user1084563 Dec 09 '11 at 20:40