Can a lambda access members of its target functional interface? - java

I have created a simple interface using java8. In that it contains one method and one default method.
interface Lambda{
default void dummy(){
System.out.println("Call this..");
}
void yummy();
}
I'm trying to us these two methods using the historical way like
public class DefaultCheck {
public static void main(String[] args) {
DefaultCheck check = new DefaultCheck();
check.activate(new Lambda() {
#Override
public void yummy() {
dummy();
}
});
}
void activate(Lambda lambda){
lambda.yummy();
}
}
Now i'm trying to implement the same thing using lambda expression, getting error like `dummy is undefined`
check.activate(() -> {
dummy();
});
Can any one please suggest, how to implement this scenario using Lambda expression ??

It can't be done.
JLS 15.27.2 addresses this:
Unlike code appearing in anonymous class declarations, the meaning of
names and the this and super keywords appearing in a lambda body,
along with the accessibility of referenced declarations, are the same
as in the surrounding context (except that lambda parameters introduce
new names).
The transparency of this (both explicit and implicit) in the body of a
lambda expression - that is, treating it the same as in the
surrounding context - allows more flexibility for implementations, and
prevents the meaning of unqualified names in the body from being
dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to
talk about itself (either to call itself recursively or to invoke its
other methods), while it is more common to want to use names to refer
to things in the enclosing class that would otherwise be shadowed
(this, toString()). If it is necessary for a lambda expression to
refer to itself (as if via this), a method reference or an anonymous
inner class should be used instead.

The inner class implementation works since the code is called as if you coded:
check.activate(new Lambda() {
#Override
public void yummy() {
this.dummy();
}
});
Our problem now is that lambdas do not introduce a new scope. So, if you want your lambda to be able to reference itself, you may refine your #FunctionalInterface so that its functional method accepts itself and its required parameters:
check.activate(this_ -> this_.dummy());
where Lambda is defined as:
#FunctionalInterface
public interface Lambda {
void yummy(Lambda this_);
default void yummy() {
yummy(this);
}
default void dummy(){
System.out.println("Call this..");
}
}

If I understand it correctly. You are trying to call a default method in an interface through lambda implementation. I think it can be done.
#FunctionalInterface
interface Value
{
String init(Value a);
default String add(String b)
{
return "added content "+b;
}
default String getResult()
{
String c = init(this);
return c;
}
}
public class Main
{
public static void main(String[] args)
{
Value v = a -> a.add("inpout"); // here I am calling add method in Value interface.
String c = v.getResult();
System.out.println(c);
}
}

Related

How do I stop a functional interface from being a target for lambda expressions?

I have an API with an interface with two (overloaded) methods of the same name that take different argument types. These different types are both technically functional interfaces, but the user should not be allowed to create instances of one of them. Here is a simplified example:
public class Example
{
#FunctionalInterface
public interface Computation
{
int compute();
}
public interface WrappedComputation
{
Computation unwrap();
}
public static class Solver
{
public static int solve(Computation a)
{
return a.compute();
}
public static int solve(WrappedComputation b)
{
return solve(b.unwrap());
}
}
public static void main(String... args)
{
// 'Computation' interface should be a lambda target
// so coder can make their own 'A' computation
Solver.solve( () -> { return 5 + 5; } );
// 'WrappedComputation' interface SHOULD NOT be a lambda target
// or else coder can cause runtime exceptions etc., like passing a null 'Computation' reference that will be computed
Solver.solve( () -> { Computation a = null; return a; } );
}
}
The only idea I have so far is to add a dummy/unused method to the interface that I don't want to be a lambda target, and implement it in all of the implementing classes. That seems a little sloppy/unneeded though... any other suggestions?
There is no way to prevent the usage of lambda expressions by API clients when your interface satisfies the criteria for it.
Your supposition that API clients can only cause trouble via lambdas is incorrect -- any bad thing you can do with a lambda, you can also do with an anonymous inner class or a named class. Consider:
Solver.solve( new WrappedComputation(){
public Computation unwrap(){
Computation a = null; return a;
}
});
This has exactly the same semantics and end result (a runtime exception) as your lambda.
Perhaps what you want instead is to prevent any uncontrolled creation of WrappedComputation? In that case, consider making it a final class whose constructor checks for error cases:
public final class WrappedComputation{
private final Computation _wrapped;
public WrappedComputation(#NonNull wrapped){
_wrapped = Objects.requireNonNull(wrapped);
}
}
Coder can always cause runtime exception, so that's a bad excuse.
If you don't want ambiguity, don't overload the method.
Name it something else, e.g. solveWrapped.

Value of "this" in an anonymous class vs a lambda expression

I am little bit confused with the different behavior of an anonymous class and a lambda expression.
When I'm using a lambda expression:
//Test.java
Runnable r1 = () -> System.out.println(this);
Runnable r2 = () -> System.out.println(toString());
#Override
public String toString() {
return "Hello World!";
}
// in main method
new Test().r1.run();
new Test().r2.run();
Output : Hello World!
Hello World!
When using an anonymous class:
Runnable r1 = new Runnable() {
#Override
public void run() {
System.out.println(this);
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
System.out.println(toString());
}
};
#Override
public String toString() {
return "Hello World!";
}
// in main method
new Test().r1.run();
new Test().r2.run();
Output : Package_Name.Test$1#1db9742
Package_Name.Test$2#106d69c
Can someone please explain the different behavior?
In a lambda expression, this is lexically bound to the surrounding class, while in the anonymous class this is lexically bound to the anonymous class.
The Java Language Specification describes this behavior at 15.27.2:
Unlike code appearing in anonymous class declarations, the meaning of names and the this and super keywords appearing in a lambda body, along with the accessibility of referenced declarations, are the same as in the surrounding context (except that lambda parameters introduce new names).
The transparency of this (both explicit and implicit) in the body of a lambda expression - that is, treating it the same as in the surrounding context - allows more flexibility for implementations, and prevents the meaning of unqualified names in the body from being dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to talk about itself (either to call itself recursively or to invoke its other methods), while it is more common to want to use names to refer to things in the enclosing class that would otherwise be shadowed (this, toString()). If it is necessary for a lambda expression to refer to itself (as if via this), a method reference or an anonymous inner class should be used instead.
In order to reference this of the surrounding class from inside an anonymous class, you will have to use a qualified this.
Runnable r1 = new Runnable() {
#Override
public void run() {
System.out.println(Test.this); // or Test.this.toString()
}
};

Java 8 Lambda Can't Call Default Interface Methods [duplicate]

I have created a simple interface using java8. In that it contains one method and one default method.
interface Lambda{
default void dummy(){
System.out.println("Call this..");
}
void yummy();
}
I'm trying to us these two methods using the historical way like
public class DefaultCheck {
public static void main(String[] args) {
DefaultCheck check = new DefaultCheck();
check.activate(new Lambda() {
#Override
public void yummy() {
dummy();
}
});
}
void activate(Lambda lambda){
lambda.yummy();
}
}
Now i'm trying to implement the same thing using lambda expression, getting error like `dummy is undefined`
check.activate(() -> {
dummy();
});
Can any one please suggest, how to implement this scenario using Lambda expression ??
It can't be done.
JLS 15.27.2 addresses this:
Unlike code appearing in anonymous class declarations, the meaning of
names and the this and super keywords appearing in a lambda body,
along with the accessibility of referenced declarations, are the same
as in the surrounding context (except that lambda parameters introduce
new names).
The transparency of this (both explicit and implicit) in the body of a
lambda expression - that is, treating it the same as in the
surrounding context - allows more flexibility for implementations, and
prevents the meaning of unqualified names in the body from being
dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to
talk about itself (either to call itself recursively or to invoke its
other methods), while it is more common to want to use names to refer
to things in the enclosing class that would otherwise be shadowed
(this, toString()). If it is necessary for a lambda expression to
refer to itself (as if via this), a method reference or an anonymous
inner class should be used instead.
The inner class implementation works since the code is called as if you coded:
check.activate(new Lambda() {
#Override
public void yummy() {
this.dummy();
}
});
Our problem now is that lambdas do not introduce a new scope. So, if you want your lambda to be able to reference itself, you may refine your #FunctionalInterface so that its functional method accepts itself and its required parameters:
check.activate(this_ -> this_.dummy());
where Lambda is defined as:
#FunctionalInterface
public interface Lambda {
void yummy(Lambda this_);
default void yummy() {
yummy(this);
}
default void dummy(){
System.out.println("Call this..");
}
}
If I understand it correctly. You are trying to call a default method in an interface through lambda implementation. I think it can be done.
#FunctionalInterface
interface Value
{
String init(Value a);
default String add(String b)
{
return "added content "+b;
}
default String getResult()
{
String c = init(this);
return c;
}
}
public class Main
{
public static void main(String[] args)
{
Value v = a -> a.add("inpout"); // here I am calling add method in Value interface.
String c = v.getResult();
System.out.println(c);
}
}

How to pass a concrete method as parameter to another concrete method

I am newbie to java, and developing a real life project. I have many methods and about 2500 lines of code thus far. Many of the methods are slightly different(usually a difference of mere a single identifier) due to which i have to copy the code again and again with slight changes.
What i want is to pass a method as parameter to another method, I've gone through lambda expressions
but i could not find it enough appealing, off-course due to my own conceptual shortcomings. because it tells to define functional interface of each method to be passed. but as per my thoughts it would not give me a generic code so that i would be able to simply add some other Tables in future.
i am putting a piece of code to demonstrate and better explain my problem.
if(houseTabPanel.getComponentCount()==0){
houseTableDb();
}
if(isSelected){
selection(houseTable);
}
else {
houseTable.setColumnSelectionAllowed(false);
houseTable.setRowSelectionAllowed(false);
houseTable.setCellSelectionEnabled(false);
Rselection(houseTable);
}
now i have different methods named houseTableDb() , plotTableDb() , adminTableDb() etc.
i want to make a method of this piece of code and pass plotTableDb() etc as parameter..
something like...
public void genericMethod(JPanel p, JTable t, some method reference to use instead of houseTableDb){}
pardon me if am not descriptive enough.. any response would be truly appreciated by core of the heart.
Provided that all of these methods have the same signature you can define an interface with a single method with that signature (return value, parameter list). Then you write classes implementing the method, one for each method's implementation. For passing the method, you create an object of that class and pass the object. The call to the actual method is replaced by the call to the method defined in the interface.
interface Callee {
void meth();
}
class MethOne implements Callee {
public void meth(){...}
}
void caller( Callee callee ){
callee.meth();
}
Callee ofOne = new MethOne();
caller( ofOne );
But to avoid all this hazzle: that's why lambdas have been added...
You can do like this :
public void genericMethod(JPanel p, JTable t, TableDbCallBack tableDb)
{
if(p.getComponentCount()==0)
{
tableDb.run();
}
if(isSelected)
{
selection(t);
}
else
{
t.setColumnSelectionAllowed(false);
t.setRowSelectionAllowed(false);
t.setCellSelectionEnabled(false);
Rselection(t);
}
}
usage :
genericMethod(p, t, new HouseTableDb());
genericMethod(p, t, new AdminTableDb());
Implementation :
public interface TableDbCallBack extends Runnable {}
public class HouseTableDb implements TableDbCallBack
{
#Override
public void run()
{
// Whatever it should do
}
}
public class AdminTableDb implements TableDbCallBack
{
#Override
public void run()
{
// Whatever it should do
}
}

What is the breakdown for Java's lambda syntax?

Please explain the syntax for Java 8's lambda methods.
There are a lot of explanations out there for what lambda functions are, but I can't find a thorough explanation of the syntax, and I am finding it very difficult to learn to replicate the syntax correctly because I don't understand why they're written as they are.
Here's a common case that I run into, courtesy NetBeans:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new MainAppJFrame();
});
}
So somehow, the following lambda expression is resolving into an anonymous Runnable object's run() method:
() -> {
// do stuff
}
The -> is the lambda syntax proper, right? And the curly braces are simply containing the anonymous method code. Are the parentheses an empty argument, because in this case we're creating a Runnable.run() method?
This is all rather unclear to me. I assume the compiler knows to instantiate an anonymous Runnable based on the type expected by the SwingUtilities.invokeLater(Runnable) method? What would happen if there were two SwingUtilities.invokeLater methods which differ only in parameter list? Obviously there aren't in this specific case, but it's possible elsewhere:
interface ExampleLambdaConsumer {
public void doSomething(Runnable r);
public void doSomething(java.lang.reflect.Method m);
}
class C implements ExampleLambdaConsumer {
// implementations for doSomething methods here
public static void main(String[] args) {
doSomething(() -> {
// lambda method body here
}
}
}
Syntax is:
arguments -> body
where arguments can be either
()
a single variable if the type of that variable can be inferred from the context
a sequence of variables, with or without types (or since Java 11, with var), in parentheses.
Examples: (x), (x, y), (int x, int y), (var x, var y) (Java 11+).
The following are invalid: (int x, y), (x, var y), (var x, int y)
and body can be either an expression or a {...} block with statements. The expression (other than a method or constructor call) is simply returned, i.e. () -> 2 is equivalent to () -> {return 2;}
In case of lambda expressions like () -> f() (the body is a method or constructor call expression):
if f() returns void, they are equivalent to () -> { f(); }
otherwise, they are equivalent to either () -> { f(); } or () -> { return f(); }). The compiler infers it from the calling context, but usually it will prefer the latter.
Therefore, if you have two methods: void handle(Supplier<T>) and void handle(Runnable), then:
handle(() -> { return f(); }) and handle(() -> x) will call the first one,
handle(() -> { f(); } will call the second one, and
handle(() -> f()):
if f() returns void or a type that is not convertible to T, then it will call the second one
if f() returns a type that is convertible to T, then it will call the first one
The compiler tries to match the type of the lambda to the context. I don't know the exact rules, but the answer to:
What would happen if there were two SwingUtilities.invokeLater methods which differ only in parameter list?
is: it depends on what would be those parameter lists. If the other invokeLater had also exactly one parameter and that parameter would be of type that is also an interface with one method of type void*(), well, then it would complain that it cannot figure out which method you mean.
Why are they written as they are? Well, I think it's because syntax in C# and Scala is almost the same (they use => rather than ->).
The syntax is
(parameter_list_here) -> { stuff_to_do; }
The curly braces can be omitted if it's a single expression. The regular parentheses around the parameter list can be omitted if it's a single parameter.
The syntax only works for all functional interfaces. The #FunctionalInterface annotation tells the compiler that you intend to write such an interface and gives a compile error if you do not meet the requirement(s) - for example it must only have 1 overrideable method.
#FunctionalInterface
interface TestInterface {
void dostuff();
}
Runnable is also declared like that. Other interfaces are not, and they cannot be used with lambda functions.
Now that we've made a new functional interface with a method that takes no parameters, how about we test the question you had about "collision" in the signatures?
public class Main {
private void test(Runnable r) {
}
private void test(TestInterface ti) {
}
public static void main(String[] args) {
test(() -> { System.out.println("test");})
}
#FunctionalInterface
interface TestInterface {
void dostuff();
}
}
Result: compile error: ambigouous call to method test.
You see, the compiler/VM(if done runtime) finds the appropriate methods and their parameter list and sees if the parameter is a functional interface and if it is it creates an anonymous implementation of that interface. Technically (in byte code) it's different from an anonymous class, but otherwise identical (you won't see Main$1.class files).
Your example code (courtesy of Netbeans) can also be replaced with
SwingUtilities.invokeLater(MainAppJFrame::new);
Btw. :)
Lambda Expressions are basically adopted in Java 8 to simplify overriding process function as anonymous functions.
They are mere shortcut to Override old java anonymous functions.
Refer following example:
Suppose you have interface A which has only one method declared like below:
interface A{
void print();
}
now with old java style we'll override this in anonymous way like below:
new A() {
#Override
public void print() {
System.out.println("in a print method");
}
};
additionally now with java 8 lambda expression we'll use it like below:
() -> System.out.println("in a print method");
Here we can pass parameters required to method before -> operator
and then overridden body after -> operator.
the only more settings that we need to achieve this is that we need to declare interface with #FunctionalInterface as below:
#FunctionalInterface
interface A{
void print();
}
Note: - A lambda expression can only be used for a "functional" interface that has only one non-default method.
The syntax is confusing.
It drives me around the twist.
If it was not for Intellij, correcting me I would get it wrong.
Compiles OK.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> {return (integer%2 == 0);};
}
}
Compiles OK.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> {return integer%2 == 0;};
}
}
Does NOT Compile, since it is not a statement anymore.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> {return integer%2 == 0};
}
}
Does NOT Compile, since it is not a statement anymore and the return statement has been removed.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> {integer%2 == 0};
}
}
Compiles OK.
class Scratch {
public static void main(String[] args) {
Predicate<Integer> even = integer -> integer%2 == 0;
}
}
So moral of the story is, if you use the brackets what is inside must
be a statement, and it must return the type expected by the Functional interface single abstract method (i.e. the only one that is not a default).
I actually wrote it more for myself than anything else, cause it was bugging me.

Categories