I'm playing around with lambdas in eclipse oxygen. I have code something like this
#FunctionalInterface
interface TriFinction<O,I,J, R> {
R whatEver(O object, I input1, J input2);
}
class Dummy {
public String dothingsWithTwoArgs(String a, String b) {
return a+b;
}
}
public class LambdaTest {
public static void main(String[] args) {
Dummy::dothingsWithTwoArgs;
}
}
I'm unable to extract Dummy::dothingsWithTwoArgs. Eclipse is showing a compilation error Syntax error, insert "AssignmentOperator Expression" to complete Expression, but extraction is working perfectly in intellij. Is there any workaround for this in eclipse?
First notice that your dothingsWithTwoArgs is not static, therefore you should not attempt to invoke it in a static fashion: you should use an instance of your Dummy class or make the dothingsWithTwoArgs static
Here are some illustrations that will get you going
First you need a method that has your TriFinction as one of its parameters
Example:
public static String sumToString(String a,String b, String c, TriFinction<String,String,String,String> f) {
return f.whatEver(a, b, c);
}
Second, in your Dummy class you need a method that matches the genric signature of your TriFinction (which means for example that it receives three parameters for O,J, and I and that it returns a R)
for example
public static String dothingsWithThreeArgs(String a, String b,String c) {
return a+ " " + b + " " + c;
}
Now you can use the method reference in your main method for example:
System.out.println(sumToString("2","3","4",Dummy::dothingsWithThreeArgs));
Here is the full example along with a second illustration from your TriFinction (and I guess you should refactor and rename it TriFunction :) )
public class ExtractWithLambda {
#FunctionalInterface
interface TriFinction<O,I,J, R> {
R whatEver(O object, I input1, J input2);
}
public static String writeEqu(TriFinction<Double,Double,Double,String> f) {
return f.whatEver(2.5, 3.4, 5.6);
}
public static String sumToString(String a,String b, String c, TriFinction<String,String,String,String> f) {
return f.whatEver(a, b, c);
}
public static void main(String[] args) {
System.out.println(writeEqu(Dummy::writeEquation));
System.out.println(sumToString("2","3","4",Dummy::dothingsWithThreeArgs));
}
}
class Dummy {
public static String dothingsWithThreeArgs(String a, String b,String c) {
return a+ " " + b + " " + c;
}
public static String writeEquation(double a, double b, double c) {
return a + "*x*x " + b + "*x " + c ;
}
}
One main thing we should know is Compilation error messages are compiler dependent. This does not mean different compilers would produce different error messages all the time. But there can be situations.
Regarding your problem I found this answer and post. That post has a detailed explanation about this error under topic not a statement.
So the main point is this. As you mentioned, this error message is specific to Eclipse compiler. The point the compiler is raising is your line is just an expression, not a statement. In order to understand it as a statement, the compiler wants you to add an assignment operator. That's the whole meaning of insert "AssignmentOperator Expression" to complete Expression. So what you all want to do is just assign that line to another defined variable, which would look like this.
someVariable = Dummy::dothingsWithTwoArgs;
Hope you can find more depth and more examples with the sources I mentioned. :))
Extracting Lambda to a method seems only suported from Eclipse 4.23 (Feb. 2022, 6 years later)
Extract lambda body to method
A new content assist has been added to extract the body of a lambda to a method.
To invoke the new feature, perform a Ctrl + 1 within the selected lambda body:
Related
Here's a Interview question.
Question:
public class test {
public static void main(String[] args) {
int a= 10;
int b=10;
method(a,b);
System.out.println(a);
System.out.println(b);
}
public static void method(int a,int b){
//**Under the premise of not changing the original question, how to write this function in the main function to output a=100,b=200?**
}
}
Answers:
import java.lang.reflect.Field;
class Text
{
public static void main(String[] args) throws Exception
{
int a = 10;
int b = 10;
method(a,b);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
private static void method(Integer a, Integer b) throws Exception
{
Field fielda = a.getClass().getDeclaredField("value");
fielda.setAccessible(true);
fielda.set(a,100);
System.out.println("a = " + a);
Field fieldb = b.getClass().getDeclaredField("value");
fieldb.setAccessible(true);
fieldb.set(b,200);
System.out.println("b = " + b);
System.exit(0);
}
}
And we can overwrite function print. in function 'method. etc...
So, my questions are:
Why a.getClass().getDeclaredField("value") can get variabe "a" from method main? I checked each item of a.getClass().getDeclaredFields returned array in debug mode, but did not find any regularities.
Are there any refers about every item meaning of a.getClass().getDeclaredFields returned array.
I know that methods' inner variables save in stack memory,and shared in the same thread. Can we change variable main's "a" value through Reflection or Using a new Java classloader?
The solution is a big disguise. It doesn’t change the variables of the main method at all. Note that it also changed the question’s method declaration from void method(int a,int b) to void method(Integer a, Integer b) (I’m not sure whether this is allowed for solutions), to enforce a boxing conversion from int to Integer. (It also added throws Exception declarations that weren’t in the original code).
Therefore, the a.getClass().getDeclaredField("value") expression doesn’t access anything from the main method, but the value field of the wrapper class java.lang.Integer. Then, access override is used to modify the value field.
But note that this nasty hack still has no effect on the main method. Since the main method uses int primitives, these values are unaffected by any manipulation of the java.lang.Integer instances. That’s why the solution uses another trick—it does the printing itself using the lines
System.out.println("a = " + a);
and
System.out.println("b = " + b);
followed by
System.exit(0);
Since these print statements are using the Integer objects, they are affected by the hack, whereas the System.exit(0) call ensures that the method never returns to the main method, so the main method’s print statements are never executed.
Once you understand the “do the printing yourself and exit the JVM” part, you recognize that the entire Reflection hack is entirely unnecessary. You can achieve exactly the same using
public static void method(int a, int b) {
System.out.println("a = 100");
System.out.println("b = 200");
System.exit(0);
}
This does exactly the same as the solution and it doesn’t even need to change the question’s method signature. But, of course, without the distracting Reflection hack, it’s more obvious what’s actually going on.
That said, Reflection doesn’t offer any way to access local variables. You would need a debugger for that. Since you also asked for a ClassLoader, you can manipulate the code of a class to use different values, but that wouldn’t fulfill the question’s requirement of doing it inside of method, i.e. while the code in question is already running.
This the following a good design if I wanted to call a method to a method?
The code below is this just an example.
public Enigma(){
String sentences = "This ";
method1(sentences);
}
public void method1(String x){
x = x + "a ";
method2(x);
}
public void method2(String x){
x = x + "test ";
method3(x);
}
public String method3(String x){
x = x + "!";
return x;
}
If those methods are only called from the constructor, then there's no point in making them public.
Also, usually you'd call method1 from the outside after creating the Enigma object.
Finally, as you may know chaining calls like that may lead to code that is difficult to understand and follow.
But if your question is related to "does this work", the answer is simply yes :)
I believe you are on the right track. Even if your example doesn't do anything concrete, I believe it is a good idea to point out possible flaws.
The class name has to be the same name of its Java file. For example, your class "Enigma" has to be written in the "Enigma.java" file. Otherwise, problems can appear. Often it is a good thing to remember.
Note that you can call method3 from method2 in a way that uses the output of this function.
public method2(String x) {
x = x + "a ";
x = x + method3(x)
}
Note that this example is only to show you how you can retrieve the value of the method you just called. You can always simply call this method the same way you call a void even if the method returns something. Both options work, it is for you to decide what your program has to do and how, depending on the context.
Overall, the correct Java syntax for your class is this one:
public class Enigma {
//put your class properties here
public Enigma(){
String sentences = "This ";
method1(sentences);
}
public void method1(String x) {
x = x + "a "; method2(x);
}
public void method2(String x) {
x = x + "test "; method3(x);
}
public String method3(String x) {
x = x + "!";
return x;
}
}
After this, if you are using Enigmaa as an object, you might want to add a constructor. If Enigma is not an object, use static methods by writing static just before your method return type in the declaration. For example: public void method1(String x) { would become public static void method1(String x) {. Doing so when possible is a good way to keep simple a program that acts like a script.
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
I think I have written this program pretty well. It gives me no errors, but it is not giving me any output either. What is wrong with this? I checked other programs to see if anything is wrong with Eclipse, but every other program is running except this.
Note: I am newbie Java learner. Explain the problem in detail. I know I have written the spelling of Inheritance wrong.
public class Inheritence {
int a;
String b;
Inheritence(int x, String y) {
a = x;
b = y;
}
}
class B extends Inheritence {
int c;
B(int j, String k, int l) {
super(4, "Srimanth");
a = j;
k = b;
c = l;
}
public static void main(String args[]) {
Inheritence obj1 = new Inheritence(4, "Srimanth");
B obj2 = new B(4, "Srimanth", 5);
System.out
.println("The details of the guy are" + obj1.a + " " + obj1.b);
System.out.println("The details of the guy are" + obj2.c);
}
}
The error in your code is that main method is defined in a non public class B . Move main method to public class Inheritence or define make class B subclass of Inheritence and Inheritence having main method.
The name of the file is Inheritence.java?
In that case you should put different classes in different files, and call the one that have the main method (better write the parameters like "String[] args") probably can't find the main method
When I run it I get the following:
error: Class names, 'Inheritence', are only accepted if annotation processing is
explicitly requested
1 error
Try the changing the file name/class name.
This problem is about overloading methods and I think I understand the basic idea but I get some weird error "Overloading.java:14".
Like my problem is that I don't know how to return two parameters of my method. So I thought maybe convert the method with the two int parameters with toString(), then return it. Something gone miserably wrong.
The output have to be following:
a 10
a and b 10, 20
char a
result 97
My problem as it is, is with the "a and b 10, 20", and have not done the "char a" just to make you guys aware. This is not homework.
Here is my code so far contains a main class and a helper class:
OverMain Class :
class OverMain {
public static void main(String args[]) {
Overload overload = new Overload();
int result;
System.out.println("a " + overload.test(10)); //prints a 10
System.out.println("a and b " + overload.test(10, 20)); //the method I have trouble with
result = overload.test('a'); //prints Result 97
System.out.println("Result " + result);
}
}
Overload Class:
//The class which is suppose to overload test methods
class Overload {
public int test(int a) {
return a;
}
public String test(int a, int b) {
String string = "";
string = test(a, b).toString();
return string;
}
}
It's not really clear what you're trying to do, but you don't return parameters, and I don't think overloading is really the problem here. To take overloading out of the situation, you can always change the methods to have different names - get it working that way, and then you can always change the names back later and work out any conflicts.
In your case I think you just need:
public String test(int a, int b) {
return a + ", " + b;
}
In other words, just use string concatenation and the automatic int to String conversion that the compiler will apply in order to use string concatenation.
Note that if your code actually compiled, you'd get a stack overflow because you're calling test(a, b) from test(int a, int b) - it would just call itself forever, until you ran out of stack space.
The problem is in your method test(int, int)
public String test(int a, int b) {
String string = "";
string = test(a, b).toString(); // Danger
return string;
}
You have a never ending recurrence relation
Solution: return a + ", " + b