I am learning Java generics and I am trying to adapt some code I developed as an exercise.
In particular, I developed an ArrayVisualizer class that uses Sedgewick's StdDraw library to visualize and animate the behaviour of a dynamic array. I have my own dynamic array class which supports generics, and I am trying to extend the usage of ArrayVisualizer to anything that is akin to this array.
In short, my question is: how can you deal with generic types containing other generic types?
Here is my thought process:
I started by making this Interface:
public interface IterableCollection<Item> {
void add(Item i);
Item get(int index) throws IndexOutOfBoundsException; // These can be slow for LinkedList implementations
void set(int index, Item value) throws IndexOutOfBoundsException;
int capacity();
int size(); // Capacity and size can be the same for LinkedList implementations
}
Then, I would like my ArrayVisualizer class to take as parameters any class that implements this Interface. After some googling, I found that you can't write
public class ArrayVisualizer<T implements IterableCollection<?> >
but you have to use extends.
However, even if I write that I can't use the T class inside my functions.
For example, I have a compiler error if I try to generalize this function:
public static void draw(T<String> vector) throws Exception
It is like I have to specify that T is also generic, but I can't find a way to declare it. I have tried the following, and none works:
public class ArrayVisualizer<T<?> implements IterableCollection<?> >
public class ArrayVisualizer<T<S> implements IterableCollection<S> >
RESOURCES: I have uploaded the working non-generic version of my code as a reference.
DynamicArray.java
ArrayVisualizer.java (this takes some spaced strings as input)
InteractiveArrayVisualizer.java (this one doesn't allow to choose the values of the cells but you can fill them by clicking on the next empty spot and you can empty them by clicking on the last open cell. This is meant to use a debug helper for the resize problem of the dynamic array).
Your ArrayVisualizer class must specify both the collection type, and the element type. You cannot quantify over T<String> like that in Java. (Other languages can do it, but not Java.)
So, something like....
class ArrayVisualizer<E, T extends IterableCollection<E>> {
public void draw(T vector) { ... }
}
(although if I were you, I would try to use the pre-built Iterable or Collection interface rather than my own IterableCollection interface...)
Related
EDIT: This question is not well worded, and the provided answer is correct in a literal sense but did not teach me how to attain what I needed. If you are struggling with the same problem, this is what finally helped me: How to enforce child class behavior/methods when the return types of these methods depends on the child class?
I am trying to implement a basic matrix class from a boilerplate abstract class I wrote. There will be several implementations of this abstract class, each one using a different math library, which I will then test for speed.
Each implementation will hold its data in that library's native matrix data structure. I think this is a use case for generics. At this point I think I've read too many tutorials and watched too many videos, as I just can't seem to figure out all the right places to put the T Notation to make this work correctly.
So my question is twofold:
Have I misused or missed the point of generics?
If not, what is the correct syntax for their use?
I've read the docs plus about three different tutorials and still can't understand.
Here is what I've tried:
public abstract class BaseMatrix<T> {
protected int[] shape;
protected int nrows;
protected int ncols;
protected T data; // <--- Here is the generic data --->
public BaseMatrix(int rows, int cols){
this.nrows = rows;
this.ncols = cols;
this.shape = new int[]{nrows, ncols};
}
public abstract BaseMatrix mmul(BaseMatrix other);
And here is my implementation:
public class ND4JDenseMatrix extends BaseMatrix{
// private INDArray data;
public ND4JDenseMatrix(int rows, int cols) {
super(rows, cols);
this.data = Nd4j.zeros(this.shape); <--- Here is the non-generic data --->
}
#Override
public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
ND4JDenseMatrix result = new ND4JDenseMatrix(nrows, ncols);
result.data = data.mmul(other.data);
return result;
}
The error is: Method does not override method from its superclass.
hold its data in that library's native matrix data structure. I think this is a use case for generics.
Generics serves to link things. You declared the type variable with <T>, and you've used it in, as far as your paste goes, exactly one place (a field, of type T). That's a red flag; generally, given that it links things, if you use it in only one place that's usually a bad sign.
Here's what I mean: Imagine you want to write a method that says: This method takes 2 parameters and returns something. This code doesn't particularly care what you toss in here, but, the parameters must be the same type and I return something of that type too. You want to link the type of the parameter, the type of the other parameter, and the return type together.
That is what generics is for.
It may apply here, if we twist our minds a bit: You want to link the type of the data field to a notion that some specific implementation of BaseMatrix can only operate on some specific type, e.g. ND4JMatrix.
However, mostly, no, this doesn't strike me as proper use of generics. You can avoid it altogether quite easily: Just.. stop having that private T data; field. What good is it doing you here? You have no idea what type that is, you don't even know if it is serializable. You know nothing about it, and the compiler confirms this: There is absolutely not one iota you can do with that object, except things you can do to all objects which are generally quite uninteresting. You can call .toString() on it, synchronize on it, maybe invoke .hashCode(), that's about it.
Why not just ditch that field? The implementation can make the field, no need for it to be in base!
public class ND4JDense extends BaseMatrix {
private ND4JMatrix data; // why not like this?
}
(This code assumes 'ND4JMatrix' is the proper data type you desire here, a thing that can is the internal representation for the data in the ND4J impl).
However, if you must, yeah, you can use generics here. You've type-varred BaseMatrix, and that means all usages of BaseMatrix must be parameterized. That's the part you messed up in your code. If we go with your plan of a type-parameterized BaseMatrix class and a field of type T, the right code is:
public class ND4JDense extends BaseMatrix<ND4JMatrix> {
...
}
I wouldn't, however, do it this way (I'd go with having the impl have the field, much simpler, no need to bother anybody with the generics). Unless, of course, you DO have an actual need for that field and it IS part of BaseMatrix's API. For example, if you want this:
public class BaseMatrix<T> {
public T getData() { return data; }
}
then it starts to make more sense. With that, you can write the following and it'll all compile and work great:
public class ND4JDense extends BaseMatrix<ND4JMatrix> {
...
// no need to write a getData method here at all!
...
}
ND4JDense dense = new ND4JDense();
ND4JMatrix matrix = dense.getData();
But, clearly, this makes no sense if you intend for the ND4JMatrix to remain an implementation detail that users of the BaseMatrix API should probably not be touching.
EDIT: You changed the question on me, later. Now you want the mmul method to take 'self' as argument, effectively: You want the same type to be passed in.
You can sort of do that but it is a little tricky. You need the self-ref generics hack. It looks like this:
public class BaseMatrix<T extends BaseMatrix<T>> {
public abstract T mmul(T other);
}
In practice the only valid value for T is your own class, or at least, that is the intent. This works fine:
public class ND4JDenseMatrix extends BaseMatrix<ND4JDenseMatrix> {
public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
.. impl here ..
}
}
As far as I see, you have two issues in your code:
You're not actually overriding the method of the superclass. What you have created is an overload of method mmul. To correctly override the method, the method signature must match, in particular the input parameter must be the same. It's ok to have a subtype of the return type, as Java support covariant. If you instead put one of its subclass, that is overloading. Hope you get the difference. So the correct signature can be the following:
public BaseMatrix mmul(BaseMatrix other) {
...
}
You have not specified the type T, so the compiler cannot know that by assumption is a subtype of BaseMatrix. it can be any type, even Object for example, so you are going to get "method not found" compilation error.
I have a class called CountService. It has this method
public int count()
What I want is to append this function to any java.util.List variable and it will return the size of that list( an integer). I know that list has a size() method. I'm just testing this out if it's possible to append a method to a class. I don't know where it doesn't really belong to.
Sample:
java.util.List<String> list;
list.count();
So even though count does not belong to java.util.List, I want this to be possible in my code. Is there any way?
edit:
It's not specifically for java.util.List only. Rather for any class. Let's say i have Class A and Class B
Now for example Class A represents a String type. And now I have a method in Class B called length(). I want this to be possible.
ClassA_VariableName.length()
And then I'll be able to get the length of object. Class B is like a collection of functions or features that can be appended to any type it was made to be appended to.
The short answer is NO, you cannot do this in Java without using introducing a new type (class or interface) that is declaring the method.
You would have to extend java.util.List
public interface SuperList extends List {
default int count() {
return size();
}
}
And then you would have to introduce a new class that is implementing that interface (and maybe inherit stuff from an existing JDK list e.g. ArrayList).
But if you are not limited to Java you can take a look at other JVM languages. For example Groovy or Kotlin provide features to add a method to a class.
Here is an example in Groovy that uses the Expando class to add a method to a list.
List list = new ArrayList()
list.metaClass.count() {
delegate.size()
}
// now call it
list.count()
In Java you can not to add methods to classes which sources you can not change unlike javascript or ruby.
You can create your own class and inherit it from say ArrayList:
class MyList extends ArrayList {
public int count() {
//...
}
}
I have n classes which either stack or do not stack on top of one another. All these classes extend the same class (CellObject). I know that more classes will be added to this list, and I want to create some kind of way that it is easy to manipulate "stackability" in one place.
I was thinking of creating a matrix, where the row-index is the class on the bottom of the stack and the column index is the class on the top of the stack. The value would be true (or 1) if you can stack top on bottom, false (0) otherwise.
However, my colleague suggests creating n+1 methods called canStack. One general canStack method would switch on an instanceof statement that would direct it into one of the n submethods. Each of the submethods would just answer the question of whether the top object can stack on the bottom object by itself.
I think my solution is more elegant/clean. Is this true? If so, how would I implement it?
I changed objects to classes
Your solution would be shorter. But it has the drawback that if you add a sublcass of CellObject, you could potentially forget to alter your array. Even if you know this should happen, someone else might some day work on the code. Then again, his solution has that same issue.
Now, this is a slightly wild idea, but since you're essentially saying something about classes it feels like a metadata facility is in order. What you could do is define an annotation that states which classes can be stacked onto the annotated class and/or which classes it can stack on.
Something like this:
#interface Stackable {
Class<? extends CellObject>[] stackables(); //Classes that may stack on the annotated one
Class<? extends Cellobject>[] pillars(); //Classes this one can stack on
}
Then you could create an annotation processor that uses this metadata. It could create a configuration file your read in at compile time, or generate some boilerplate code for you. You could generate meta-classes like JPA does for its type-safe query API that say something about the class. Or you could even retain the annotations at runtime to use reflection for finding out what can stack on what, building up your desired array ad-hoc rather than having to code it.
If you use an annotation processor, then maybe it would be safer to use String arrays with canonical class names, since the Class objects might not be available yet at compile time. Its feasibility would also depend on whether all CellObject classes are always in the same compilation run or not.
Using reflection (possible when making sure the annotation has a RetentionType RUNTIME) seems like a viable option here. Check the array; if the corresponding element is null (can be done by using Boolean instead of boolean), do the reflection stuff and fill in that element. Next time you can avoid the reflection overhead, lazily filling the array as needed.
EDIT: forgot to mention, my solution doesn't enforce you to keep the metadata up-to-date either. Also, the complexity could be reduced if the stackability is transitive. That is, A can stack on B and B can stack on C implies A can stack on C.
The matrix approach would scale as O(n2). In contrast, the other approach would scale as O(n), but it would be riskier to maintain.
As an alternative, consider letting an abstract CellObject implement a suitable Stackable interface, but defer the implementation to the n concrete subclass. the compiler will identify missing implementations immediately. See also When an Abstract Class Implements an Interface.
interface Stackable {
boolean canStack(Stackable other);
}
abstract class CellObject implements Stackable {}
class Cell01 extends CellObject {
#Override
public boolean canStack(Stackable other) {
return true; // TODO
}
}
class Cell02 extends CellObject {
#Override
public boolean canStack(Stackable other) {
return true; // TODO
}
}
...
I don't think your matrix concept would be the good way to achieve your goal. You'll end up with a huge matrix that contains every possibilities. Obviously, extracting the information you wish from the matrix will be fairly easy, but maintaining it in the long run might prove to be a painful experience as more CellObject subclasses are being added. The same applies to the n + 1 methods your colleague suggested.
In both cases, everytime you will add a subblass of CellObject, you will have to either go to the class that holds the matrix, create a new row, and a new column for each existing row, and manually specify if this new class can be stacked or not on class x, or add a new method canStackOnNewClassX () to each existing class. Both solutions are bug prone in my opinion (you might easily forget to update your matrix, or enter the wrong information as the code might not be easily readable), there are more elegant ways to handle such kind of problem.
One thing you could do is have a map in your CellObject super class that will hold on your "stackability" information, and provide methods to populate this map and to retrieve if a member of class A can be stacked on a member of class B. Something like this:
public abstract class CellObject
{
private static Map<Class<? extends CellObject>, Map<Class<? extends CellObject>, Boolean>> fullStackabilityMap =
new HashMap<Class<? extends CellObject>, Map<Class<? extends CellObject>, Boolean>> ();
protected static void addStackableOnObjectInformation (Class<? extends CellObject> baseObjectClass, Class<? extends CellObject> objectToStack, boolean canStackOnObject)
{
Map<Class<? extends CellObject>, Boolean> stackableMapForObject = fullStackabilityMap.get (baseObjectClass);
if (stackableMapForObject == null)
{
stackableMapForObject = new HashMap<Class<? extends CellObject>, Boolean> ();
fullStackabilityMap.put (baseObjectClass, stackableMapForObject);
}
stackableMapForObject.put (objectToStack, canStackOnObject);
}
protected boolean isStackableOnObject (CellObject baseObject)
{
Map<Class<? extends CellObject>, Boolean> stackableMapForObject = CellObject.fullStackabilityMap.get (baseObject.getClass ());
if (stackableMapForObject == null)
{
return false;
}
Boolean canStackOnObject = stackableMapForObject.get (this.getClass ());
return canStackOnObject != null ? canStackOnObject : false; //Assume that the object cannot be stacked if it was not specified
}
}
public class CellObjectA extends CellObject
{
}
public class CellObjectB extends CellObject
{
static
{
addStackableOnObjectInformation (CellObjectB.class, CellObjectA.class, true);
}
}
public class CellObjectC extends CellObject
{
static
{
addStackableOnObjectInformation (CellObjectC.class, CellObjectA.class, true);
addStackableOnObjectInformation (CellObjectC.class, CellObjectB.class, true);
}
}
The creation of fullStackabilityMap in CellObject seems complicated, due to Java's lack of diamond operator in Java 6, but it could be simplified if you wrote a utility method that creates maps, or use Guava.
So, in this example, CellObjectC instances would not be stackable over kind of objects; CellObjectB instances could be stacked on CellObjectC objects only, and CellObjectA could be stacked on either CellObjectB or CellObjectC objects.
The only work you would have to do each time you add a new class is to update the static initializers of your existing classes to make sure this new class is accounted for. The advantages of this solution are:
You only have to specify which kind of object can be stacked on which kind of object. No need to fully initialize a matrix with all possibilities.
You can ask an object directly if it can be stacked on any kind of object, rather than having to statically poll an external class, which to me is easier to maintain, and generates cleaner code.
You do not have to maintain n+1 methods that will tell you with object A can be stacked on object B, which would be a total nightmare if you end up with a significant number of CellObject subclasses.
It was such a simple, brilliant idea. Use the power of Java 5.0 enumerated types to encode details of a data dictionary (attribute name, type, range, units, etc.) and create a type-safe system for setting and reading attribute values (i,.e., attribute AAH is short, ACC is enumerated and should only accept the values ACC001, ACC002, ACC003, etc.).
The hitch is that different attributes have different types (integer, float, text, enumerated), and the behaviors for each type are different. So I create a base class with a type parameter and some abstract methods:
public abstract class GsAttributeValueBase<T extends Comparable<T>> {
protected T m_value;
...
public GsAttributeValueBase(...) {..}
...
public abstract void SetValue(T value) throws IllegalArgumentException;
public T GetValue() { return m_value; }
// etc., etc., etc
}
I then subclass this for each type (basically, I'm trying to fake partial specialization):
public class GsAttributeValueShort extends GsAttributeValueBase<Short> {...}
public class GsAttributeValueLong extends GsAttributeValueBase<Long> {...}
public class GsAttributeValueEncoded extends GsAttributeValueBase<GsAttributeEncodedValueEnum> {...}
...
So far so good. Now I want to basically create a factory method in the attribute enumeration type to return an instance of one of the above subtypes (since each attribute knows its type and range), something like
public GsAttributeValueBase<? extends Comparable<?>> CreateInstance()
{
switch(m_format)
{
case SHORT: return new GsAttributeValueShort(...);
case LONG: return new GsAttributeValueLong(...);
case ENCODED: return new GsAttributeValueEncoded(...);
...
}
}
and call the method as:
GsAttributeValueShort = GsAttributeEnum.AAH.CreateInstance();
This is where I hit a brick wall; I get an incompatible types error on the order of
found : GsAttributeValueBase<capture of ? extends java.lang.Comparable<?>>
required: GsAttributeValueShort
I've tried roughly a dozen permutations on the declaration of CreateInstance() so far (it can't be static, since it relies on information specific to the enumeration instance). I'm about to tear my hair out at this point; I've wasted several days going down this rabbit hole, and need to either get this working today or punt altogether.
I really want to make this work; I think it would be valuable to not just this project but other projects going forward. But Java generics don't behave like C++ templates (something that's been driven home with a vengeance over the past week), and I know I'm missing something vital here, but I can't see what it is.
EDIT
I can't make this work the way I'm envisioning in my head and I've burned too much time on it. Thanks for the suggestions, but I'm going to go ahead and close this down.
EDIT 2
Oh. I can't close my own question. Oh well.
What about:
public <T extends Comparable<T>> GsAttributeValueBase<? super T> CreateInstance() {
...
}
Just use a map and my TypeSafeMap pattern.
Some thoughts on Generics: Generics are meant to make collections type safe. They aren't really intended for complex things like building type-safe classes at runtime. So be mindful and use your tools so that they don't become a burden. If a cast works and you don't understand how the generic construct works (even if you just wrote it), use the cast. Just imagine coming back to this code in half a year and having to fix it.
I'm currently playing with implementing various sorting algorithms in Java, mostly for fun, but I'm struggling with how to do it 'right'. That is, I want the user to be able to call the sorting algorithm of choice on anything that is comparable - ints, longs, Strings, booleans (actually, are these comparable in Java?), their own classes; whatever. The question is how to do this.
I was thinking of using a class to represent the sorting algorithm, and therefore store the things to be sorted inside using a generic list or whatever (List<E>). This would also allow me to use multiple constructors and thus allow the user to pass in the data in various forms - Lists, Arrays, whatever. Is this the correct way to do it? My current problem is that I don't wish for the user to have to create a class when they want to sort something, I'd rather it was able to be called much like System.out.println or the like.
// Example:
int[] myInts = {5,4,3,2,1};
// This is what I do *not* want.
InsertionSort mySort = new InsertionSort();
int[] sortedInts = mySort.sort(myInts);
// This is more like what I want.
int[] sortedInts = Sorting.insertionSort(myInts);
I apologise with what may seem like a basic question, but I am just learning my way with programming languages. Which is a bit ridicolous for a 2nd year Computing student working at a software company for his summer job, but you'd be surprised at how little programming knowledge is required for most of my work... it's usually more design knowledge.
EDIT:
For clarity, my three main question are:
Is it better to have the user create a class to do the sorting, or to have a static method in a class the user imports?
Is it possible to deal with both primitive data types and generic objects easily? Since I want to be able to handle any generic object that implements comparable (or likewise), this then causes problems with primitives (as they don't implement anything ;) ).
What is the best way to handle generic input - what should I check for before I try to sort them (implementing Comparable, for example)?
You could take as example the way Collections provides the binarySearch operation ... And indeed, the
int[] sortedInts = Sorting.insertionSort(myInts);
is more java-way, even if I would personnally prefer
public class Sorting {
public static <DataType extends Comparable> Iterable<DataType> insertionSort(Iterable<DataType> data);
}
<DataType> ensure output data is of the same type than input
Iterable<DataType> data input data is an iterable, to ensure maximum compatibility. Obviously, using a List would be by far simple, as it allows internal item reordering. Howeve"r, using an iterable ensure the implementor of this method will have to re-create the list in order to modify it, guaranteeing that the input list is left unchanged, and that the output list is another one.
Since I just saw you edit your question, let me reply to it point by point (and consider chosing an answer after that, as it is easier to add new questions than to edit existing ones endlessly - unless you make your question a community wiki, like I do of this reply)
Is it better to have the user create a class to do the sorting, or to have a static method in a class the user imports?
To my mind, using a static method in this case is preferable, as you here have to manipulate objects you didn't create, in a quite "basic" fashion.
Is it possible to deal with both primitive data types and generic objects easily? Since I want to be able to handle any generic object that implements Comparable (or likewise), this then causes problems with primitives (as they don't implement anything ;) ).
Have you heard about autoboxing ? It's a feature of Java 5 which makes primary types "equivalents" of objects. That's to say int are automatically converted into Integer, which, as you know, implement Comparable.
What is the best way to handle generic input - what should I check for before I try to sort them (implementing Comparable, for example)?
Notice that, due to my method declaration (the ), checking that input data implements Comparable is not done by you, but by the Jav compiler, allowing your IDE to show you mistakes.
I think you answered your own question? If you want to expose a static method instead of making the user create and object and call an instance method, then just do that. Sorting.insertionSort() looks fine to me.
Internally that can dispatch to whatever you like. Inside, if you want to implement this with classes and polymorphism and whatnot, go ahead. It does seem like a bit overkill though. I am not sure inheritance and polymorphism help a lot here.
The normal way of implementing a sorting algorithm would be to implement a static method, e.g. take a look at the source code for Arrays.sort(). You can overload this method with diferent implementations for different parameter types (e.g. objects that implement comparable vs. provide your own comparator vs. primitive arrays etc.)
Here's one I wrote earlier:
public static <T> void swap(T[] a, int x, int y) {
T t=a[x];
a[x]=a[y];
a[y]=t;
}
public static <T extends Comparable<? super T>> void mergeInOrder(T[] src, T[] dst, int p1, int p2, int p3, int p4) {
if (src[p2].compareTo(src[p3])<=0) return; // already sorted!
// cut away ends
while (src[p1].compareTo(src[p3])<=0) p1++;
while (src[p2].compareTo(src[p4])<=0) p4--;
int i1=p1;
int i3=p3;
int di=p1;
while(di<p4) {
if (src[i1].compareTo(src[i3])<=0) {
dst[di++]=src[i1++];
} else {
dst[di++]=src[i3++];
if (i3>p4) {
System.arraycopy(src,i1,dst,di,p2-i1+1);
break;
}
}
}
System.arraycopy(dst, p1, src, p1, (p4-p1)+1);
}
public static <T extends Comparable<? super T>> void mergeSort(T[] src, T[] dst, int start, int end) {
if (start+1>=end) {
if (start>=end) return;
if (src[start].compareTo(src[end])>0) {
swap(src,start,end);
}
return;
}
int middle=(start+end)/2;
mergeSort(src,dst,start, middle);
mergeSort(src,dst,middle+1, end);
mergeInOrder(src,dst,start,middle,middle+1,end);
}
private static ThreadLocal<Comparable<?>[]> mergeSortTemp=new ThreadLocal<Comparable<?>[]>();
#SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void mergeSort(T[] src) {
int length=src.length;
Comparable<?>[] temp=mergeSortTemp.get();
if ((temp==null)||(temp.length<length)) {
temp=new Comparable[length*3/2];
mergeSortTemp.set(temp);
}
mergeSort(src,(T[])temp,0,length-1);
}
However, I can think of two good reasons to implement a sorting algorithm as a class where you generate your own instance:
It lets you polymorphically pass around instances of sorting algorithms - this could be useful if e.g. you were creating a collection of sorting algorithms and wanted to run lots of benchmarks on them for example.
You can have private state in the sorter instance - this is useful for some sorting algorithms, e.g. having some pre-allocated arrays for temporary storage, and it makes sense to put it in a class instance if you want to be able to simultaneously use different sort instances from multiple threads - a static method implementation would need some form of synchronisation (e.g. see the use of the ThreadLocal in the code above).
I'm not sure if this is what you are struggling with ... but it is next to impossible to implement an algorithm that works both for reference types and (real) primitive types. The reason is the Java type system does not have a notional universal type that has the primitive types and Object as subtypes.
The normal workaround for this is to wrap the primitive types using their corresponding wrapper classes; e.g. Integer for int, Boolean for bool and so on. This allows you to implement (for example) a sorting algorithms that for for any Collection<T> or any <T>[].
This approach has performance / memory usage issues when applied to large arrays of (say) integers. Either you wear the performance hit, or you implement the algorithm and its supporting classes separately for each primitive type.
(I said next to impossible, because it is possible to abstract the comparison of a pair of array elements and swapping of a pair of array elements in a way that doesn't expose the actual element type in the interface; e.g.
public interface ArraySortAdapter {
public abstract int compareElements(Object array, int pos1, int pos2);
public abstract void swapElements(Object array, int pos1, int pos2);
}
and provide different implementations for different array types; e.g.
public class IntArraySortAdapter implements ArraySortAdapter {
public int compareElements(Object array, int pos1, int pos2) {
int[] intArray = (int[]) array;
if (intArray[pos1] < intArray[pos2]) {
return -1;
} else if (intArray[pos1] > intArray[pos2]) {
return +1;
} else {
return 0;
}
}
...
}
However, this is cumbersome and inefficient, to say the least ...)