Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid a generics warning

Tags:

java

generics

I have a utility function that will shuffle the elements of any Vector, but which generates generic warnings about using raw types.

static public void shuffle(Random r,Vector v)
   {    int sz = v.size();
        for(int pass = 0;pass<4;pass++)
        {   for(int i=0;i<sz;i++)
            { int j=nextInt(r,sz);
              Object ii = v.elementAt(i);
              v.setElementAt(v.elementAt(j),i);
              v.setElementAt(ii,j);
            }
        }
  }

there seems to be no way to quiet the warnings other than by suppressing them. Changing the method signature to Vector<Object> restricts the callers Vector<Object>. Changing to Vector<?> makes the setElementAt uncompilable.

like image 340
ddyer Avatar asked Apr 07 '26 07:04

ddyer


2 Answers

First you should note that you're reinventing the wheel.

Collections.shuffle(yourVector, yourRandom);

does the trick :-)


To make your method generic for all types of Vectors, this is the way to write it:

static public <T> void shuffle(Random r, Vector<T> v) {
    int sz = v.size();
    for (int pass = 0; pass < 4; pass++) {
        for (int i = 0; i < sz; i++) {
            int j = nextInt(r, sz);
            T ii = v.elementAt(i);
            v.setElementAt(v.elementAt(j), i);
            v.setElementAt(ii, j);
        }
    }
},
like image 99
aioobe Avatar answered Apr 08 '26 21:04

aioobe


As pointed out already, you can do this with generics like so:

public static <T> void privateShuffle(Random r, Vector<T> v) {
    int sz = v.size();
    for (int pass = 0; pass < 4; pass++) {
        for (int i = 0; i < sz; i++) {
            int j=nextInt(r,sz);
            T ii = v.elementAt(i);
            v.setElementAt(v.elementAt(j), i);
            v.setElementAt(ii, j);
        }
    }
}

However, since you're writing a utility method I'd prefer the ? wildcard syntax - it's a lot cleaner to look at. As you've already noted, you can't use the following header directly on that method, but I'd be tempted to do something like the following:

public static void shuffle(Random r, Vector<?> v) {
    privateShuffle(r, v);
}

private static <T> void privateShuffle(Random r, Vector<T> v) {
    int sz = v.size();
    for (int pass = 0; pass < 4; pass++) {
        for (int i = 0; i < sz; i++) {
            int j=nextInt(r,sz);
            T ii = v.elementAt(i);
            v.setElementAt(v.elementAt(j), i);
            v.setElementAt(ii, j);
        }
    }
}

Yes, it's an extra method, but that way you get to expose the "clean API" look of the unbounded wildcard whilst still maintaining the type safety (this is how a lot of the Java API methods work.)

As a side note, I'd also re-iterate that unless you're doing this for legacy reasons, Vector is generally considered an obsolete collection these days and a much better choice would be to use a list (and code to the list interface.)

like image 28
Michael Berry Avatar answered Apr 08 '26 21:04

Michael Berry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!