Type Inference in Method Reference - java

I recently put my hands on Java 8 and tried using Method References.
I was trying different kinds of Method references and got stuck in the type "Reference to an Instance Method of an Arbitrary Object of a Particular Type".
String[] arr = {"First", "Second", "Third", "Fourth"};
Arrays.sort(arr, String::compareToIgnoreCase);
This works perfectly well. But when I try to refer a method of a user defined class through its type :
Demo2[] arr = {a, b};
Arrays.sort(arr, Demo2::compare);
This displays compile-time error as "Non-static method cannot be referenced from a static context".
Here's the Demo2 class :
public class Demo2 implements Comparator<Demo2> {
Integer i;
Demo2(Integer i1){
i = i1;
}
public Integer getI() {
return i;
}
#Override
public int compare(Demo2 o1, Demo2 o2) {
return o1.getI().compareTo(o2.getI());
}
}

As greg-449 pointed to you, your code has a bug.
By making a method reference like YourObjet::yourMethod you make a static reference to the method of the instance. So the method will be called for each object and thus the signature needs to be different than the earlier
A code that will compile will be of the following form :
Demo2[] demos = {a, b};
Arrays.sort(demos, Demo2::compareTo);
public class Demo2 {
Integer i;
Demo2(Integer i1){
i = i1;
}
public Integer getI() {
return i;
}
public int compareTo(Demo2 other) {
return this.getI().compareTo(other.getI());
}
}
But as RealSkeptic pointed out, this is not the correct way to implement and objet comparison. You should give the Arrays.sort method a comparator instead :
Arrays.sort(demos, (obj1, obj2) -> obj1.getI().compareTo(obj2.getI()));

The Comparator interface required for Arrays.sort(T[],Comparator<T>) has a method that accepts two object references of the same type T, and returns an integer.
There is a bit of "magic" in method references. What Java does is wrap the method in such a way that it will fit the interface requirement.
The interface, of course, doesn't require a static method. But the wrapping can create a method that calls a static method, as in the Tutorial's first example:
public static int compareByAge(Person a, Person b) {
return a.birthday.compareTo(b.birthday);
}
It wraps it in such a way that you get something similar to
new Comparator<Person>() {
#Override
public int compare(Person a, Person b) {
return Person.compareByAge(a,b);
}
}
Which satisfies the interface.
But in the example in the section "Reference to an Instance Method of an Arbitrary Object of a Particular Type", it wraps it differently. It needs a method that receives two strings, but it has a method that only receives one. This is how String::compareToIgnoreCase is defined:
public int compareToIgnoreCase(String str)
But in this case, it's an instance method. What Java does now is, because this method belongs to an object of type String, and accepts an object of type String it is easy to build a "wrap" around it that makes it into a method that accepts two objects, much like the lambda expression:
(String a, String b) -> {
return a.compareToIgnoreCase( b );
}
Or, if we imagine a formal wrapping as a Comparator:
new Comparator<String>() {
#Override
public int compare(String a, String b) {
return a.compareToIgnoreCase(b);
}
}
So, the fact that it's an instance method that belongs to type T, accepts type T and returns int allows Java to wrap it appropriately so it fits the Comparator interface.
But int compare(Demo2 o1, Demo2 o2) doesn't fit that pattern. It accepts two parameters. If a method accepts two parameters, it must be a static method to fit the wrapping rules - there is no way to pass the "this" object into the Comparator interface. So it tries to wrap it as a static method, and fails, as it is not a static method.
Bottom line: you got the error, because for this particular type of method reference, you need an instance method with only one parameter of the same type as the class.
As #Holger mentions in a comment, if you have a new class you are building, you shouldn't put a comparison method in it specifically for this sort of sorting task. If the class has a natural ordering, make it Comparable and use Arrays.sort(Object[]). If it doesn't, and you need to sort it sometimes based on any of its attributes, use a lambda expression or Comparator.comparing(Demo2::getI) which makes better use of an existing getter for the specific purpose of comparison.

As a convention, Comparator<T> is implemented with a lambda expression and it looks very odd to implement it in a class.
Demo2[] array = new Demo2[2];
array[0] = new Demo2(12);
array[1] = new Demo2(32);
Comparator<Demo2> demo2Comparator = (e1,e2)->e1.getI().compareTo(e2.getI());
Arrays.sort(array, demo2Comparator);

Related

How does java's double colon operator refer non-static method using class name

I have written a code like this:
public class MyClass implements Comparable{
int value;
MyClass(int value){
this.value = value;
}
public static void main(String[] args) {
MyClass obj1 = new MyClass(30);
MyClass obj2 = new MyClass(5);
MyClass obj3 = new MyClass(15);
List<MyClass> classList = new ArrayList<>();
classList.add(obj1);
classList.add(obj2);
classList.add(obj3);
List<MyClass> list2 =classList.stream().sorted(MyClass::compareTo).collect(Collectors.toList());
list2.stream().forEach(x-> System.out.println(x.value));
}
#Override
public int compareTo(Object o) {
MyClass obj = (MyClass)o;
if(this.value<obj.value){
return +1;
}else return -1;
}
}
This code compiles successfully gives me the correct output as expected-
30
15
5
I have 2 questions
How are we able to refer non-static method compareTo using Myclass(classname)? Shouldn't we be expected to use object of my class to refer compareTo()?
How are we able to use compareTo() method which takes only 1 parameter, whereas sorted() expects Comparator Interface whose abstract class compare() takes 2 parameters?
The Stream method sorted takes a Comparator<T> as parameter. This is a functional interface, so you can use a lambda expression or method reference as parameter that adheres to this interface. The method signature is as follows:
int compare(T var1, T var2);
So, for example, the following lambda expression is valid:
(MyClass a, MyClass b) -> a.compareTo(b)
A method reference can refer to static methods, but in this specific context, the type of the method reference can also replace the first parameter, so the following expression is equivalent to the above:
MyClass::compareTo
Similarly, you can do the following:
(String a, String b) -> a.equals(b)
String::equals
Or things like this:
(String a) -> "b".equals(a)
"b"::equals
List list2 =classList.stream().sorted(MyClass::compareTo).collect(Collectors.toList());
In this line you have used stream.sorted which still is a stream then you have called compareTo method in MyClass for each stream element.

Java static method seems to be set to instance of a type? (syntax)

After doing some research on Comparables and Comparators I ran across some funny syntax that looks useful (and that I don't understand).
Example:
public static Comparator<Type> TypeComparer = new Comparator<Type>() {
public int compare(Type a, Type b) {
return a.compareTo(b);
}
}
I'd really like to know what is going on here. I would never think to use the = operator when defining a method. It is a method right? Or a variable containing a method perhaps?
How would I use this object? What should I expect to be returned if I can call it?
If you'd like to look at the original example see Blog Post
TypeComparer is not a static method, it's a static field.
Let's walk through the syntax part-by-part:
public static Comparator<Type> TypeComparer = ... declares a field. Its name is TypeComparer, and type is Comparator<Type>. Since Comparator<T> is an interface, the field accepts instances of any class implementing the interface.
new Comparator<Type>() { ... } This syntax defines a new class and creates its instance at the same time. The newly defined class has no name (it's called an anonymous inner class) and its only instance is assigned to TypeComparer
public int compare(Type a, Type b) { ... } This is a method of the anonymous comparator class. It implements the method from the Comparator<T>, which is required to complete the class.
Users of your class can use the instance of Comparator<Type> without knowing its exact type, because they can program to its interface (i.e. call its compare(...) method).
Note: Starting with Java 8 you can shorten the above example to a single line:
public static Comparator<Type> TypeComparer = (a, b) -> {return a.compareTo(b);};
How would I use this object? What should I expect to be returned if I
can call it?
You use anonymous class as you don't need to create a named class.
They enable you to declare and instantiate a class at the same time.
It makes sense only if you want to define an implementation that is used only in the frame of the class that declares it.
Otherwise, creating a named class is more relevant as it allows to make the class more easily/naturally usable by client classes.
With a named class (public or whatever access modifier) you write :
public class MyComparator implements Comparator<Type> {
public int compare(Type a, Type b) {
return a.compareTo(b);
}
}
And then you can use it :
Collections.sort(myList, new MyComparator();
With anonymous class you write :
Comparator<Type> typeComparer = new Comparator<Type>() {
public int compare(Type a, Type b) {
return a.compareTo(b);
}
};
and use the variable as any variable :
Collections.sort(myList, typeComparer);
You could even shorten it by eliminating the variable :
Collections.sort(myList, new Comparator<Type>() {
public int compare(Type a, Type b) {
return a.compareTo(b);
}
});
As you see it makes less code but it is not very readable.
Java 8 addresses this issue.
You could use a lambda expression :
Collections.sort(myList, (a, b) -> a.compareTo(b));
Or a method reference (lambda expression shorter version) :
Collections.sort(myList, Comparable::compareTo);
Or the Comparator.comparing() static method :
Collections.sort(myList, Comparator.comparing(Comparator.naturalOrder());

Passing generic class type in java

I'm trying to see if the template expression pattern can be imitated in Java, to do optimizations like loop fusion.
As an example, I port the c++ classes found in this expression template example to java classes: https://en.wikipedia.org/wiki/Expression_templates#Motivation_and_example
First, a template class VecExpression<E> representing a vector expression. It uses a template parameter E and takes the class type of E as a constructor parameter. It then creates a private variable thisAsE set to this cast to the class type of E
public abstract class VecExpression <E> {
private VecExpression thisAsE;
public VecExpression(Class<E> type) throws Exception {
if(type.isInstance(this)) {
thisAsE = (VecExpression)type.cast(this);
}
else {
throw new Exception("Class type must extend VecExpression");
}
}
public double get(int i) {
return thisAsE.get(i);
}
public int size() {
return thisAsE.size();
}
}
Second, a class Vec extending VecExpression<Vec> which passes Vec.class into the super constructor and implements the get() and size() methods called in the VecExpression<E> class.
public class Vec extends VecExpression<Vec> {
private double[] elems;
public <E> Vec(VecExpression<E> expression) throws Exception {
super(Vec.class);
for(int i = 0; i < expression.size(); ++i) {
elems[i] = expression.get(i);
}
}
public Vec(double[] elems) throws Exception {
super(Vec.class);
this.elems = elems;
}
public double get(int i) {
return elems[i];
}
}
And third, a template class VecSum<E1, E2> which extends VecExpression<VecSum<E1, E2>, and uses its get() method to return the sum of two VecExpression<E>s. The type is passed as an explicit parameter Class<VecSum<E1, E2>> type.
public class VecSum <E1, E2> extends VecExpression<VecSum<E1, E2>> {
private VecExpression u;
private VecExpression v;
public VecSum(Class<VecSum<E1, E2>> type, VecExpression<E1> u, VecExpression<E2> v) throws Exception {
super(type);
if(u.size() != v.size()) {
throw new Exception("Vectors must be of the same size");
}
this.u = u;
this.v = v;
}
public double get(int i) {
return u.get(i) + v.get(i);
}
public int size() {
return v.size();
}
}
Finally, we use the expression template to generate a class that can add three vectors with a single pass through memory.
public class Main {
public static void main(String[] args) throws Exception {
Vec a = new Vec(new double[] {1, 2, 3});
Vec b = new Vec(new double[] {1, 2, 3});
Vec c = new Vec(new double[] {1, 2, 3});
VecSum<Vec, Vec> ab = new VecSum<Vec, Vec>(VecSum<Vec, Vec>.class, a, b);
VecSum<VecSum<Vec, Vec>, Vec> abc = new VecSum<>(VecSum<VecSum<Vec, Vec>, Vec>.class, ab, c);
}
}
EDITED as per Louis Wasserman's comment
However, the class types passed into the VecSum constructor don't work because the expression is trying to get a class from a parameterized type. Louis pointed out that implementations of a generic class don't compile to different classes like they do in c++. How would you pass their type, or is there another approach to the expression template pattern?
What you're trying to do won't work in Java, at least insofar as you're trying to use to get a compile-time optimization through the use of a Java generic. The reason is that, unlike a C++ template, the Java generic does not get resolved at compile-time. Since the compiler is not resolving the type at compile-time it cannot use anything about it to make a compile-time optimization. The byte code created by the Java compiler, in some sense, goes the other way "erasing" the generic information completely. If your Java class is class C<A> then everywhere the type A appears in your code, it is replaced by the class Object. If your Java class is class D<E extends F> then everywhere that E appears in your code is replaced by F.
In that case, you might ask why the generics at all. The answer is that before the complier throws away the parameter, it does do type-safe checking on inputs and it implicitly inserts a cast on method returns. That's a convenience that was added to Java a few versions back, but the Java container classes like ArrayList existed. It's just that you didn't have type-safety in the same way that you do now since the inputs were explicitly Object (letting you put in any object even if you knew it was supposed to only contain, say, String objects and forcing you to cast the result of get to, say, a String explicitly).
This is in contrast to a C++ template where the compiler creates a class definition from the template and compiles that class. That class can then be compiled as any other class, including potentially using optimizations that are specific to the value of the template parameter. Moreover, template specialization in C++ allows for template metaprogramming more generally since it allows you to create a base case for recursion in the template parameters.
(You cannot have "generic specialization" in any analogous sense in Java for the reason noted above - The Java compiler is throwing out the generic parameter already, so your "specialized" class - if you tried to define such a thing - would be the same as the "generic" class.)
Finally, as regards your examples, keep in mind that Class with a capital 'C' in Java is a class like any other, including that it derives from Object. This isn't going to get you around the compile-time vs. runtime differences between the C++ templates and the Java generics.

What is the purpose of List<Void>?

I didn't even know this was doable, but I saw while perusing some code online a method with a signature like this:
public List<Void> read( ... )
... What? Is there ever a reason to do this? What could this List even hold? As far as I was aware, it's not possible to instantiate a Void object.
It is possible that this method signature was created as a by-product of some generic class.
For example, SwingWorker has two type parameters, one for final result and one for intermediate results. If you just don't want to use any intermediate results, you pass Void as the type parameter, resulting in some methods returning Void - i.e. nothing.
If there were a method List<V> returnAllIntermediateResults() in SwingWorker with Void as the type parameter V, it would have created a method just like you posted in your question.
The code would be perfectly valid. You can instantiate any implementation of the List interface (e.g. ArrayList) with type parameter Void. But the only value a Void type can have is null. So the list could not hold anything else but nulls, if the implementation allows null elements.
One case in which it may be useful is if you wanted to return a collection of return values from a function. Say
static List<T> forEach(Func<A,T> func, List<A> items) {
List<T> ret = new List<T>();
for(int i = 0; i< items.length; i++) {
ret.add(func.call(items[i]);
}
return ret;
}
public static void main() {
...
List<Void> boringResult =
forEach(
new Func<Void, Integer> {#override Void call(Integer i) {...}});
}
Not that useful but you could see a case where it was required.
List<Void> is weird. It can only have null elements, since you can't create an object of type Void. I don't think there is a practical use for such a thing.
Void is part of java.lang. It's not a special keyword or anything. It's a "pseudo-type" (according to the docs) used to as a place-holder to represent the Class object corresponding to void, as in Class<Void>. From the docs for Class:
The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
The Void class exists mainly for the sake of the last part of this, so you can write:
Class<Void> voidType = void.class; // == Void.TYPE
just like you can write:
Class<Integer> intType = int.class; // == Integer.TYPE
I agree, it's odd.
I can see a use for it if you want to extend a generic class and return void from a method. I've bumped into a case were I want to use int and had to use Integer because java generics don't like primitive types.
public interface ObjectUserPool<E, T> {
public E useObject(T o);
}
public class NonReturningObjectUserPool extends ObjectUserPool<Void, Integer> {
public Void useObject(Integer i);
}
I think this is what the java API is saying, though to be honest I can't really find a use for NonReturningObjectUserPool.

What's the nearest substitute for a function pointer in Java?

I have a method that's about ten lines of code. I want to create more methods that do exactly the same thing, except for a small calculation that's going to change one line of code. This is a perfect application for passing in a function pointer to replace that one line, but Java doesn't have function pointers. What's my best alternative?
Anonymous inner class
Say you want to have a function passed in with a String param that returns an int.
First you have to define an interface with the function as its only member, if you can't reuse an existing one.
interface StringFunction {
int func(String param);
}
A method that takes the pointer would just accept StringFunction instance like so:
public void takingMethod(StringFunction sf) {
int i = sf.func("my string");
// do whatever ...
}
And would be called like so:
ref.takingMethod(new StringFunction() {
public int func(String param) {
// body
}
});
EDIT: In Java 8, you could call it with a lambda expression:
ref.takingMethod(param -> bodyExpression);
For each "function pointer", I'd create a small functor class that implements your calculation.
Define an interface that all the classes will implement, and pass instances of those objects into your larger function. This is a combination of the "command pattern", and "strategy pattern".
#sblundy's example is good.
When there is a predefined number of different calculations you can do in that one line, using an enum is a quick, yet clear way to implement a strategy pattern.
public enum Operation {
PLUS {
public double calc(double a, double b) {
return a + b;
}
},
TIMES {
public double calc(double a, double b) {
return a * b;
}
}
...
public abstract double calc(double a, double b);
}
Obviously, the strategy method declaration, as well as exactly one instance of each implementation are all defined in a single class/file.
You need to create an interface that provides the function(s) that you want to pass around. eg:
/**
* A simple interface to wrap up a function of one argument.
*
* #author rcreswick
*
*/
public interface Function1<S, T> {
/**
* Evaluates this function on it's arguments.
*
* #param a The first argument.
* #return The result.
*/
public S eval(T a);
}
Then, when you need to pass a function, you can implement that interface:
List<Integer> result = CollectionUtilities.map(list,
new Function1<Integer, Integer>() {
#Override
public Integer eval(Integer a) {
return a * a;
}
});
Finally, the map function uses the passed in Function1 as follows:
public static <K,R,S,T> Map<K, R> zipWith(Function2<R,S,T> fn,
Map<K, S> m1, Map<K, T> m2, Map<K, R> results){
Set<K> keySet = new HashSet<K>();
keySet.addAll(m1.keySet());
keySet.addAll(m2.keySet());
results.clear();
for (K key : keySet) {
results.put(key, fn.eval(m1.get(key), m2.get(key)));
}
return results;
}
You can often use Runnable instead of your own interface if you don't need to pass in parameters, or you can use various other techniques to make the param count less "fixed" but it's usually a trade-off with type safety. (Or you can override the constructor for your function object to pass in the params that way.. there are lots of approaches, and some work better in certain circumstances.)
Method references using the :: operator
You can use method references in method arguments where the method accepts a functional interface. A functional interface is any interface that contains only one abstract method. (A functional interface may contain one or more default methods or static methods.)
IntBinaryOperator is a functional interface. Its abstract method, applyAsInt, accepts two ints as its parameters and returns an int. Math.max also accepts two ints and returns an int. In this example, A.method(Math::max); makes parameter.applyAsInt send its two input values to Math.max and return the result of that Math.max.
import java.util.function.IntBinaryOperator;
class A {
static void method(IntBinaryOperator parameter) {
int i = parameter.applyAsInt(7315, 89163);
System.out.println(i);
}
}
import java.lang.Math;
class B {
public static void main(String[] args) {
A.method(Math::max);
}
}
In general, you can use:
method1(Class1::method2);
instead of:
method1((arg1, arg2) -> Class1.method2(arg1, arg2));
which is short for:
method1(new Interface1() {
int method1(int arg1, int arg2) {
return Class1.method2(arg1, agr2);
}
});
For more information, see :: (double colon) operator in Java 8 and Java Language Specification §15.13.
You can also do this (which in some RARE occasions makes sense). The issue (and it is a big issue) is that you lose all the typesafety of using a class/interface and you have to deal with the case where the method does not exist.
It does have the "benefit" that you can ignore access restrictions and call private methods (not shown in the example, but you can call methods that the compiler would normally not let you call).
Again, it is a rare case that this makes sense, but on those occasions it is a nice tool to have.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class Main
{
public static void main(final String[] argv)
throws NoSuchMethodException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
{
final String methodName;
final Method method;
final Main main;
main = new Main();
if(argv.length == 0)
{
methodName = "foo";
}
else
{
methodName = "bar";
}
method = Main.class.getDeclaredMethod(methodName, int.class);
main.car(method, 42);
}
private void foo(final int x)
{
System.out.println("foo: " + x);
}
private void bar(final int x)
{
System.out.println("bar: " + x);
}
private void car(final Method method,
final int val)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
{
method.invoke(this, val);
}
}
If you have just one line which is different you could add a parameter such as a flag and a if(flag) statement which calls one line or the other.
You may also be interested to hear about work going on for Java 7 involving closures:
What’s the current state of closures in Java?
http://gafter.blogspot.com/2006/08/closures-for-java.html
http://tech.puredanger.com/java7/#closures
New Java 8 Functional Interfaces and Method References using the :: operator.
Java 8 is able to maintain method references ( MyClass::new ) with "# Functional Interface" pointers. There are no need for same method name, only same method signature required.
Example:
#FunctionalInterface
interface CallbackHandler{
public void onClick();
}
public class MyClass{
public void doClick1(){System.out.println("doClick1");;}
public void doClick2(){System.out.println("doClick2");}
public CallbackHandler mClickListener = this::doClick;
public static void main(String[] args) {
MyClass myObjectInstance = new MyClass();
CallbackHandler pointer = myObjectInstance::doClick1;
Runnable pointer2 = myObjectInstance::doClick2;
pointer.onClick();
pointer2.run();
}
}
So, what we have here?
Functional Interface - this is interface, annotated or not with #FunctionalInterface, which contains only one method declaration.
Method References - this is just special syntax, looks like this, objectInstance::methodName, nothing more nothing less.
Usage example - just an assignment operator and then interface method call.
YOU SHOULD USE FUNCTIONAL INTERFACES FOR LISTENERS ONLY AND ONLY FOR THAT!
Because all other such function pointers are really bad for code readability and for ability to understand. However, direct method references sometimes come handy, with foreach for example.
There are several predefined Functional Interfaces:
Runnable -> void run( );
Supplier<T> -> T get( );
Consumer<T> -> void accept(T);
Predicate<T> -> boolean test(T);
UnaryOperator<T> -> T apply(T);
BinaryOperator<T,U,R> -> R apply(T, U);
Function<T,R> -> R apply(T);
BiFunction<T,U,R> -> R apply(T, U);
//... and some more of it ...
Callable<V> -> V call() throws Exception;
Readable -> int read(CharBuffer) throws IOException;
AutoCloseable -> void close() throws Exception;
Iterable<T> -> Iterator<T> iterator();
Comparable<T> -> int compareTo(T);
Comparator<T> -> int compare(T,T);
For earlier Java versions you should try Guava Libraries, which has similar functionality, and syntax, as Adrian Petrescu has mentioned above.
For additional research look at Java 8 Cheatsheet
and thanks to The Guy with The Hat for the Java Language Specification §15.13 link.
#sblundy's answer is great, but anonymous inner classes have two small flaws, the primary being that they tend not to be reusable and the secondary is a bulky syntax.
The nice thing is that his pattern expands into full classes without any change in the main class (the one performing the calculations).
When you instantiate a new class you can pass parameters into that class which can act as constants in your equation--so if one of your inner classes look like this:
f(x,y)=x*y
but sometimes you need one that is:
f(x,y)=x*y*2
and maybe a third that is:
f(x,y)=x*y/2
rather than making two anonymous inner classes or adding a "passthrough" parameter, you can make a single ACTUAL class that you instantiate as:
InnerFunc f=new InnerFunc(1.0);// for the first
calculateUsing(f);
f=new InnerFunc(2.0);// for the second
calculateUsing(f);
f=new InnerFunc(0.5);// for the third
calculateUsing(f);
It would simply store the constant in the class and use it in the method specified in the interface.
In fact, if KNOW that your function won't be stored/reused, you could do this:
InnerFunc f=new InnerFunc(1.0);// for the first
calculateUsing(f);
f.setConstant(2.0);
calculateUsing(f);
f.setConstant(0.5);
calculateUsing(f);
But immutable classes are safer--I can't come up with a justification to make a class like this mutable.
I really only post this because I cringe whenever I hear anonymous inner class--I've seen a lot of redundant code that was "Required" because the first thing the programmer did was go anonymous when he should have used an actual class and never rethought his decision.
The Google Guava libraries, which are becoming very popular, have a generic Function and Predicate object that they have worked into many parts of their API.
One of the things I really miss when programming in Java is function callbacks. One situation where the need for these kept presenting itself was in recursively processing hierarchies where you want to perform some specific action for each item. Like walking a directory tree, or processing a data structure. The minimalist inside me hates having to define an interface and then an implementation for each specific case.
One day I found myself wondering why not? We have method pointers - the Method object. With optimizing JIT compilers, reflective invocation really doesn't carry a huge performance penalty anymore. And besides next to, say, copying a file from one location to another, the cost of the reflected method invocation pales into insignificance.
As I thought more about it, I realized that a callback in the OOP paradigm requires binding an object and a method together - enter the Callback object.
Check out my reflection based solution for Callbacks in Java. Free for any use.
Sounds like a strategy pattern to me. Check out fluffycat.com Java patterns.
oK, this thread is already old enough, so very probably my answer is not helpful for the question. But since this thread helped me to find my solution, I'll put it out here anyway.
I needed to use a variable static method with known input and known output (both double). So then, knowing the method package and name, I could work as follows:
java.lang.reflect.Method Function = Class.forName(String classPath).getMethod(String method, Class[] params);
for a function that accepts one double as a parameter.
So, in my concrete situation I initialized it with
java.lang.reflect.Method Function = Class.forName("be.qan.NN.ActivationFunctions").getMethod("sigmoid", double.class);
and invoked it later in a more complex situation with
return (java.lang.Double)this.Function.invoke(null, args);
java.lang.Object[] args = new java.lang.Object[] {activity};
someOtherFunction() + 234 + (java.lang.Double)Function.invoke(null, args);
where activity is an arbitrary double value. I am thinking of maybe doing this a bit more abstract and generalizing it, as SoftwareMonkey has done, but currently I am happy enough with the way it is. Three lines of code, no classes and interfaces necessary, that's not too bad.
To do the same thing without interfaces for an array of functions:
class NameFuncPair
{
public String name; // name each func
void f(String x) {} // stub gets overridden
public NameFuncPair(String myName) { this.name = myName; }
}
public class ArrayOfFunctions
{
public static void main(String[] args)
{
final A a = new A();
final B b = new B();
NameFuncPair[] fArray = new NameFuncPair[]
{
new NameFuncPair("A") { #Override void f(String x) { a.g(x); } },
new NameFuncPair("B") { #Override void f(String x) { b.h(x); } },
};
// Go through the whole func list and run the func named "B"
for (NameFuncPair fInstance : fArray)
{
if (fInstance.name.equals("B"))
{
fInstance.f(fInstance.name + "(some args)");
}
}
}
}
class A { void g(String args) { System.out.println(args); } }
class B { void h(String args) { System.out.println(args); } }
Check out lambdaj
http://code.google.com/p/lambdaj/
and in particular its new closure feature
http://code.google.com/p/lambdaj/wiki/Closures
and you will find a very readable way to define closure or function pointer without creating meaningless interface or use ugly inner classes
Wow, why not just create a Delegate class which is not all that hard given that I already did for java and use it to pass in parameter where T is return type. I am sorry but as a C++/C# programmer in general just learning java, I need function pointers because they are very handy. If you are familiar with any class which deals with Method Information you can do it. In java libraries that would be java.lang.reflect.method.
If you always use an interface, you always have to implement it. In eventhandling there really isn't a better way around registering/unregistering from the list of handlers but for delegates where you need to pass in functions and not the value type, making a delegate class to handle it for outclasses an interface.
None of the Java 8 answers have given a full, cohesive example, so here it comes.
Declare the method that accepts the "function pointer" as follows:
void doCalculation(Function<Integer, String> calculation, int parameter) {
final String result = calculation.apply(parameter);
}
Call it by providing the function with a lambda expression:
doCalculation((i) -> i.toString(), 2);
If anyone is struggling to pass a function that takes one set of parameters to define its behavior but another set of parameters on which to execute, like Scheme's:
(define (function scalar1 scalar2)
(lambda (x) (* x scalar1 scalar2)))
see Pass Function with Parameter-Defined Behavior in Java
Since Java8, you can use lambdas, which also have libraries in the official SE 8 API.
Usage:
You need to use a interface with only one abstract method.
Make an instance of it (you may want to use the one java SE 8 already provided) like this:
Function<InputType, OutputType> functionname = (inputvariablename) {
...
return outputinstance;
}
For more information checkout the documentation: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
Prior to Java 8, nearest substitute for function-pointer-like functionality was an anonymous class. For example:
Collections.sort(list, new Comparator<CustomClass>(){
public int compare(CustomClass a, CustomClass b)
{
// Logic to compare objects of class CustomClass which returns int as per contract.
}
});
But now in Java 8 we have a very neat alternative known as lambda expression, which can be used as:
list.sort((a, b) -> { a.isBiggerThan(b) } );
where isBiggerThan is a method in CustomClass. We can also use method references here:
list.sort(MyClass::isBiggerThan);
The open source safety-mirror project generalizes some of the above mentioned solutions into a library that adds functions, delegates and events to Java.
See the README, or this stackoverflow answer, for a cheat sheet of features.
As for functions, the library introduces a Fun interface, and some sub-interfaces that (together with generics) make up a fluent API for using methods as types.
Fun.With0Params<String> myFunctionField = " hello world "::trim;`
Fun.With2Params<Boolean, Object, Object> equals = Objects::equals;`
public void foo(Fun.With1ParamAndVoid<String> printer) throws Exception {
printer.invoke("hello world);
}
public void test(){
foo(System.out::println);
}
Notice:
that you must choose the sub-interface that matches the number of parameters in the signature you are targeting. Fx, if it has one parameter, choose Fun.With1Param.
that Generics are used to define A) the return type and B) the parameters of the signature.
Also, notice that the signature of the Method Reference passed to the call to the foo() method must match the the Fun defined by method Foo. If it do not, the compiler will emit an error.

Categories

Resources