Interface binding in Eclipse - java

I have the following code in Eclipse(Helios)/STS which runs and prints console output when doing a Run As> Java Application, in spite of obvious compilation issues
public interface ITest{
String func();
}
public static class Test implements ITest{
void printFunc(){
System.out.println("Inside Test Function");
}
}
public static void main(String[] args) {
Test test = new Test();
test.printFunc();
}
Can anyone pinpoint the reasoning behind this Eclipse functioning.
Note: Doing a javac externally obviously fails to compile.

Eclipse's Java compiler is designed to cope with flaky, non-compiling code. It will add whatever stuff is necessary to the code to get it to compile.
See this question What is the difference between javac and the Eclipse compiler?

It might have been that you have coded the class successfully before the errors. Eclipse auto-compiles your file while you are coding. Just then, you happen to have errors.. then you decide to run as Java Application, Eclipse will run the most recent compiled class.
I tried your code, implemented the necessary methods to remove the errors, then removed it again to put back the errors.. sure enough, it printed out "Inside Test Function". I also tried commenting out System.out.println("Inside Test Function"); and it still printed out.
In another try, I created another class, added your code, then run (without implementing the errors to avoid auto-compiling), then it printed out an error..
java.lang.NoSuchMethodError: main
Exception in thread "main"

Related

What is the difference between java.lang.NoSuchMethodError main Exception in thread "main " and Error: Main method not found in class

I have this class
public class demo3 {
private static void sum()
{
}
}
when I tried to run this class, I expected the error to be java.lang.NoSuchMethodError main Exception in thread "main "
however, the output was a bit different and I got below message
Error: Main method not found in class demo3, please define the main method as:
public static void main(String[] args)
now this got my curiosity as to in which case I will get java.lang.NoSuchMethodError or in which case I will get the other error message.
You get the Main method not found message when public static void main(String[]) can't be found in the class that you've asked the JVM to start running. That is, the entry point of the overall program cannot be found.
You get the java.lang.NoSuchMethodError message if your (already running) code attempts to invoke a method on a class which was available at compile time, but not available in the version of the class you are using at runtime (for example, you compile against one version of the library, and then update the library jar without recompiling). This can occur at any point in the program.
There doesn't look to be anything in JLS which says that NoSuchMethodError can't be thrown, rather than the Main method not found; however, failing to write a main method (either entirely, or writing one with the wrong signature) is a far more common mistake than the "class changed after compilation" case, especially for beginners, for whom the NoSuchMethodError might be too cryptic. There is no harm in providing a more user-friendly message in this one case.

Debugging Java code tested with Spock and JMockit

I'm using Spock to write tests for a Java application. The test includes a JMockit MockUp for the class. When debugging a test (using IntelliJ) I would like to be able to step into the Java code. I realize using F5 to step into the code won't work, because of all the Groovy magic with reflection that goes on. Unfortunately, even if I set a breakpoint in the Java code, it still will not be hit, even though it runs through the code.
Here is the code to test:
public class TestClass {
private static void initializeProperties() {
// Code that will not run during test
}
public static boolean getValue() {
return true; // <=== BREAK POINT SET HERE WILL NEVER BE HIT
}
}
Here is the test code:
class TestClassSpec extends Specification {
void setup() {
new MockUp<TestClass>() {
#Mock
public static void initializeProperties() {}
}
}
void "run test"() {
when:
boolean result = TestClass.getValue()
then:
result == true
}
}
The test passes and everything works well, but I'm not able to debug into the Java code.
Note: I can debug if I do not use the JMockit MockUp, but that is required to test a private static method in my production code.
Any ideas on how to get the debugger to stop in the Java code from a Spock test that uses JMockit?
This answer has plagued me for days, and I have searched and searched for an answer. Fifteen minutes after posting for help, I find the answer . So for anyone else who runs into this, here's my solution - this is all thanks to this answer: https://stackoverflow.com/a/4852727/2601060
In short, the breakpoint is removed when the class is redefined by JMockit. The solution is to set a break point in the test, and once the debugger has stopped in the test THEN set the breakpoint in the Java code.
And there was much rejoicing...

Why/how does JUnit pass tests with compiler errors?

I've just started learning about TDD and am trying to write a simple project that way.
I'm using Eclipse and JUnit, and every time I make a change I run all the tests in the relevant package.
But then I'm very surprised to see in the package explorer that one of my test cases has a big red cross indicating a compiler problem... Annoyed I figured that I got my eclipse shortcuts mixed up and haven't been running all the tests, as they are all passing.
But when I start fiddling about, I realise that it seems Eclipse + JUnit will run and pass tests even if there are compiler errors...
The JUnit test case:
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class ATestCase {
private Command command;
private Invoker invoker;
#Before
public void setUp() throws Exception {
command = new Command() {
public void methodA(){};
//haven't implemented methodB()
};
invoker = new Invoker(command);
}
#Test
public void test(){
invoker.invoke();
}
}
interface Command{
void methodA();
void methodB();
}
The Invoker class:
class Invoker{
private Command command;
public Invoker(Command command) {
this.command = command;
//if I invoke methodB() I get UnresolvedCompilationError
}
public void invoke(){
command.methodA();
//only if I call methodB here
//do I get Unresolved compilation problem
// command.methodB();
}
}
The command object I create in setUp in the test case only implements one of the interface's methods. This of course causes a compilation error warning in Eclipse.
However unless I actually call that method in the test case, the test passes.
If I do call the method, then the test fails with 'unresolved compilation error'.
Can anyone explain to me what exactly is going on?
******EDIT******
I'm not sure why this was closed as a duplicate.
Apparently I'm supposed to edit this question to make the difference clear:
Well the question I'm supposed to be duplicating asks in the first line:
What are the possible causes of a "java.lang.Error: Unresolved
compilation problem"?
The title of my question states I'm asking:
Why/how does JUnit pass tests with compiler errors?
As in how can code which shouldn't compile be run by JUnit without causing errors?
I fully understand the causes of the Unresolved Compilation Error, it's the obvious unresolved compilation error in my code. What I don't understand is how the error doesn't always occur (it only occurs when I specifically call an unimplemented method) and how the tests pass?!
It may be that these issues are related, but unless there is a specific answer explaining how they are related I fail to see how they are in any way duplicate questions...
When a class fails to implement an interface method, the Java compiler does not reject the code but instead emits bytecode for the method that will raise the runtime error seen. This explains why JUnit is able to run the tests and why the test passes if you don't call methodB - the runtime error does not get raised.
Per this page, this does not occur by default but requires that you have the Java -> Debug 'Suspend execution on compilation errors' setting enabled.
I'm assuming that is by design: to allow for testing specific methods without having to worry about whether other dependencies which the compiler would pick up on anyway are resolved or not. i.e. we shouldn't be using JUnit to tell us whether our entire project can compile or not.

why java can run with a compile time error in eclipse

interface A
{
public void f();
public void g();
}
class B implements A
{
public void f()
{
System.out.println("B.f()");
}
}
public class Main
{
public static void main(String[] args)
{
B tmp = new B();
tmp.f();
System.out.println("B.f()");
}
}
I don't implement all the method in the interface A in B
and it has a error that
The type B must implement the inherited abstract method A.g()
but why it can get the output that
B.f()
B.f()
Eclipse allows you to run code with compile-time errors - after giving you a warning and offering you the option to back out (which you should normally take).
If you try to call tmp.g() you'll get an exception indicating a compile-time failure.
Occasionally it can be useful to run code which doesn't fully compile - particularly if the compile-time failure is unrelated to the code you actually wish to run, e.g. when unit testing - but I would be very careful about how you use this feature.
Eclipse can "patch" around certain classes of compile errors, and run a program even if errors exist. Normally, you get a dialog box that says the following:
Errors exist in required project(s):
(project name)
Proceed with launch?
[X] Always launch without asking
If you select Proceed, or if you have disabled the dialog, Eclipse will proceed to fix the compile errors if possible. If you try to run code impacted by the compile error, you'll get a runtime exception.
In this case, Eclipse adds a dummy B.g() method containing just the following:
throw new java.lang.Error("Unresolved compilation problem: \n"
"The type B must implement the inherited abstract method A.g()");
By inserting this dummy method, the code will compile properly and it will run. If you never call B.g, then you'll never see this error.

Don't run android application in eclipse

When I want to run my java code, I have this problem :
Exeption in thread "main" java.lang.ArrayIndexOutOfBoundsException:0
at com.ibm.icu.text.BreakDictionary.main(BreakDictionary.java:44)
i can't run my code... It's simple
public class main{
public static void main(String[] args){
System.out.print("Hi");
}
}
WTF is com.ibm.icu.text.BreakDictionary?
Make sure of the class whose main you are running. I suspect you're not running your class. Your java command should look like this:
java -cp somepath com.mycompany.mypackage.MyClass
Better yet, use an IDE like eclipse that make it easy to run a class
Also, rename your class from main to MyClass - anything with a leading capital letter - it's good coding style
Exeption in thread "main" java.lang.ArrayIndexOutOfBoundsException:0
at com.ibm.icu.text.BreakDictionary.main(BreakDictionary.java:44)
This exception says that you are running the main method in a class named BreakDictionary. In your sample code the class is called main.
You can solve this in eclipse by right-clicking your class and select run as and then java application. This will ensure that you are using your main class as the entry point and not BreakDictionary (which seems to either be on your classpath or you are simply not running the correct project in eclipse).

Categories