terryhau
terryhau

Reputation: 569

Java generic method

I have a whole bunch of classes that define these two constants, eg:

public class Face
{
    public static final int LUMP_INDEX = 1;
    public static final int SIZE = 20;

    blah blah
}

public class Edge
{
    public static final int LUMP_INDEX = 5;
    public static final int SIZE = 32;

    blah blah
} 
etc.

At the moment, i have a function for each one to create an array of that class, using the 2 constants defined in the class.

private Face[] createFaces(RandomAccessFile in)
{
    int numFaces = doSomeCalculations(Face.LUMP_INDEX, Face.SIZE);
    Face[] faces = new Face[numPlanes];

    blahblah;
    for(int i = 0; i < numFaces; i++)
        faces[i] = new Face();

    return faces;
}

A bit silly to have a create function for every class. The only thing that changes is the class type. So i wanted to create a genertic method that would work with any of the classes above. Something like:

private T[] create(RandomAccessFile in, Class T)
{
    int num = doSomeCalculations(T.LUMP_INDEX, T.SIZE);
    T[] faces = new T[numPlanes];

    blahblah;
    for(int i = 0; i < num; i++)
        faces[i] = new T();

    return faces;
}

However I'm not sure how to do it properly. Any help would be appreciated. Thanks.

Upvotes: 2

Views: 13099

Answers (4)

Michael Borgwardt
Michael Borgwardt

Reputation: 346476

The only way that could be made to work is by using reflection to read the constants through the class object and Array.newInstance() to create the array. Oh, and the method signature would have to look like this:

private <T> T[] createFaces(RandomAccessFile in, Class<T> clazz)

Edit An alternative solution would be to keep the constants in a map keyed by class rather than as static fields. Java just isn't dynamic enough, especially on the class level, to do it your way cleanly.

Upvotes: 7

Pablo Grisafi
Pablo Grisafi

Reputation: 5047

You can always use the simpler form:

<T> T[] create(RandomAccessFile in, Class<T> clazz, int lumpIndex, int size)
{
    int numPlanes = doSomeCalculations(lumpIndex, size);
    T[] faces = new T[numPlanes];

    blahblah;

    return faces;
}

And use it like

Face[] faces = create(in, Faces.class, Face.LUMP_INDEX, Face.SIZE

It is neither as professional as using an abstract factory, nor as silly (and dangerous!) as having the same function over and over again. You can still make the mistake of calling it using

Face[] faces = create(in, Faces.class, Edge.LUMP_INDEX, Edge.SIZE)

But this is a mistake that it is easy to point.

Upvotes: 0

Dave C
Dave C

Reputation: 11

Potentially you could do this by having both (all?) of the items you want to create extend some superclass "Array-Able Object"

But provided your "blablabla" in createFaces is not the same, you gain nothing and back yourself into a corner with that extension.

I'd look into whether or not you really need these different classes which all do the same thing, or whether there's some more general fix you could look into. If the only difference between the two is their static variables, for instance- then you should move those to a single location, say- a resource file.

If all you have the same, though, are those "create array" sections of this code, then separating or somehow linking them seems unnecessary at best.

Upvotes: 1

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147164

There's no excuse for using reflection in a situation like this. Bung in an Abstract Factory or similar.

Upvotes: 1

Related Questions