Reputation: 3757
We have an application where we publish and interface and an implementation separately. The users will compile against our interface, but only at run-time will they need to deploy the implementation. The implementation is never referred to explicitly.
I got a little curious about what happens if you mix versions of interface and implementation (where newer versions would have for example added methods). So, I made a simple example:
├── mix
│ └── Mix.java
├── v1
│ ├── DummyImpl.java
│ └── DummyInterface.java
└── v2
├── DummyImpl.java
└── DummyInterface.java
v1 of the interface looks like this:
interface DummyInterface {
void v1();
}
v2 of the interface looks like this:
interface DummyInterface {
void v1();
void v2();
}
The Mix.java file looks like this:
class Mix {
public static void main(String[] args) {
DummyInterface di = new DummyImpl();
di.v1();
if (System.getProperty("foo") != null)
di.v2();
}
}
The *Impl classes contain some sort of implementation of the interfaces. What it does is not important. The next step is a bit of trickery.
The v1 implementation clearly does not fulfill the v2 interface, but the JVM will gladly allow me to run the program.
If I set the "foo" property it will fail, but not until I actually get to that line in the code.
I guess this is where my question comes: Is this guaranteed behavior? If so, where is it specified what will/should happen in this case?
My example is of course silly, but since we have a similar situations in a bigger system, I would like to know what we can count on to work, what wouldn't work and what we can't know if it'll work.
Upvotes: 0
Views: 174
Reputation: 88796
Because you abstracted the interface, the client program doesn't know that the version running is v1. When it tries calling a v2 method that doesn't exist in v1, you'll end up getting a (not-so) nice NoSuchMethodError
.
As a reminder, things marked as errors in Java are considered non-recoverable and you normally shouldn't try to catch it.
Upvotes: 1
Reputation: 2507
The compiler generates an invokeinterface
bytecode for your calls there (not invokespecial
). This bytecode does a multistep-lookup for the concrete method to call at runtime. So your code does not fail at compile time.
Upvotes: 4