Avoiding ambiguous methods caused by extends/implements - java

I have a convenience function which takes various types of objects and converts them in a serializable sort of way. For example, JSON-like objects are converted into JSON:
public static <T> String process( List<T> list ) {
if( list instanceof JSONArray ) {
return ((JSONArray) list).toJSONString( );
}
// stringify the list
}
public static String process( JSONAware object ) { // array, map, value, ...
return object.toJSONString( );
}
I'm using the org.json.simple library, so JSONArray extends ArrayList implements JSONAware. But that means that when I send a JSONArray, I get:
reference to process is ambiguous
I'm aware that it could equally go to either method, which is why I have equivalent implementations in both.
Clearly I could replace both functions with one which takes arbitrary Object types, but that would remove a lot of compile-time checking which I'm not happy about. I could also rename one of the functions to force a particular choice, but that complicates the API.
Is there some way I can force a particular choice, or make it obvious to the compiler that it doesn't matter which method gets called in these cases?

You can add
public static void process(JSONArray array) {
process((JSONAware) array);
}
while it is not a general solution, it would solve it in this case.
In this example
public class Example {
static class A {
}
interface B {
}
static class C extends A implements B {
}
static void process(A a) {
}
static void process(B b ) {
}
static void process(C c) {
System.out.println("process C called");
}
public static void main(String... ignored) {
process(new C());
}
prints
process C called

Related

Combining different types of command interfaces using generics/inheritance

I'm using the command pattern to encapsulate logic in "command" objects. I currently have two types of command interfaces:
public interface ObjectCommand
{
public void execute(Object object);
}
And one that makes the execute method return something:
public interface ObjectToArrayCommand
{
public Object[] execute(Object object);
}
I was wondering if I could combine these two different interfaces into one interface, or have both share the same superclass interface using generics and/or inheritance, for example something like:
public interface Command<T,U>
{
public U execute(T t);
}
The problem I have with this scheme is that I cannot make parameter "U" be "void/no object". Is there another way?
I know I can use subclasses to give parameters that are MORE specific, like "Object" can become "String" in a subclass and it would still compile. But again, "Object" cannot become "void".
The reason I want to combine these two into one interface is because it is easier (conceptually speaking) if EVERY command implements the same interface instead of having two (or more) types of commands that are being used together.
What you are looking is java.lang.Void , a placeholder for void keyword
public interface ObjectCommand
{
public void execute(Object object);
}
public interface ObjectToArrayCommand
{
public Object[] execute(Object object);
}
can be combined as
public interface Command<T, U> {
public U execute(T t);
}
class CheckGenerics {
public static void main(String[] args) {
Command<Object, Class<Void>> command1 = new Command<Object, Class<Void>>() {
#Override
public Class<Void> execute(Object t) {
return Void.TYPE;
}
};
Command<Object, Object[]> command2 = new Command<Object, Object[]>() {
#Override
public Object[] execute(Object t) {
return new Object[] { t };
}
};
Class<Void> a = command1.execute(new Object());
System.out.println(void.class == a); // prints true
Object[] b = command2.execute(new Object());
System.out.println(b);
}
Check the documentation of Void Class here ,the javadoc states that
The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void..Note that Void class cannot be instantiated,which is precisely what we want

Overloading / generics in Java

I want to run certain tests in Lists. The Lists can contain entirely different classes.
I have one method to check the consistency of the list - not null, not empty, no more than x elements. This is common to all the lists. Then I want to test each of the objects, using overloading.
The idea would be something like:
public static <T> void check(List<T> list) {
//do general checks
for (T element : list) {
check(element);
}
}
and then
public static void check(SomeType element) {...}
public static void check(SomeOtherType element) {...}
But I also had to add a method like this:
public static void check(T element) {...}
And this was called at runtime - not my other methods with the specific classes. Although the class was exactly the same. I'm evidently missing some generics understanding.
Now if I don't use the general method at all and try to solve it this way:
public static void check(List<SomeType> list) {...}
public static void check(List<SomeOtherType> list) {...}
Compiler error - "Method check(List) has the same erasure check(List) as another method..."
So is there any elegant solution for this? I could just use different method names but would like to know how it's possible without that.
Thanks!
This isn't something about generics that you're missing. Java does not have double dispatch. The call to check must be resolved at compile-time, and check(T) is the only match since the compiler can't tell if T is SomeType or SomeOtherType in a given scenario. It needs to choose one method to call that will work for all possible Ts.
This is sometimes solved using the visitor pattern.
The problem should be solved by the caller. When it instanciate your class with a concrete type for T, it should also pass an instance of Checker<T> with the same concrete type:
public class SomeClass<T> {
private List<T> list;
private Checker<T> checker;
public SomeClass(Checker<T> checker) {
this.checker = checker;
}
public void check() {
checker.check(list);
}
}
public interface Checker<T> {
public void check(List<T> list);
}
...
SomeClass<Foo> someClass = new SomeClass<Foo>(new Checker<Foo>() {
#Override
public void check(List<Foo> list) {
// do whatever you want here
}
});
You can use instanceof to dispatch:
public static <T> void check(List<T> list) {
for (T element : list) {
check(element);
}
}
public static void check(T t) {
if (t instanceof SomeType) {
SomeType someType = (SomeType) t;
// code for SomeType ...
} else if (t instanceof OtherType) {
OtherType otherType = (OtherType) t;
// code for OtherType ...
} else {
// we got a type that we don't have a method for
}
}
With generics, the type parameter is actually erased during compilation, and the list object don't know anything about the static type of the object it contains. Since it doesn't know it, it can not use overloading to call methods with different parameters, because Java doesn't support multiple dispatch.
You have then three choices:
Make your objects implement a Checked interface with a check method that does the check logic. Downside is that the check logic is now dispersed in several places and it is not practical if you have objects of classes you don't have control of.
Use instanceof to call explicitly the check methods according to the dynamic type of the object. Downside is you potentially end up with a big if/else block a bit harder to maintain.
Implement the visitor pattern. Downside is that you have to change the object classes too, but the check logic stay in a single place.
Since the type of the variable is lost in check(List<T> list) you have two options:
1. Do different things by checking runtime type
check(T element) {
if (element.getClass().equals(SomeType.class)) {
check((SomeType) element);
} elseif (element.getClass().equals(SomeOtherType.class)) {
check((SomeOtherType) element);
}
This can be made a little more sophisticated, for example by wrapping each check in a Callable and using a Map<Class, Callable>
This is similar to visitor pattern.
2. Calling a virtual method on the element to be checked itself
If the checking logic can be pushed to the object to be checked itself (this is not necessarily a bad thing) then you don't need to check types:
interface Checkable { void check(); }
class SomeType implements Checkable { .... }
class SomeOtherType implements Checkable { .... }
Then:
public static <T extends Checkable> void check(List<T> list) {
for (T element : list) {
element.check();
}
}
These are the only two options, any implementation has to be a variation on one of these

How do I define the return type inside a Java generics method?

I have a generic method, for example:
public static<T> T execute(...) {
...
}
How can I define what type T is in the method body? For example:
if (T == String) {
// do something with strings
// return string;
}
if (T == Bitmap) {
// do something with bitmap
// return bitmap;
}
I tried the following, but it didn't work:
T par = null;
if(par instanceof String) {
// do something with strings
// return string;
}
I tried declaring par like below, but that didn't work either.
T par = (T) null;
T par = (T) new Object();
You could probably do something like this:
public static <T> T execute(Class<T> t) {
if(String.class == t) {
}
}
If your code only supports a discrete set of data types, you don't want to use generics. As mentioned in the comments on the original post, this situation calls for overloaded method calls.
Consider, for example, a situation where you support Strings, Integers, and Doubles, but you don't have specific logic for other data types. You would define your methods such as:
public static String execute(String s) { ... }
public static Integer execute(Integer i) { ... }
public static Double execute(Double d) { ... }
public static Object execute(Object o) { ... }
The first three methods would define the logic for the three discrete data types you do support, while the final would define logic and/or error handling for any other data types you do not support. (Of course, this doesn't cover primitives not of int or double type, but this is just an example.)
Generics were initially added to Java to support a Collection knowing exactly what it contained. It was a way of guaranteeing that a List held only Strings by declaring it a List<String>, for example. This capability was then extended, but the basic concept held -- guarantee that if you put an unknown object of type X in, even if you don't know what X is at compile time, you can write logic for getting that same type X out. (This article is an interesting read, if out-dated.)
This does not mean it should be used where the logic applied in a method or class is dependent on the data type of the input. It should be used where it doesn't matter the incoming data type, and the same logic will be applied consistently across the unknown data type X. So if you have different logic for String than Doubles, you should not be using generics.
tl;dr:
Since the original post indicated different logic based on the data type of the input parameter, therefore, generics are not appropriate to be used. Overloading the execute method based on the supported data types should be used instead.
T Here is known as Type Parameters.
// here will define the type of T in the method go()
public interface Comparable<T> {
public int compareTo(T t) {
// do something...
}
}
For eg:
I am having a class Song, and i want to sort the songs on the basis of its title.
public class Song implements Comparable<Song> {
private String title;
public void compareTo(Song s) {
title.compareTo(s.title());
}
public void setTitle(String s) {
this.title = s;
}
public void getTitle() {
return this.title;
}
public String toString() {
return getTitle();
}
}
If you're splitting the functionality in code that way already, and the inputs are the same, you'd probably be well served with different functions. So instead of(using Jeshurun's answer)
public static <T> T execute(Class<T> t)
{
if(String.class == t) {
}
}
BitMap b = execute(BitMap.class);
You would have
public BitMap bitmapExecute(...)
{
commonWork();
//do bitmap stuff
}
public String stringExecute(...)
{
commonWork();
//do String stuff
}
BitMap b = bitmapExecute(...);
String s = stringExecute(...);
If there's a large block of common code, with only a small section different based on type, you can move that common code to its own function.
public someObject commonWork(...)
{
//Do common stuff
}
As long as you are making the decision about the type at compile time, you shouldn't have to have instanceof blocks.

Java How does this interface code actually work?

I've put together the code below using ideas giving to me by fellow members and then changing a couple of the containers. For the life of me i cant really get my head around some of this. The reason for the code is that i wished to pass a function as a parameter. The part of code i especially don't understand is:
doFunc(numbers, new IFunction() {
public void execute(Object o) {
Integer anInt = (Integer) o;
anInt++;
System.out.println(anInt);
}
});
I understand to some extent that we're using an interface to represent a function using an object (i think?). This is the full code:
public static void main(String[] args) {
Integer[] strArray = new Integer[]{1,2,3,4,5};
List numbers = Arrays.asList(strArray);
doFunc(numbers, new IFunction() {
public void execute(Object o) {
Integer anInt = (Integer) o;
anInt++;
System.out.println(anInt);
}
});
for(int y =0; y<numbers.size();y++){
System.out.println(numbers.get(y));
}
}
public static void doFunc(List c, IFunction f) {
for (Object o : c) {
f.execute(o);
}
}
public interface IFunction {
public void execute(Object o);
}
I guess i just need someone to go a little slower explaining it. Thanks for bearing with me.
That's an anonymous inner class. You could do as good as follows:
public static void main(String[] args) {
Integer[] strArray = new Integer[]{1,2,3,4,5};
List numbers = Arrays.asList(strArray);
doFunc(numbers, new ConcreteFunction());
for(int y =0; y<numbers.size();y++){
System.out.println(numbers.get(y));
}
}
public static void doFunc(List c, IFunction f) {
for (Object o : c) {
f.execute(o);
}
}
public interface IFunction {
public void execute(Object o);
}
public class ConcreteFunction implements IFunction {
public void execute(Object o) {
Integer anInt = (Integer) o;
anInt++;
System.out.println(anInt);
}
}
The difference is that a concrete class is reuseable while an anonymous inner class is not.
See also:
Java tutorial - Inner classes
The main concept here is that since the second object you're passing to doFunc is anonymous, you don't need to instantiate an object here - just the interface. Here's what each part of the code is saying:
public interface IFunction {
public void execute(Object o);
}
This says that any object which implements the interface IFunction has one method, execute, which it runs on another Object.
public static void doFunc(List c, IFunction f) {
for (Object o : c) {
f.execute(o);
}
}
This function takes a List c and any Object which implements IFunction, then runs the execute method - guaranteed to be in the second object by the IFunction interface - over all the objects in c.
doFunc(numbers, new IFunction() {
public void execute(Object o) {
Integer anInt = (Integer) o;
anInt++;
System.out.println(anInt);
}
});
This snippet from main takes a list of numbers and creates an anonymous object in-place which implements the IFunction interface. Since it's not any concrete object type, it doesn't need to have any other methods, just execute, which it defines inline.
The end result is that your IFunction object declared inside the call to doFunc is effectively a functor - it's a throwaway object that encapsulates a function, which can be run over a list of objects.
IFunction, in this case, specifies an interface that anyone who implements the interface must define.
public void execute(Object o);
This means that any object that is an IFunction has this method. The anonymous IFunction being defined in your example casts it's argument to an integer and then increments it and prints the value.
As doFunc requires a List of objects and an object that implements IFunction, the call in main passes numbers, a list of numbers, and the anonymous IFunction which increments them and prints their value.
doFunc then takes these objects in the list and passes them as an argument to the IFunction f.

Java generics (template) specialization possible (overriding template types with specific types)

I'm wondering what are the options to specialize generic types in Java, i.e. in a templated class to have specific overrides for certain types.
In my case I was a generic class (of type T) to return null usually, but return "" (the empty string), when T is the String type, or 0 (zero) when its the Integer type, etc.
Merely providing a type-specific overload of a method produces a "method is ambiguous" error:
e.g.:
public class Hacking {
public static void main(String[] args) {
Bar<Integer> barInt = new Bar<Integer>();
Bar<String> barString = new Bar<String>();
// OK, returns null
System.out.println(barInt.get(new Integer(4)));
// ERROR: The method get(String) is ambiguous for the type Bar<String>
System.out.println(barString.get(new String("foo")));
}
public static class Bar<T> {
public T get(T x) {
return null;
}
public String get(String x) {
return "";
}
}
}
Is the only option to subclass the generic class with a specific type (see StringBar in the following example?
public static void main(String[] args) {
Bar<Integer> barInt = new Bar<Integer>();
StringBar barString2 = new StringBar();
// OK, returns null
System.out.println(barInt.get());
// OK, returns ""
System.out.println(barString2.get());
}
public static class Bar<T> {
public T get() {
return null;
}
}
public static class StringBar extends Bar<String> {
public String get() {
return "";
}
}
}
Is this is the only way, it's a bit of a pain to have to create a subclass for every type I want to specialize instead of an overload of get() in the Bar class.
I'm guessing I could check the instanceof in the Bar.get() method, e.g.
T get(T t) {
if (t instanceof String) return "";
if (t instanceof Integer) return 0;
else return null;
}
However I've been taught to avoid instanceof and use polymorphism when possible.
All things considered, the concensus appears to be that the StringBar method mentioned in the question is the only way to go.
public static class StringBar extends Bar<String> {
public String get() {
return "";
}
}
Generics in Java are very different from templates in C++ in this respect. It is not possible to write a specific version of a generic class to do something different for a particular case, as C++ can do. It is also not possible to determine at run time what T is - this is because that information is not passed into the byte code (object code) and so doesn't even exist at runtime. This due to something called "type erasure".
BarString and BarInt would be the obvious way of doing this, but there are improvements you can make. For example you can write a generic Bar to cover the common cases, and then write specialized BarString and BarInt to implement special cases. Ensure that the instances can only be created through a factory, which takes the class of the object to be processed:
class Bar<T> {
class BarString extends Bar<String> {
// specialist code goes here
}
static Bar<T> createBar(Class<T> clazz) {
if (clazz==String.class) {
return new BarString();
} else {
return new Bar<T>;
}
That probably won't compile, but I don't have the time to work out the exact syntax. It does illustrate the principle.
The compiler is actually correct, because the following code is compile-time checked (Bar<String> barString = new Bar<String>();) when compiled, from
public static class Bar<T> {
public T get(T x) {
return null;
}
public String get(String x) {
return "";
}
}
to
public static class Bar<String> {
public String get(String x) {
return null;
}
public String get(String x) {
return "";
}
}
and is ambiguous as you can't have 2 identical methods with the same return types and the same parameter arguments.
See an explanation by Jon Skeet's:
What is the concept of erasure of generics in java?
Java Generics - Types erasures - when and what happens?
You can subclass Bar<T> and create StringBar (note I removed the static keyword) and override get() method.
public class BarString extends Bar<String> {
#Override
public String get(String x) {
return "";
}
}
Generics in Java aren't made for specialization. They're made for generalization! If you want to specialize for certain types, you should be specializing...through a subclass.
Often you don't need to do something in a specialized manner however. Your StringBar example is kind of contrived because you could have this:
public class Bar<T> {
private final T value;
public T get() {
return value;
}
}
I don't see why you need to specialize for a String here.

Categories