Java How does this interface code actually work? - java

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.

Related

Interfaces as parameters (Restrictions)

I came across an AP CSA question which had me puzzled for a while. It was basically an incomplete method that looked like this:
public static void methodMan(Comparable c) {.....}
The question first asked if it was valid to use the comparable interface in the parameter listing, then it asked if there were any restrictions on the comparable object. I was stuck between the choices that said either the object c that is being passed needs to be casted or initialized as a comparable or the object c could be any object that implements the comparable interface. Which one is it, and if it isn't either, what would be a restriction on the object c?
Yes it is valid to use interfaces as a parameter in methods and yes object c can be any object that implements the interface. The only caveat to the second portion is if there is a special method that needs to be invoked that the interface does not implement then you will need to cast it to the class first to get the method For Example:
public class MyComparable implements Comparable<String> {
private String item;
public MyComparable(String item) {
this.item = item;
}
#Override
public int compareTo(String o) {
return this.item.compareTo(o);
}
public Integer doThis() {
return 100;
}
public Integer compareSample(Comparable<String> c) {
if (c instanceof MyComparable) {
return ((MyComparable)c).doThis();
}
return c.compareTo(this.item);
}
}
compiles like a charm:
public static void methodMan (Comparable c) {
out.println ("we ignore c");
}
public static void main (String args[])
{
Comparable c1 = new String ();
methodMan (c1);
methodMan ((Comparable) c1);
String s2 = new String ();
methodMan (s2);
methodMan ((Comparable) s2);
}
and runs like a charm.

Make a copy of a List with abstract type to a List with specific type

first of all my code below just delivers an abstract view of my classes so that you can easily understand what my question is about :) -so also no equals, hashcode.
I have an ABC extended from Observable which has a List of AbstractObservers
Then I have some classes B and C inherit from AbstractObservers. AbstractObservers implements Observer.
The focus is now at the Recover class.
With the method recover() I try to return a List with the concrete type (B or C) instead of AbstractObservers.
I am not satisfies with my solution, I think it could be better, easier?
Have you any idea how I could solve that problem better? The Abstract classes must stay due to Hibernate.
Thank you in advance
public abstract class ABCObservable extends Observable {
List<AbstractObserver> abstractObserverList = new LinkedList<>();
public List<AbstractObserver> getAbstractObserverList() {
return abstractObserverList;
}
#Override
public synchronized void addObserver(Observer o) {
super.addObserver(o);
abstractObserverList.add((AbstractObserver) o);
}
}
AbstractObserver
public abstract class AbstractObserver implements Observer {
#Override
public void update(Observable o, Object arg) {
}
}
B
public class B extends AbstractObserver {
}
C
public class C extends AbstractObserver {
}
Recover
public class Recover {
public List<? extends AbstractObserver> recover(ABCObservable abcObservable) {
List<AbstractObserver> returnList = new LinkedList<>(); //does that delivers a List with AbstractObserver or B or C?
if (abcObservable.getAbstractObserverList().get(0) instanceof B) {
returnList = new LinkedList<>();
returnList.addAll(abcObservable.getAbstractObserverList());
} else if (abcObservable.getAbstractObserverList().get(0) instanceof C) {
returnList = new LinkedList<>();
returnList.addAll(abcObservable.getAbstractObserverList());
}
return returnList; // returns a List with B or C elements
}
}
In Java, you can't convert a list to a new type, what you can do, however, is create a new one and add the values to it. If you use a generic method, you should be able to accomplish this. I haven't test this code, but theoretically it should work:
public <T> List<T> recover(T abcObservable) {
List<AbstractObserver> list = abcObservable.getAbstractObserverList();
List<T> returnList = new LinkedList<>();
returnList = new LinkedList<>();
for(AbstractObserver a : list) {
if(a instanceof T) {
returnList.add(a);
}
}
return returnList;
}
Instead of using a defined class, this snippet uses T, you can find out more about how Java Generic Methods work on this Java Tutorial by Oracle.
EDIT: I think I'm confused about what you are asking for, this doesn't answer your question, if I understand it correctly.

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

Avoiding ambiguous methods caused by extends/implements

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

Java - Interfaces and methods

I'm looking through some interfaces at the moment and I'm wondering why this does not work:
interface I {
public void doSomething(String x);
}
class MyType implements I {
public int doSomething(String x) {
System.out.println(x);
return(0);
}
}
Basically, why can't I implement the method in the interface? THey have different signatures as one has a return type? Isn't the name, parameters and return type what make a method unique?
You can't have different return types. Imagine the following
class Foo implements I {
public int doSomething(String x) {
System.out.println(x);
return(0);
}
}
class Bar implements I {
public void doSomething(String x) {
System.out.println(x);
return;
}
}
List<I> l = new ArrayList();
l.add(new Foo());
l.add(new Bar());
for (I i : l) {
int x = i.doSomething(); // this makes no sense for Bar!
}
Therefore, the return types must also be the same!
Yeah, you're basically correct. Java doesn't allow overloading methods by return type, which would be neat. However, the interface return type must still match.
The method signature consists of the method's name and the parameters types, so you can't declare more than one method with the same name and the same number and type of arguments, because the compiler cannot tell them apart.
Think of a typical use for interfaces: e.g. anything implementing the java List interface must implement boolean add(Object o)
The caller is probably going to do something like:
if (!impl.add(o)) { /* report error */ }
If you were allowed to change the return type, you'd hit all types of problems.
void add(Object o)
if (!impl.add(o)) { // ... your method returns void, so this makes no sense
float add(Object o)
if (!impl.add(o)) { // float to boolean ? are you sure that is what you meant?

Categories