Are reverse method references possible in Java 8? - java

I know about lambda method references.
However, I am wondering whether the reverse might be possible, because I have a method that just proxies its arguments to a lambda:
Function<Arg, Result> lambda = (a) -> new Result(a);
public Result myMethod(Arg arg) {
return lambda.apply(a);
}
Haven't found anything on Google, so I guess it's not possible. Which makes sense, because after all, as I understand it, a lambda is just shorthand for a whole interface. A method and an interface are different. But you can make a lambda from a method, so maybe you can make a method from a lambda?

You can't make a method from a lambda because, as you say, a lambda is not a method and more importantly you cannot dynamically change a class by adding methods to it at runtime. That's a basic design invariant of Java classes. It is possible to dynamically respond to a predefined method of an interface with your own implementation, although it's fairly clunky. Take a look at http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html

The variable lambda has the type Function which doesn’t say anything about how the instance has been created. It might be a lambda expression, but it doesn’t have to. That said, if you want to delegate myMethod to a method declared in Function, there is no reason to automatically choose the abstract method of that interface, so, similar to method references, you would have to specify the target method like lambda::apply to make clear you want that method and not one of the other methods of the interface Function.
But unlike method references, which use a target type, you can’t derive a method declaration from the surrounding context, so you can’t spare the method declaration. So such a hypothetical feature would still require the method declaration, the reference to the lambda field and the target method name (apply), so there is not much left that you can save that would justify a new language feature.
And there is no need for such a functionality anyway. If you have code to be expressed as both, a function and a method, express it as method:
Instead of
Function<Arg, Result> lambda = (a) -> new Result(a);
public Result myMethod(Arg arg) {
return lambda.apply(a);
}
write
Function<Arg, Result> lambda = this::myMethod;
public Result myMethod(Arg arg) {
return new Result(arg);
}
But even a code replication might be acceptable, as in
Function<Arg, Result> lambda = (a) -> new Result(a);
public Result myMethod(Arg arg) {
return new Result(arg);
}
considering that lambda expressions should host rather small, often trivial, code only.

Related

Is an object created when you pass a method reference in a method

As far as I know, when you define a method in a function, an object is instantiated:
myList.stream().map(x->x.getName().replaceAll('a','b')).toList();
Or the equivalent
Function<MyObject,String> myFunc = x -> {return x.getName().replaceAll('a','b');}
myList.stream().map(myFunc).toList();
x->x.getName().replaceAll('a','b') is created as a functional interface object (and requires memory allocation, a new somewhere/somehow, right?).
However, if I pass an already existing method as a parameter, is anything created?
class A{
public list<String> transform(List<String> input){
return input.stream().filter(this::myFilter).filter(A::staticFilter).toList();
}
public boolean myFilter(String s){ // Whatever }
public static boolean staticFilter(String s) { // whatever }
}
What happens here:
Is myFilter "wrapped" in a functional interface? (is it the same for a static method reference?)
Is there something specific that happens at bytecode level which is not "clear" on language level (like method pointer or something?).
From JavaDoc Api
Note that instances of functional interfaces can be created with
lambda expressions, method references, or constructor references.
As to if the lambda expression will create an instance in heap or not, you can follow this thread where the top comment from #Brian Goetz might be helpful.
About lambda expressions:
Also as indicated here in Java Specifications for Run-Time Evaluation of Lambda Expressions
These rules are meant to offer flexibility to implementations of the
Java programming language, in that:
A new object need not be allocated on every evaluation.
Objects produced by different lambda expressions need not belong to
different classes (if the bodies are identical, for example).
Every object produced by evaluation need not belong to the same class
(captured local variables might be inlined, for example).
If an "existing instance" is available, it need not have been created
at a previous lambda evaluation (it might have been allocated during
the enclosing class's initialization, for example).
So to your question:
x->x.getName().replaceAll('a','b') is created as a functional
interface object (and requires memory allocation, a new
somewhere/somehow, right?).
The answer is some times yes, some times no. Not always the same case.
About method reference expressions:
Evaluation of a method reference expression produces an instance of a
functional interface type (§9.8). Method reference evaluation does not
cause the execution of the corresponding method; instead, this may
occur at a later time when an appropriate method of the functional
interface is invoked.
Based on what is written here for Run-Time Evaluation of Method References
The timing of method reference expression evaluation is more complex
than that of lambda expressions (§15.27.4). When a method reference
expression has an expression (rather than a type) preceding the ::
separator, that subexpression is evaluated immediately. The result of
evaluation is stored until the method of the corresponding functional
interface type is invoked; at that point, the result is used as the
target reference for the invocation. This means the expression
preceding the :: separator is evaluated only when the program
encounters the method reference expression, and is not re-evaluated on
subsequent invocations on the functional interface type.
I would assume that a functional interface type is created but not each time with each invocation. It should as well be cached and optimized for the less amount of evaluations.
Well, the compiler has a lot of leeway in how it actually implements the code you write, but generally .map() takes a Function Object so whatever expression you put in the parentheses will produce an object.
That does not mean, however, that a new Object is created every time. In your lambda example, the lambda function doesn't reference anything defined in an enclosing method scope, so a single Function object can be created and reused for all calls.
Similarly, the A::staticFilter reference only needs to produce one Function.
The object created by this::myFilter, however, needs to have a reference to this (unless the compiler can determine that it doesn't!), and so you will certainly get a new Function created inside each call to transform.

Lambda Expressions and Non-Class Java Methods [duplicate]

This question already has answers here:
Non-class functions in Java
(4 answers)
Closed 2 years ago.
When declaring methods in Java, do they need to be a part of a class? I am familiar with the idea of a Utility Class:
"Utility Class, also known as Helper class, is a class, which contains just static methods, it is stateless and cannot be instantiated. It contains a bunch of related methods, so they can be reused across the application."
However, can one just create a method separate from any class altogether? (I'd assume scope becomes public by default and declaring anything else for scope might result in an error).
If this is not possible, perhaps that would explain the need for Utility Classes, but I wasn't sure as I hadn't thought about this before - I assumed naturally you could make functions separate from any specific class, but I had been looking through various code samples and couldn't find a specific example where this was occurring.
Part of the reason I am asking this is I was reviewing this article (and mentioned in point 2):
https://www.geeksforgeeks.org/lambda-expressions-java-8/
In it, it states: Lambda expressions are added in Java 8 and provide below functionalities.
1) Enable to treat functionality as a method argument, or code as data.
2) A function that can be created without belonging to any class.
3) A lambda expression can be passed around as if it was an object and executed on demand.
Java is a sort of purely class-based programming language. So, Yes, it and everything needs to be a part of a class.
You are right, you can make a Utility class making methods public static in this way methods can be called without instantiating the class.
Answer to question in the comment:
Why would someone write Object.method() instead of just method()?
Object class is a standard class in java.lang package. You should not create your class named Object otherwise you will need to specify java.lang.Object everywhere you use java.lang.Object.
Now you probably meant
Why would someone write MyUtilClass.method() instead of just method()?
Suppose you have a class MyUtilClass as follows
public class MyUtilClass {
public static int utilMethodA() {
return 1;
}
public static boolean utilMethodB() {
int value = utilMethodA();
if(value == 1)
return true;
else
return false;
}
}
And suppose you have another class MyClass as
public class MyClass {
public void classMethod() {
int value = MyUtilClass.utilMethodA();
}
}
Here if you see in MyUtilClass, utilMethodB() uses utilMethodA() without writing MyUtilClass.utilMethodA() (however, we could write it that way also). Here we did not need to write it as MyUtilClass.utilMethodA() because compiler can find the utilMethodA() without fully specifying it's class because it is present inside it's own class.
Now, In Myclass's myMethod(), we must specify MyUtilClass.utilMethodA() (without it, it won't work), because the compiler has no way of figuring out that you meant to call utilMethodA() of MyUtilClass. There could be hundreds of classes with a method named utilMethodA(), the compiler has no way of finding out which one of the hundred methods you want to call.
Note:-
Also, you can do static import of MyUtilClass.myMethod() like
import static my.package.name.MyUtilClass.myMethodA()
and then use utilMethodA() inside MyClass without prefixing MyUtilClass (but you already informed compile by static import that you will be using utilMethodA() of MyUtilClass right?)
Looks cool to you? No!
This is rather a bad way because
It makes code looks unobvious. In a large class, it may seem that
method utilMethodA() is a local method defined somewhere in
MyClass.
Also, it can generate ambiguity to the compiler if more than one static import of utilMethodA() is done. As compiler has no way of figuring out which of the two you intend to use.
(Edit) Regarding Lambda Expression
Lambda expression is pretty cool stuff added in Java 8. They are basically a kind of function. They provide you the power to define a function right where they need to be used. For example in this link that you provided, see the example shown below syntax of lambda, there the statement
ArrayList<Integer> arrL = new ArrayList<Integer>();
arrL.add(1);
arrL.add(2);
arrL.add(3);
arrL.add(4);
arrL.forEach(n -> { if (n%2 == 0) System.out.println(n); });
Basically, what we are doing here is, we are defining a function, if n is multiple of 2, we print n. We are doing it forEach element of arrL. Did you see, we defined the function to be executed on each element right inside a function call forEach(). That's the beauty of lambda expression.
Now, coming to your question,
So the primary benefit of lambda (besides syntax) is to make it easier to implement functional interfaces (compared to what alternative)?
Yes, sort of. Easy in terms of not creating a separate class implementing the interface and then implementing the abstract method and then calling that implemented method.
This becomes lots of work, especially if you need to call that method only once for example,
Consider the Functional Interface FuncInterface defined as in the link in your question:
interface FuncInterface {
// An abstract function
void abstractFun(int x);
// A non-abstract (or default) function
default void normalFun() {
System.out.println("Hello");
}
}
Now, you want two kind of implementation to your functional interface:
One that provides twice of the passed int x.
Another one that provides square of passed int x.
So, you make two implementations of it:
First FuncInterfaceTwiceImpl
public class FuncInferFaceTwiceImpl implements FuncInterface {
#Override
public void abstractFun(int x) {
System.out.println(2 * x);
}
}
Second, FuncInterfaceSquareImpl as
public class FuncInterfaceSquareImpl implements FuncInterface {
#Override
public void abstractFun(int x) {
System.out.println(x * x);
}
}
Now, you call them as
public class MyClass {
public static void main(String[] args) {
FuncInterface interfaceTwiceObject = new FuncInferFaceTwiceImpl();
interfaceTwiceObject.abstractFun(5);
FuncInterface interfaceSquareObject = new FuncInterfaceSquareImpl();
interfaceSquareObject.abstractFun(5);
}
}
It prints
10
25
Now, what you had to do?
You had to create two separate Classes (in separate new files or
could have made private classes in the same file that of MyClass),
each implementing the abstract method.
Then you instantiated objects of each class and called them
respectively in the main function.
What if this is the only place where you had to call this twice and square thing? You had to make two classes just to use them only once. This effort is too much!!
What if you want to call it without creating new classes and implementing methods in a class?
What if I tell you only provide me the method body, I will do the work for you without you to bother about implementing interface and overriding methods?
Here comes the Lambda magic. Instead of making any impl classes just
head straight towards the main method
Instantiate two objects of FuncInterface providing only method body in Lambda expression.
Call abstract method from objects just like below
public class MyClass {
public static void main(String[] args) {
FuncInterface interfaceTwiceObject = (n) -> System.out.println(2*n);
interfaceTwiceObject.abstractFun(5);
FuncInterface interfaceSquareObject = (n) -> System.out.println(n*n);
interfaceSquareObject.abstractFun(5);
}
}
And boom, the output is
10
25
Just one more time where Lambda saved your day!!
Yes all methods in Java have to be part of a class. You cannot create a method (static or otherwise) which is not associated with a class.
EDIT
Before I answer your question, I will point out that lambda expressions were introduced in Java 8 through the concept of SAM types. In addition, a bit of syntactic sugar was also introduced to facilitate the creation of these types.
When you hear the term "Lambda expression" in Java, you should always remember that they are expressions. Your confusion stems from thinking that lambda expressions evaluate to a pure function not associated with a class or object; well this is simply not the case in Java and I will show you why.
Lambda expressions are not functions
I can now see where your confusion comes from because that article you are reading made a false claim when they say that lambda expression is:
A function that can be created without belonging to any class.
This is simply not true. A lambda expression in Java is not a function. Take the example they give for instance.
interface FuncInterface
{
// An abstract function
void abstractFun(int x);
// A non-abstract (or default) function
default void normalFun()
{
System.out.println("Hello");
}
}
class Test
{
public static void main(String args[])
{
// lambda expression to implement above
// functional interface. This interface
// by default implements abstractFun()
FuncInterface fobj = (int x)->System.out.println(2*x);
// This calls above lambda expression and prints 10.
fobj.abstractFun(5);
}
}
Proof
Now take the comment they have in the main method:
lambda expression to implement above functional interface
From the start they admit that the next line of code implements a functional interface. However functions in Java do not implement interfaces, only classes or other interfaces can do that!
Now, they even go ahead and "call" this function:
This calls above lambda expression and prints 10.
except instead of directly invoking the function (as anyone would if this was really a function), they use the property accessor notation (.) to access the actual method they wanted to call, which means what we have here is not a function, but actually an instance of an anonymous class.
Furthermore, since this object actually contains another method (normalFun), one might ask the question, which one do I use when I want to pass this "function" to another method? This is not a question that is commonly (if ever) asked in the context of lambda functions because there is only one thing to do with a lambda function and that is to call it.
In closing
Java has lambda expressions, not lambda functions.
What makes it a lambda expression is simply the syntactic sugar introduced in Java 8 that uses the () -> { } notation. Unfortunately, many fans of functional programming began associating the term "Lambda function" with objects created using this syntax, and this has led to the confusion you have expressed in your question.
To rehash what I answered previously, all functions in Java are part of a class, and you cannot have a function which is not associated with an object, nor can you create a function outside a class.
HTH

converting a java method to kotlin. Return a lambda expression

kotlin 1.3.31
I have the following code snippet in Java that I am trying to convert to Kotlin
private ArgumentMatcher<List<Person> customArgumentMatcher(final int size) {
return argument -> argument.size() == size;
}
My understanding of the above is a method declaration that has a ArgumentMatcher as the return type and the method of the interface is executed in the lambda expression and the resulting boolean is returned. Correct me if I am wrong with my explanation.
However, when I try and convert this to Kotlin
private fun customArgumentMatcher(size: Int): ArgumentMatcher<List<Person>> {
return { argument -> argument.size == size }
}
I get the following error:
Required ArgumentMatcher<List<Person>>
found: (???) -> Boolean
Many thanks for any suggestions,
Since ArgumentMatcher is a Java functional interface you need to use:
fun customArgumentMatcher(size: Int): ArgumentMatcher<List<Person>> {
return ArgumentMatcher { argument -> argument.size == size }
}
See the SAM Conversions section of the Kotlin reference.
You could also use:
fun customArgumentMatcher(size: Int) = ArgumentMatcher<List<Person>> { it.size == size }
See gidds' answer for some background on why the above syntax is necessary.
To add some background to the other answer:
This is one of the slightly awkward areas in Kotlin, as far as Java interoperability goes.  But it's an unfortunate consequence of Kotlin being a better language in itself!  Let me try to explain…
When Java added lambdas, they did it in a way (as with generics before that) to make the bare minimum of changes to the way the language worked.  So they didn't make functions first-class types.  Instead, they enshrined the existing practice of using interfaces.  For example, if you wanted something to be informed of ActionEvents, you'd implement the ActionListener interface.  This has a single method called actionPerformed() taking an ActionEvent parameter.
They didn't want to change how any of that worked, so in Java 8+, a lambda is simply a more concise way of implementing some interface.  The context (i.e. the method you're calling, or the type of variable you're assigning it to) tells the compiler what type of interface you want — it must be a ‘functional interface’ with a Single Abstract Method (SAM) — and then the compiler generates an implementation.  There are a few optimisations, but it's basically what you used to do in Java 7-.  It doesn't work too badly, but there are a lot of awkward corner cases, because functions aren't full first-class objects.
Kotlin, on the other, does have proper function types.  This is much more powerful and flexible, but doesn't match Java's way of doing things.
The Kotlin compiler has some special cases allowing a lambda to be automatically converted into an implementation of a Java SAM interface.  (This doesn't apply when implement Kotlin interfaces, though, which causes some confusion.)
In cases where you're passing a SAM-implementing lambda directly to a method, the compiler can infer its type.  (As in #Slaw's second example.)
But in other cases, you need to specify the interface name before the opening brace.  (As in #Slaw's first example.)

New Feature Lambda Overloading in Java [duplicate]

This question already has answers here:
Java 8 Lambda expression - Method overloading doubts
(6 answers)
Closed 4 years ago.
I'm a little bit confused about why there is no such thing like lambda overloading.
I know lambda expression work with #FunctionalInterface If you have two or more abstract method in interface then compiler can't decide what function to call when you are using a lambda expression, so it is necessary to have only one abstract method in the interface if you want to use a lambda expression. But what if you have two or more function with different arguments or a different type of arguments or return type than the compiler can easily decide what function to call.
For example:
interface Foo{
void show(String message);
void count(int number);
}
// Calling with lambda (Syntax is not correct)
x -> "Example Message"; // It should need to call void show();
x -> 7; // It should need to call void count();
Why this kind of thing is not available in java. isn't it a good thing.
You've considered one side of the problem - which method the lambda expression should correspond to. What you haven't considered is what happens to all other methods in the interface.
The language could be specified so that the lambda expression corresponds to one method, and all the others throw a RuntimeException - but that would rarely be useful. Consider how the Foo would be used. You'd end up with an object that you could only call some methods on, and you wouldn't even know which methods you could call safely.
If you know you're only going to call one method (e.g. count in your example), then that's one standalone piece of functionality, and can be encapsulated in an interface on its own - at which point existing lambda expression functionality is fine. If you don't know that you only want to use a single method, then your proposal won't help anyway.

Replacing chained method call using method reference

"Java 8 Lambdas: Pragmatic Functional Programming" has an example for using peek method in Stream API. This piece of code prints artist nationalities whose name starts with "The":
Set<Nationality> nationalities = album.getMusician()
.filter(artist -> artist.getName().startsWith("The"))
.map(artist -> artist.getNationality())
.peek(nation -> System.out.println(nation))
.collect(Collectors.toList());
I want to rewrite this code with method references:
Set<Nationality> nationalities = album.getMusician()
.filter(artist -> artist.getName().startsWith("The"))
.map(Artist::getNationality)
.peek(System.out::println)
.collect(Collectors.toList());
Is there any solution to rewrite filter(artist -> artist.getName().startsWith("The"))?
You need to create a separate method that takes an Artist and returns a boolean:
private boolean nameStartsWithThe(Artist a) {
return a.getName().startsWith("The");
}
Set<Nationality> nationalities = album.getMusician()
.filter(this::nameStartsWithThe)
or with a static method:
private static boolean nameStartsWithThe(Artist a) {
return a.getName().startsWith("The");
}
Set<Nationality> nationalities = album.getMusician()
.filter(MyClass::nameStartsWithThe)
You'd need something that composes the two methods. There are some methods for composing methods (IntUnaryOperator has compose and andThen methods that can compose two IntUnaryOperators into a new IntUnaryOperator). But the ones I've found all seem specialized for certain types of functional interfaces; defining compose methods for every possible pair of functional interface types would be too unwieldy.
I did get something to work that would compose a Function and a Predicate to get a new Predicate:
static <T,U> Predicate<T> functionPredicate(Function<T,U> func, Predicate<U> pred) {
return obj -> pred.test(func.apply(obj));
}
That is, it can compose a predicate that operates on T from a function that takes a T and returns U, and a predicate that operates on U. This would almost work on your example, except that startsWith needs another parameter. But this does work:
static boolean startsWithThe(String s) {
return s.startsWith("The");
}
Predicate<Artist> pred = functionPredicate(Artist::getName, ThisClass::startsWithThe);
where ThisClass is whatever class contains startsWithThe. This works. If you want to avoid writing a new method (like startsWithThe), you could probably write a "parameterized predicate" generic method so that you write something like
Predicate<Artist> pred = functionPredicate(Artist::getName, parameterizedPredicate(String::startsWith, "The"));
but I haven't tried it.
So it seems it's possible to come up with something that will let you use method references instead of lambdas. I question whether it's worthwhile. To me, a method reference is just a shorthand for certain kinds of lambdas; and unless you can do what you want with a simple method reference, I'd think using a lambda is concise and clear enough, and you don't need to add all the extra rigmarole like my functionPredicate method. I've seen several questions that ask something like "How can I use a method reference for this instead of a lambda?", and I honestly don't understand why.
There is no way to replace that line with a method reference.
Method reference works by using the fact that there is only one object being used in entire lambda expression and the compiler can infer it (reference does not matter and type can be inferred) using target typing.
So,
artist -> artist.getNationality()
is replaced with
Artist::getNationality
Here Artist::getNationality method matches with the target type without requiring any further information.
In case of artist -> artist.getName().startsWith("The"), there are two method calls in the lambda expression. The order, parameters are important, and have to be specified.
It looks as if the artist reference should be inferred, but the compiler won't know what object should the startsWith("The") method be called on.
Hope this helps.

Categories