"AssignmentOperator Expression" error on simple lambda expression code - java

I'm learning how to use lambda expressions now, and I've seen some tutorials with a simple example:
(int x) -> x + 5;
But my compiler is showing this error:
Syntax error, insert "AssignmentOperator Expression" to complete Expression
Am I forgetting something?

Lambda expressions always have to be assigned to a reference type of Functional Interafces (also called single abstract method interfaces). Infact, they provide shortcut to the verbose anonymous class (with single method) implementations.
So, in simple words, Lambda expression = abstract method implementation (of the functional interface).
For example, your expression can be assigned to the below Functional Interface:
public interface MyInterface {//define Functional Interafce (SAM)
public int someMethod(int a);
}
public class Test {
public static void main(String[] args) {
MyInterface myInterface = (int a) -> a +5;//assign the expression to SAM
int output = myInterface.someMethod(20)); //returns 25
}
}

Lambdas are expressions that cannot be used as statements. From JLS8 §15.27:
It is a compile-time error if a lambda expression occurs in a program in someplace other than an assignment context (§5.2), an invocation context (§5.3), or a casting context (§5.5).
Consider this example:
// functional interface
interface Operator
{
int apply(int a, int b);
}
// method that expects instance of the interface
int calculate(int a, int b, Operator op)
{
return op.apply(a, b);
}
// lambda expression
Operator plus = (a, b) -> a + b;
// method call
calculate(40, 2, plus);

The issue is, as pointed out above, you are not doing anything with the lambda. This means that:
the compiler does not know which functional interface (e.g. java.util.function.Function) to infer as the type for your lambda.
Your line of code is "not a statement" (another error message often emitted by the compiler). This is similar to something like this:
"Hello";
Which is not valid Java.

A lambda expression cannot stand alone in Java, it need to be associated to a functional interface.
public interface myinterface
{
int mymethod(int a,int b);
}
public static void main(String[] args)
{
myinterface my = ( a,b ) -> {
int mul = a*4;
int add = a+b;
return add; };
}
Note: This is the first and last time you will see implemention of interface without keyword "Implements".
Play Around: try adding a new dummy method to your interface myinterface and you will see that your code will fail to compile, thus indicating that reference has to be only made from Functional interface not from general interfaces.
public interface myinterface
{
int mymethod(int a,int b);
int newmethod(String j);
}
public static void main(String[] args) {
myinterface my = ( a,b ) -> {
int mul = a*4;
int add = a+b;
return add;
};
Compilation Error: The target type of this expression must be a
functional interface

Related

why the method is giving error eventhough i have bounded gererics type parameter {T extends Number}? Here T should accept Integer,Double,Float...etc? [duplicate]

I am trying to create a generic class in Java that will perform operations on numbers. In the following example, addition, as follows:
public class Example <T extends Number> {
public T add(T a, T b){
return a + b;
}
}
Forgive my naivety as I am relatively new to Java Generics. This code fails to compile with the error:
The operator + is undefined for the argument type(s) T, T
I thought that with the addition of "extends Number" the code would compile. Is it possible to do this Java or will I have to create overridden methods for each Number type?
Number does not have a + operator associated with it, nor can it since there is no operator overloading.
It would be nice though.
Basically, you are asking java to autobox a descedant of Number which happens to include Integer, Float and Double, that could be autoboxed and have a plus operator applied, however, there could be any number of other unknown descendants of Number that cannot be autoboxed, and this cannot be known until runtime. (Damn erasure)
Your problem is not really related to generics, rather to operators, primitives vs objects, and autoboxing.
Think about this:
public static void main(String[] args) {
Number a = new Integer(2);
Number b = new Integer(3);
Number c = a + b;
}
The above does not compile
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(3);
Number c = a + b;
}
The above does compile, but only because of autoboxing - which is kind of a hacky syntax glue introduced in Java 5, and only works (in compile time) with some concrete types : int-Integer for example.
Behind the scenes, the Java compiler is rewriting the last statement ("I must unbox a and b to apply the sum operator with primitive datatypes, and box the result to assign it to object c") thus:
Number c = Integer.valueOf( a.intValue() + b.intValue() );
Java can't unbox a Number because it does not know at compile time the concrete type and hence it cannot guess its primitive counterpart.
You can do something like this
class Example <T extends Number> {
public Number add(T a, T b){
return new Double(a.doubleValue() + b.doubleValue());
}
}
Yes, Nathan is correct. If you want something like this, you have to write it yourself
public class Example <T extends Number> {
private final Calculator<T> calc;
public Example(Calculator<T> calc) {
this.calc = calc;
}
public T add(T a, T b){
return calc.add(a,b);
}
}
public interface Calculator<T extends Number> {
public T add(T a, T b);
}
public class IntCalc implements Calculator<Integer> {
public final static IntCalc INSTANCE = new IntCalc();
private IntCalc(){}
public Integer add(Integer a, Integer b) { return a + b; }
}
...
Example<Integer> ex = new Example<Integer>(IntCalc.INSTANCE);
System.out.println(ex.add(12,13));
Too bad Java has no type classes (Haskell) or implicit objects (Scala), this task would be a perfect use case...
There are similar questions to this one, and the answer is you can't do it like that.
You could check if a and b are an instance of Long/Double/Integer/etc. and delegate the add to methods like:
public Integer add(Integer a, Integer b) {
return a+b; // this actually uses auto boxing and unboxing to int
}
And you would need to create one for every type that extends Number, so that's not really feasible. In other words, don't use generics for numeric operations. Number as a superclass is pretty limited.
Consider Example<Number>, how would + work on that? There is no add or similar in Number or even the likes of Integer.
Worse consider final class FunkyNumber extends Number { ... weird stuff, no add op ... }.
Even the java runtime library has this problem, most of the methods dealing with primitives have to duplicate the same functionality.
The fastest option would be to write your code for one type and then copy it and replace the type to generate the methods for the other types. A short script should be enough to do this.

Error assigning lambda to functional interface variable: inherited abstract method must be implemented. Why?

I implemented the functional interface, using the functional method in a lambda function. Everything works fine except I get an error that this inherited abstract method (in my case, the functional method) must be implemented. And here I'm confused. I used the lambda function to implement this functional method. Why should I again implement the method?
How is the implementation of functional methods done correctly?
Here is my code:
interface MyFunction {
int getValue(int num);
}
class Factorial implements MyFunction {
public static void main (String [] args) {
MyFunction myFactorialFunc = (num) -> {
int fact = 1;
for(int i = 1; i <= num; i++){
fact = i * fact;
}
return fact;
};
System.out.println(myFactorialFunc.getValue(7));
}
}
I guess you must have heard from somewhere that "you can implement single-method interfaces with a lambda expression!" and proceeded to try it out by writing this code, all the while misunderstanding what is meant by that.
Lambda expressions doesn't actually allow you to write class MyClass implements SomeInterface without declaring the required method. As far as the compiler is concerned, Factorial only has a main method declared, and no getValue method, so it doesn't implement the MyFunction interface.
Your code does demonstrate "you can implement single-method interfaces with a lambda expression" though. Here in the main method, you assigned a lambda expression to a variable of type MyFunction:
MyFunction myFactorialFunc = (num) -> {
int fact = 1;
for(int i = 1; i <= num; i++){
fact = i * fact;
}
return fact;
};
Normally, you have to put an implementation of MyFunction on the right-hand side of =, don't you? But now, you can just use a lambda expression! This is because the signature of the lambda expression matches the signature of the single method in the interface, so the compiler goes "yeah, that's fine, I'll just use this as the implementation of that method".
You defined your Factorial class to implement MyFunction, but it doesn't implement the method of that interface (int getValue(int num);).
The MyFunction instance implemented within your main using a lambda expression doesn't implement that interface for your Factorial class.
Just change it to:
class Factorial {
public static void main (String [] args) {
MyFunction myFactorialFunc = (num) -> {
int fact = 1;
for(int i = 1; i <= num; i++){
fact = i * fact;
}
return fact;
};
System.out.println(myFactorialFunc.getValue(7));
}
}

Generic type instantiation and Lambdas

I am working with anonymous functions and functional interfaces, I have one functional interface that takes two objects of same type and returns true or false.
package elementutils;
#FunctionalInterface
public interface TwoElementPredicate <T> {
public boolean compare(T a, T b);
}
I use the functional interface in another class to get the "better element" using anonymous functions, the method betterElement takes two objects and the instance of the functional interface. Then i should be able to create lambdas to compare two objects of the same type in the main.
package elementutils;
public class ElementUtils <T> {
public T betterElement(T a, T b, TwoElementPredicate elements){
if (elements.compare(a, b) == true) {
return a;
}else {
return b;
}
}
public static void main(String[] args) {
//String x= ElementUtils.betterElement("java", "python", (a, b) -> a.length() < b.length());
//int y= ElementUtils.betterElement(2, 3, (a, b) -> a > b);
//double z= ElementUtils.betterElement(2.5, 3.7, (a, b) -> a > b);
// all this give errors
}
}
The functions should take any object as long as they are from the same type. I thought I could achieve that using generic classes but when I instantiate the lambdas it seems that the elements are always of type object so I cannot use length() and cannot assigne them to a String for example.
I hope I explained myself correctly, any help will be highly appreciated.
You are missing the type parameter T on TwoElementPredicate and hence you are using a raw type
You need to declare the parameter elements as of type TwoElementPredicate<T>
Your definition of betterElement uses a raw TwoElementPredicate, so its arguments will always be Objects. Instead, you should use a generic parameter, with the same T as the elements:
public T betterElement(T a, T b, TwoElementPredicate<T> elements) {
// Here ----------------------------------------^

Why Java-8 lambda need invokeDynamic byteCode to invoke an interface method

Hi I am trying to understand the advantages of using Lambda expression, where I heard usage of the invokeDynamic byteCode by JVM to execute lambda expression will improve the performance compared to XXXX(Sorry I don't know, it might be an Anonymous inner class).
My question is Why Lambda expressions need invokeDynamic byteCode.
For example:
public class LambdaTest {
public static void main(String[] args) {
MathOperation addition = (int a, int b) -> a + b;
addition.operation(1, 2);
}
private static int operate(int a, int b, MathOperation operation){
return operation.operation(a, b);
}
interface MathOperation {
int operation(int a, int b);
}
}
where the lambda expression (int a, int b) -> a + b; can be simply desugared into a static method like
private static int lambda$1(int a, int b) {
return a + b;
}
which eventually can be invoked using invokstatic byteCode right?
More questions: What is the dynamicity lambda expression trying to achieve, when all the argument type, returns type are defined during the compile time itself.
For example: in the lambda expression (int a, int b) -> a + b; everything(argument type, return type) got defined during the compile time itself right?
The method holding the body of the lambda expression is not invoked via invokedynamic. The implementation of the functional interface is invoked via invokeinterface, just like any other interface method. The caller even doesn’t know whether an object implementing an interface has been generated for a lambda expression.
How this generated implementation of the interface invokes the synthetic method, is JRE specific, but usually it happens via an ordinary invocation (invokestatic, invokevirtual or invokespecial). Only the access rights follow different rules, i.e. the method can be invoked by the generated class despite being private.
The invokedynamic instruction is used for the instantiation of the interface implementation, so it allows arbitrary, unknown implementation classes, including classes, which do not exist at compile-time, but are generated at runtime. It also opens the possibility to return an existing instance instead of creating a new one, which is impossible for ordinary instance creation code.

Can I do arithmetic operations on the Number baseclass?

I am trying to create a generic class in Java that will perform operations on numbers. In the following example, addition, as follows:
public class Example <T extends Number> {
public T add(T a, T b){
return a + b;
}
}
Forgive my naivety as I am relatively new to Java Generics. This code fails to compile with the error:
The operator + is undefined for the argument type(s) T, T
I thought that with the addition of "extends Number" the code would compile. Is it possible to do this Java or will I have to create overridden methods for each Number type?
Number does not have a + operator associated with it, nor can it since there is no operator overloading.
It would be nice though.
Basically, you are asking java to autobox a descedant of Number which happens to include Integer, Float and Double, that could be autoboxed and have a plus operator applied, however, there could be any number of other unknown descendants of Number that cannot be autoboxed, and this cannot be known until runtime. (Damn erasure)
Your problem is not really related to generics, rather to operators, primitives vs objects, and autoboxing.
Think about this:
public static void main(String[] args) {
Number a = new Integer(2);
Number b = new Integer(3);
Number c = a + b;
}
The above does not compile
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(3);
Number c = a + b;
}
The above does compile, but only because of autoboxing - which is kind of a hacky syntax glue introduced in Java 5, and only works (in compile time) with some concrete types : int-Integer for example.
Behind the scenes, the Java compiler is rewriting the last statement ("I must unbox a and b to apply the sum operator with primitive datatypes, and box the result to assign it to object c") thus:
Number c = Integer.valueOf( a.intValue() + b.intValue() );
Java can't unbox a Number because it does not know at compile time the concrete type and hence it cannot guess its primitive counterpart.
You can do something like this
class Example <T extends Number> {
public Number add(T a, T b){
return new Double(a.doubleValue() + b.doubleValue());
}
}
Yes, Nathan is correct. If you want something like this, you have to write it yourself
public class Example <T extends Number> {
private final Calculator<T> calc;
public Example(Calculator<T> calc) {
this.calc = calc;
}
public T add(T a, T b){
return calc.add(a,b);
}
}
public interface Calculator<T extends Number> {
public T add(T a, T b);
}
public class IntCalc implements Calculator<Integer> {
public final static IntCalc INSTANCE = new IntCalc();
private IntCalc(){}
public Integer add(Integer a, Integer b) { return a + b; }
}
...
Example<Integer> ex = new Example<Integer>(IntCalc.INSTANCE);
System.out.println(ex.add(12,13));
Too bad Java has no type classes (Haskell) or implicit objects (Scala), this task would be a perfect use case...
There are similar questions to this one, and the answer is you can't do it like that.
You could check if a and b are an instance of Long/Double/Integer/etc. and delegate the add to methods like:
public Integer add(Integer a, Integer b) {
return a+b; // this actually uses auto boxing and unboxing to int
}
And you would need to create one for every type that extends Number, so that's not really feasible. In other words, don't use generics for numeric operations. Number as a superclass is pretty limited.
Consider Example<Number>, how would + work on that? There is no add or similar in Number or even the likes of Integer.
Worse consider final class FunkyNumber extends Number { ... weird stuff, no add op ... }.
Even the java runtime library has this problem, most of the methods dealing with primitives have to duplicate the same functionality.
The fastest option would be to write your code for one type and then copy it and replace the type to generate the methods for the other types. A short script should be enough to do this.

Categories