just trying out things in java, found following issue.
DefaultAndStaticMethodMain.java:8: error: not a statement
implementation1::sendNotification;
^
1 error
Following is my code.
ParentInterface:
public interface ParentInterface {
default void callForCompletion() {
System.out.println("<<<< Notification sending completed. >>>>");
}
}
Child interface:
public interface ChildInterface extends ParentInterface {
public abstract void sendNotification();
static String printNotificationSentMessage() {
return "Notification is sent successfully.";
}
}
Implementation 1:
public class Implementation1 implements ChildInterface {
#Override
public void sendNotification() {
System.out.println("Implementation --- 1");
System.out.println("Sending notification via email >>>");
}
}
Implementation 2:
public class Implementation2 implements ChildInterface {
#Override
public void sendNotification() {
System.out.println("Implementation ---- 2.");
System.out.println("Sending notification via SMS >>>");
}
}
Main method:
public class DefaultAndStaticMethodMain {
public static void main(String[] args) {
Implementation1 implementation1 = new Implementation1();
implementation1::sendNotification; // Compilation error as shown above.
Implementation2 implementation2 = new Implementation2();
implementation2.sendNotification();
// Following works fine.
// Arrays.asList(implementation1, implementation2).stream().forEach(SomeInterfaceToBeRenamed::sendNotification);
}
}
I am not sure what am I doing wrong, I have JDK 13 installed in local machine and working with IntelliJ 2019.3 with JDK 11. I checked that IntelliJ supports JDK 13
Thanks.
Update
By mistake I left a semi-colon over there, removed it, please check again.
A method reference is not the same as a method call. Those are two distinct things.
A method call is a standalone expression, or, more precisely, an expression statement. That means that in your case implementation2.sendNotification() works, as you would expect.
A method reference, however,
is used to refer to the invocation of a method without actually performing the invocation
and is not a standalone expression. It can only be used where a lambda expression can also be used. A method reference as a standalone expression does not compile, just like an arithmetic expression without assignment (e.g. 3 + 17;). This is enforced by the Java Language Specification, § 14.8 and § 15.13.
More to read:
Please Explain Java 8 Method Reference to instance Method using class name
Method reference in Java 8
What do you intend for the implementation1::sendNotification; line to do? Judging by the implementation2.sendNotification(); line below it looks like you're trying to call sendNotification on implementation1, which is written like this:
implementation1.sendNotification();
The :: notation is a method reference, and (as the error message says) it an identifier, not a statement, and thus can't be a line on its own. Similarly you couldn't write implementation1; (a variable) or ChildInterface; (a class identifier) as a statement.
The .forEach(SomeInterfaceToBeRenamed::sendNotification); line compiles because you are passing the method reference to forEach(), and it in turn invokes each sendNotification() method.
Related
I am currently trying to call Java Code in C#. One possibility is IKVM, whereupon I looked at a tutorial for this tool. I have to say, and that's really curious: the tool seems to work in part.
But now to my problem:
So I took the following tutorial (https://www.codeproject.com/Articles/594632/IKVM-NET-in-Details). Following this example, I wrote my own Java code. In addition, I have added a few more methods to the java file. My source code for testing is relatively short:
The Java source code:
package TestProject;
public class TestClassJava {
public static void Print() {
System.out.println("Hi C# from JAVA");
}
public static void PrintStr(String str) {
System.out.println(str);
}
public static String returnString() {
return "Hi C# from Java method";
}
public static String returnInputString(String input) {
return input;
}
public static int retInt() {
return 42;
}
public static int returnIntNumber(int inp) {
return inp;
}
public static boolean returnTrueBoolean() {
return true;
}
}
The C# source code:
using System;
using System.IO;
using TestProject;
using ikvm.io;
using ikvm.lang;
using ikvm;
using ikvm.runtime;
using ikvm.extensions;
namespace IKVM_Test_Case_08_08_2019
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(TestClassJava.retInt()); // shows: 42 (works!)
Console.WriteLine(TestClassJava.returnString()); // shows: Hi C# from Java method (works!)
TestClassJava.Print(); // here appears the error System.TypeInitializationException
TestClassJava.PrintStr("Hallo"); // here appears the error System.TypeInitializationException
Console.WriteLine(TestClassJava.Print()); // can not convert from void to bool
}
}
}
The whimsical part now happens while running the program in C#. I try the methods in C# via Console.WriteLine(TestClassJava.retInt()); then, for example, the number 42 will be given to me, as it should be. I can also call the method returnString().
In the methods without return value, however, Print() & PrintStr(String str), I always get the following error message:
Error message:
System.TypeInitializationException
HResult=0x80131534
Message=The type initializer for 'java.lang.StdIO' threw an exception.
Source=IKVM.OpenJDK.Core
StackTrace:
at java.lang.System.get_out()
at TestProject.TestClassJava.Print()
at IKVM_Test_Case_08_08_2019.Program.Main(String[] args) in C:\Users\...\source\repos\IKVM_Test_Case_08_08_2019\IKVM_Test_Case_08_08_2019\Program.cs:line 19
Inner Exception 1:
MissingMethodException: Method not found: 'Void System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.Security.AccessControl.FileSystemRights, System.IO.FileShare, Int32, System.IO.FileOptions)'.
I can not quite explain that, so I asked this question in the hope, that someone knows an advice.
According to the quoted tutorial, it all had to work that way. Nevertheless, I get this error message.
I hope my question is so far understandable.
I'm creating a Nativescript plugin. It includes a custom Android Library (AAR) and I want to use it from the Typescript code. When I run a demo (in device or emulator) I get a TypeError: sender.registerListener is not a function error when calling this registerListener method, which is weird because I'm able to call other methods of the same object.
I think that it could be because I am not implementing properly the interface required as parameter. I think that I can explain it better with code:
Sender.java: the public class I will use in Typescript:
package com.berriart.android.myplugin;
public class Sender {
public static final String TAG = "Sender";
private Context _context = null;
public Sender(Context context) {
_context = context;
}
public void send(final String messagePath, final String messageToSend) {
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "Send call: " + messagePath + " " + messageToSend);
}
}
public void registerListener(MessageListener listener) {
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "registerListener");
}
}
// Other code here
}
MessageListener.java: the interface that must be implemented by the registerListener parameter:
package com.berriart.android.myplugin;
public interface MessageListener {
void receive(String messagePath, String messageReceived);
}
This is the Typescript (Nativescript) code of the plugin ( to ):
import * as app from "tns-core-modules/application";
export class WearMessaging {
public static send(messagePath: string, messageToSend: string) {
let sender = new com.berriart.android.myplugin.Sender(app.android.context);
sender.send(messagePath, messageToSend);
}
public static registerListener(receiveCallback: (messagePath: string, messageReceived: string) => void) {
let messageListener = new com.berriart.android.myplugin.MessageListener({
receive: receiveCallback
});
let sender = new com.berriart.android.myplugin.Sender(app.android.context);
sender.registerListener(messageListener);
}
}
If I include WearMessaging.send("/demo", "Hola"); in my nativescript application it compiles and run properly, it's call the Java method successfuly. But if I run:
WearMessaging.registerListener((messagePath: string, messageReceived: string) => {
console.log(messagePath);
console.log(messageReceived);
});
The application stops at run time and throws: TypeError: sender.registerListener is not a function refering to the myplugin.android.ts file.
I'm getting crazy trying to make this work, so, let me know if you have any clue. As I say I think that is because I'm missing something when implementing the interface and because the parameter type do not match them method is not being recognized, but maybe I'm wrong.
Here you can see some official doc:
https://docs.nativescript.org/runtimes/android/generator/extend-class-interface
Thanks in advance.
Ok, I solved it :S
It seems that the incremental build was doing something wrong. After deleting manually the build files of the demo everything went fine:
rm -rf platforms/android/build/*
rm -rf platforms/android/app/build/*
# Then build & deploy again
So, question code seems to be fine if you need to do something similar.
I'm not a java jock, but I'm trying to learn how to use node-java. I tried to run one of the examples listed on npm java and gethub node-java and they don't work. I think my method is not initialize in my node.js script correctly. I'm using JDK/JRE 1.8 on a Window 10 laptop. Below is my simple code example. Any help would be appreciated.
var Test = java.import("com.sample.SearchQueryRulesFromTable");
var result = Test.SearchQueryRulesFromTable("C1", "P1");
console.log(result);
Error in node-java
nodeJavaBridge.js:233
return java.newInstanceSync.apply(java, args);
^
TypeError: Could not find method
"com.sample.SearchQueryRulesFromTable(java.lang.String,
java.lang.String)" on class "class com.sample.SearchQueryRulesFromTable".
Possible matches:
public com.sample.SearchQueryRulesFromTable() at Error (native)
at javaClassConstructorProxy….
Here is part of my java code:
...
public class SearchQueryRulesFromTable {
...
public static final void main(String[] args) {...
Results of javap
Compiled from "SearchQueryRulesFromTable.java
public class com.sample.SearchQueryRulesFromTable {
public com.sample.SearchQueryRulesFromTable();
descriptor: ()V
public static final void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
}
#AlphaVictor I have tried to call the main method using node-java constructs that didn't seem to work. I don't know what I'm doing wrong. Below is the main method in SearchQueryRulesFromTable:
ItemSearch item1 = new ItemSearch();
item1.setSearchCustomer(args[0]);
item1.setSearchItem(args[1]);
Using:
java.callStaticMethodSync("com.sample.SearchQueryRulesFromTable",
"ItemSearch(item1)","C1", "P1", function(err, results) {
if(err) {console.error(err);
javaLangSystem.out.printlnSync('test complete! '+ results);return;}
Error:
C:\Users\rdouglas\AppData\Roaming\npm\node_modules\NewProjects\08-
egilerapp1\classes>node test.js
(node) sys is deprecated. Use util instead.
C:\Users\rdouglas\AppData\Roaming\npm\node_modules\NewProjects\08-
egilerapp1\classes\test.js:14
var result =
java.callStaticMethodSync("com.sample.SearchQueryRulesFromTable",
"ItemSearch","C1", "P1")
^
Error:
Could not find method "ItemSearch(java.lang.String, java.lang.String)" on
class "class com.sample.SearchQueryRulesFromTable". No methods with that
name.
at Error (native)
at Object.<anonymous>
(C:\Users\rdouglas\AppData\Roaming\npm\node_modules\NewProjects\08-
egilerapp1\classes\test.js:14:19)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
at node.js:968:3
TypeError: Could not find method
"com.sample.SearchQueryRulesFromTable(java.lang.String,
java.lang.String)" on class "class com.sample.SearchQueryRulesFromTable".
This error tells you that you have tried to call a constructor on class SearchQueryRulesFromTable that accepts two String arguments. There is no such constructor defined on that class.
Your code is attempting to call this non-existent constructor here:
SearchQueryRulesFromTable("C1", "P1");
Depending on what you are trying to do, you may want to call the main method within SearchQueryRulesFromTable instead, and pass it a String[].
I have 2 classes, cPuzzlePieces and cShapes. cPuzzlePieces extends cShapes.
Right now I get 2 errors on cPuzzlePeaces.
The first error is on the first line of the def and says:
implacet super constructor cShapes is undefined for default constructor.
The second error on the first line of the construter says
constructor call must be the first staemnt
and it is on the first staement.
Here is my code:
public class cPuzzlePieces extends cShapes{ // first error message is here
int mAmountOfShapes;
Context InContext;
void cPuzzlePieces(Context MyContext) throws IOException
{
super( MyContext); // SECOND ERROR MESSAGE IS HERE
InContext=MyContext;
}
}
public class cShapes
{
cShape[] MyShapes;
public int mAmountOfShapes=0;
boolean AnimationRunning=false;
cShapes(Context InContext) throws IOException
{
}
...
...
}
This
void cPuzzlePieces(Context MyContext) throws IOException
is a method, not a constructor.
Remove the void keyword. Add an appropriate access modifier (if need be). Also check for the IOException. Currently, nothing is throwing it.
Related
"Constructor call must be the first statement in a constructor" issue in Java
Java naming conventions state that class names should start with an uppercase alphanumeric character. Please follow that.
I was trying to modify class dynamically, such as call sleep() before a line. I attached agent to a jvm during runtime using Attach method. Then I got target class from jvm, and modified it(Add a line to call sleep()). And I got redine class error. I am using JDK1.6. I am using ASM core API to modify class.
The Error:
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:124)
Is there something wrong with ASM code? Actually my ASM code finished its job(to Add a line to call sleep()). Does current jvm not support retransform class? It seems failed to execute retransformClasses(). Does retransformClasses() not support the ASM operation(to add a line into a method to call sleep())? Any ideas? thx
EDIT:
The class which I want modify:
import java.util.concurrent.TimeUnit;
public class Person {
public String name = "abc";
public String address = "xxxxx" ;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void sayHello() throws InterruptedException {
System.out.println("aaaaaaaaaa");
System.out.println("Hello World!");
TimeUnit.SECONDS.sleep(120);
System.out.println("dd");
}
public void sayHello2() {
System.out.println("aaaaaaaaaa1");
System.out.println("Hello World!2");
}
public static void main (String args[]) {
try {
Person p = new Person();
p.sayHello(); // linenumber #9. A line to call Sleep() should be added before #here.
p.sayHello2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
My ASM code:
public void visitMethodInsn(int arg0, String arg1, String arg2, String arg3) {
Label la=new Label();
mv.visitLabel(la);
int linenumber=la.getOffset();
if(linenumber==9) {
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/util/concurrent/TimeUnit", "SECONDS", "Ljava/util/concurrent/TimeUnit;");
mv.visitLdcInsn(new Long("5"));
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/concurrent/TimeUnit", "sleep", "(J)V");
super.visitMethodInsn(arg0, arg1, arg2, arg3);
}
}
Not looking at your code yet, I think I can suggest something. When a class is first loaded, in addition to storing the class's byte codes, the JVM also has tables where it keeps track of the types of fields and the signatures of methods in each class.
The error you are seeing would suggest that the class was loaded, this signature information was stored and then you tried to add the method after that.
If you instead put your agent jar onto the command line, you can do things before the class is loaded for the first time. If you add your method before the signature info is stored away, you should be good.
If you have to connect the agent after the process is already launched, you may be able to transform the class but you may only be able to transform it without changing the set of fields, their types, or the methods, or their signatures. In other words, you may be able to change the byte codes but you have to not invalidate the previously-stored meta information.