Generics and interface // do I have to use them together? - java

I'm learning Java but I believe that this question is not language-specific. Sorry if someone has already asked the question, I'm not sure how to phrase this in a search query.
Shortly after implementing a few generic methods for myself, I came to realize that: Since Generics allow you to use parameters of more types, some of the arguments that the user puts in might not have the functionality that you expect. A "hack" that I came up with is to restrict the parameter input type using an interface as an Upper Bound. For popular functionalities like compareTo(), this is fine as the interface Comparable is popular enough, but I find it awkward that I have to write a custom interface just to get my generics to work.
Here's some code to help make sense of my nonsense. Consider the following non-working code that attempts to count unique elements in a collection of generic datatype:
public static <T> int countUnique(Collection<T> c) {
int count = 0;
for(T t : c) {
count += (t.isUnique()) ? (1) : (0);
}
return count;
}
An obvious problem arises when the compiler complains that the objects t do not have (or rather, the compiler cannot determine that they have) the method isUnique(). My solution:
public interface unique {
public boolean isUnique();
}
public static <T extends unique> int countUnique(Collection<T> c) {
int count = 0;
for(T t : c) {
count += (t.isUnique()) ? (1) : (0);
}
return count;
}
Question is: Do I have to do this every time? Isn't it clunky? Is there a standard practice that I should instead be adopting?

This is the main principle of OOP. You're working with objects and objects have behaviors (methods).
Every method knows what objects it is working with. For example, your method compares 2 numbers. If you pass 1 number and 1 Array of Strings it won't be able to compare them.
You don't have to use interface as upperbound in your example.It can be your class and in case you have 2 classes that have similar behavior then you create an interface and change your method above to use that interface.
Also, by Java Code Conventions interface name should start from capital letter.

Related

Proper use of generics in abstract java class?

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.

How do I make a function with overloading? [duplicate]

This question already has answers here:
Why is method overloading and overriding needed in java? [duplicate]
(2 answers)
Closed 4 years ago.
I asked on SE how to make a function that accepts different kinds of variables. People have told me to "overload".
My question: how do I use overloading to make a function that will accept multiple data types (int bool string) as it's input?
Also, what are the advantages and disadvantages of overloading? Is it related to "overloading my computer"?
Overloading is a concept that doesn't hurt your computer but sometimes it makes your head hurt. Not really. Overloading is just writing multiple implementations of a method with the same name but different parameter types. It requires the programmer to write code like this. Notice the return types are the same.
public int SomeMethod(int someValue)
{ //one implementation for ints }
public int SomeMethod(String someValue)
{ //another implementation for strings}
Which method is invoked depends on on the argument type. The method invoked here is the one for integer arguments:
int result = SomeMethod(5);
Another way of doing this is using Generic Methods. This is a little advanced for the question asked, but it might be what you're looking for. The Oracle Java Documentation is a good place to start.
Try looking into generic types: https://docs.oracle.com/javase/tutorial/java/generics/boundedTypeParams.html
Overloading is a concept. It will not affect your computer or your code. It is simply the fact of declaring multiple methods in your class with the same name but different arguments.
For example:
private int doSomething(int anInteger) {
// do something with an integer
}
private int doSomething(float aFloat) {
// do something with a float
}
Doing this will allow you to use the same method name on different parameter types, but have different method implementation.
public void myFunction(String s){ ... }
public void myFunction(int i){ ... }
public void myFunction(bool b){ ... }
Really you should be able to google "java overloading" or something instead of posting on here for this. Googling is a top developer skill. Read the documentation, or your textbook or something.

Is it possible to put methods in arrays to be randomized?

I'm using Java, and wondering if it's possible to put methods directly into arrays as elements. Something like:
...[] arrayName = {herp(), derp(), jinkies()};
When I looked this up prior, some people mentioned "reflection," but I don't know what this is (I'm very new to programming). Is there a simple way to put methods into arrays (my goal is to spit them out randomly with a Random, and eventually terminate with a String parameter in each method named "quit" or something)? If not, how does reflection work for this circumstance (if at all)?
I am NOT only asking what reflection is. My exact (main) question is "Is it possible to put methods into arrays," and if it is, how is that done? What is the syntax for it?
Thank you for your time
It is not possible in java to assign function as object.
But still you can use use lambda expression or similar structure for this. Which will not actually assign functions but you can use it like one.
Create a functional interface
#FunctionalInterface
interface MyFunction {
public void fun();
}
Use lambda expressions to initialize array of that functional interfaces
MyFunction[] functions = new MyFunction[]{
() -> System.out.println("I am herp"),
() -> {
int a = 2;
int b = 3;
System.out.println(a + b);
}
};
Use the array like array of functions.
functions[0].fun();
you can make a class for every method and make an array of classes.
also for it to be easier do it with inner classes and it will be more readable.
(of course every class will share the same interface)

Reflection Casting and Overloaded Method Dispatching in Java

Note that all the code is a simplified example in order to only communicate the core ideas of my question. It should all compile and run though, after slight editing.
I have several classes which all implement a common interface.
public interface Inter{}
public class Inter1 implements Inter{}
public class Inter2 implements Inter{}
In a separate class I have a list of type Inter, which I use to store and remove Inter1 and Inter2 types, based on user input.
java.util.ArrayList<Inter> inters = new java.util.ArrayList<Inter>();
I also have a family of overloaded methods, which deal with how each implementation interacts with each other, along with a default implementation for 2 "Inter"s.
void doSomething(Inter in1, Inter in2){
System.out.println("Inter/Inter");
}
void doSomething(Inter1 in1, Inter1 in2){
System.out.println("Inter1/Inter11");
}
void doSomething(Inter2 in1, Inter1 in2){
System.out.println("Inter2/Inter1");
}
The methods are periodically called like so:
for(int i = 0; i < inters.size() - 1; i++){
for(int o = i+1; o < inters.size(); o++){
Inter in1 = inters.get(i); Inter in2 = inters.get(o);
doSomething(in1.getClass().cast(in1), in2.getClass().cast(in2));
System.out.println("Class 1: " + in1.getClass().getName());
System.out.println("Class 2: " + in2.getClass().getName());
}
}
An example output from this is:
Inter/Inter
Class 1: Inter
Class 2: Inter
Inter/Inter
Class 1: Inter
Class 2: Inter1
Inter/Inter
Class 1: Inter1
Class 2: Inter1
Looking at the output, it is clear that doSomething(Inter in1, Inter in2) is called, even in cases when other methods should be called. Interestingly, the class names outputted are the correct ones.
Why does java have static method overloading when the class types are determined at runtime using reflection?
Is there any way to get Java to do this? I know I can use reflection and Class.getMethod() and method.invoke() to get the results I want, but it would be so much neater to do so with casting.
I realize that questions about similar concepts have been asked before, but while all of the answers were informative, none satisfied me.
Double dispatch looked like it would work, but that would mean reworking a lot of code, since I use this type of thing often.
It looks to me like we're talking about what's going on with:
doSomething(in1.getClass().cast(in1), in2.getClass().cast(in2));
Based on your surprise that the type that is being output is always Inter, it seems you're a little confused on what's going on here. In particular, you seem to think that in1.getClass().cast(in1) and in2.getClass().cast(in2) should be forcing a different overload because of their differing runtime type. However, this is wrong.
Method overload resolution happens statically. This means that it happens based on the declared types of the two arguments to the method. Since both in1 and in2 are both declared as Inter, the method chosen is obviously void doSomething(Inter in1, Inter in2).
The takeaway here is that in1 is declared as an Inter. This means that in1.getClass() is essentially the same as Inter.class for the purposes of static analysis -- getClass simply returns a Class<? extends Inter>. Therefore, the casts are useless, and you're only ever going to get the first overload.
The Java Language Specification (JLS) in section 15.12 Method Invocation Expression explains in detail the process that the compiler follows to choose the right method to invoke.
There, you will notice that this is a compile-time task. The JLS says in subsection 15.12.2:
This step uses the name of the method and the types of the argument expressions
to locate methods that are both accessible and applicable
There may be more than one such method, in which case the most specific one is chosen.
In your case, this means that since you are passing two objects of type Integer, the most specific method is the one that receives exactly that.
To verify the compile-time nature of this, you can do the following test.
Declare a class like this and compile it.
public class ChooseMethod {
public void doSomething(Number n){
System.out.println("Number");
}
}
Declare a second class that invokes a method of the first one and compile it.
public class MethodChooser {
public static void main(String[] args) {
ChooseMethod m = new ChooseMethod();
m.doSomething(10);
}
}
If you invoke the main, the output says Number.
Now, add a second more specific method to the ChooseMethod class, and recompile it (but do not recompile the other class).
public void doSomething(Integer i) {
System.out.println("Integer");
}
If you run the main again, the output is still Number.
Basically, because it was decided at compile time. If you recompile the MethodChooser class (the one with the main), and run the program again, the output will be Integer.
As such, if you want to force the selection of one of the overloaded methods, the type of the arguments must correspond with the type of the parameters at compile time, and not only at run time as you seem to expect in this exercise.

Java - Implementing sorting algorithms the 'right' way

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 ...)

Categories