1

I have following code, which is supposed to test different sorting algorithm implementations (& teach me generics) with arrays of different number types (Integer, Long, ...). Although I've gotten it to work, I was wondering if there can be improvements, specifically in 3 places where I've put FIXME.

Thanks..

package com.kash.test;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

class SortTester<E extends Number> {
    E[] arr;
    E[] copyArr;
    Class<E> classOfElemType;
    int arrayLenToTestWith;

    @SuppressWarnings({ "unchecked" })
    SortTester(Class<E> cc, int ll) {
        classOfElemType = cc;
        arrayLenToTestWith = ll;
        arr = (E[]) Array.newInstance(classOfElemType, arrayLenToTestWith);
        copyArr = (E[]) Array.newInstance(classOfElemType, arrayLenToTestWith);
        for (int i = 0; i < arrayLenToTestWith; i++) {
            arr[i] = copyArr[i] = randomNumber();
        }
    }

    void reset() {
        System.arraycopy(copyArr, 0, arr, 0, arrayLenToTestWith);
    }

    E randomNumber() {
        // FIXME: Is tehre a way to do this without reflection?
        // FIXME: Also by converting the random() output to int we lose
        //        precision, anyway to avoid that without some "instanceof"
        //        kinda checks?
        try {
            // Every Number subclass, has a c'tor with a single String
            // arg, which represents an int.
            Constructor<E> ctor = classOfElemType.getConstructor(String.class);
            return ctor.newInstance(Integer.toString((int) (Math.random() * (arrayLenToTestWith * 2))));
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException
                | IllegalArgumentException | InvocationTargetException e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
            e.getCause().printStackTrace();
        }
        return null;
    }

    void print() {
        for (int i = 0; i < arrayLenToTestWith; i++) {
            System.out.println(Array.get(arr, i));
        }
    }

    void test(/* sorters */) {
        // test the Sorter instances on our array for time and space..
        // for s in sorters
        // do
        // // start monitors..
        // s.sort(arr);
        // // stop monitors
        // reset();
        // done
        // // print results...
    }
}

public class Main<T extends Number> {

    public static void main(String[] args) {
        // FIXME: Is tehre a way to remove the unchecked warnings for Class below? Without
        //        using "@SuppressWarnings({ "unchecked" })"
        Class types[] = { Integer.class, Double.class, Float.class, Long.class, Short.class };
        for (Class cc : types) {
            SortTester<?> typeTester = new SortTester<>(cc, 10);
            System.out.println("Type = " + cc.getCanonicalName());
            typeTester.print();
        }
        // Class<?> types2[] = { Integer.class, Double.class, Float.class, Long.class, Short.class };
        // for (Class<?> cc1 : types) {
        // SortTester<cc1> typeTester = new SortTester<>(cc1, 10);
        // typeTester.print();
        // }
    }
}

---- edit ----

class above is meant to test following interface:

package com.kash.src;

import java.util.Comparator;
import java.util.List;

/**
 * 
 * Interface that provides all sorting functions for all possible representations
 * of a list of Objects (non-primitive types). <br>
 * 
 * - {@link List}<{@link Comparable}><br>
 * - Array of < ? extends {@link Comparable}><br>
 * - {@link List}< ? > with external {@link Comparator}<br>
 * - Array of < ? > with external {@link Comparator}<br>
 * 
 * @author Kashyap Bhatt
 * 
 * @param <T>
 */

public interface Sorter {
    <T extends Comparable<? super T>> void sort(List<T> list);

    <T extends Comparable<? super T>> void sort(T[] array);

    <T extends Object> void sort(List<T> list, Comparator<? super T> c);

    <T extends Object> void sort(T[] array, Comparator<? super T> c);
}
5
  • Third Fix: Class<Number> types[] .... Anyway, some warnings cannot be removed because you use methods that existed before generics and are not ready to use them (I believe the second one is one example) Commented Sep 20, 2012 at 19:04
  • Class<Number> types[] = { Integer.class, .... }; gives this error: Cannot create a generic array of Class<Number> and Type mismatch: cannot convert from Class<Integer> to Class<Number>. PS: I can probably use Arrays.newInstance(Number.class, ...) but then I can't initialize it in a single line. Commented Sep 20, 2012 at 19:07
  • @SJuan76 "you use methods that existed before generics " ==> Is tehre an alternative/correct way? I'm new to generics so... Commented Sep 20, 2012 at 19:10
  • Sorry, I did misread the code; I was thinking of an array of numbers (not an array of classes of numbers). In Java, if A extends B, Generic<A> does not extend Generic<B> (check type erasure). Commented Sep 20, 2012 at 19:18
  • @SJuan76: True, but Class<Integer> is a subtype of Class<? extends Number>. Commented Sep 20, 2012 at 19:21

1 Answer 1

1

As a good general rule, never use an array when you could use a Collection.

This is how I would initialize the types variable:

List<Class<? extends Number>> types = Arrays.<Class<? extends Number>>asList( Integer.class, Double.class, Float.class, Long.class, Short.class );

The rest of your code will work unchanged.

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, that's a workaround. But I need to test methods that take primitive arrays. See the edit. And I wanted to learn generics a bit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.