Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the interface without recompiling the implementing class

I have the following classes

public abstract interface X 
{
    public abstract void f() throws java.io.IOException;
}


public class Y implements X 
{
    public void f() throws java.io.IOException 
    {
        throw new java.ioIOException("Hello");
    }

    public static void main(String [] args)
    {
        X x = new Y();
        try
        {
            x.f();
        }
        catch (IOException e)
        {
            System.out.println("Caught");
        }
    }

}

Now I compile both and get X.class and Y.class.

Now I change X to remove the throws

public abstract interface X 
{
    public abstract void f();
}

Obviously if I recompile both X & Y, Y's compilation will fail

Y.java:4: f() in Y cannot implement f() in X; overridden method does not throw j
ava.io.IOException

However, what I if only recompile X.java & keep my Y.class which was compiled with the older X.java.

What happens in such a case - is it well defined?

Or does it fall under the category of undefined - i.e. anything can happen?

Are there any guarantees at all - i.e. if I am running it always under Java 1.6.32 under Windows, can I rely on nothing bad happening?

Update: Updated it because some answers said I would get a IncompatibleClassChangeError at runtime. But I don't.

Steps

1) Compile both X.java and Y.java as given above. Run Y.

Output: Caught

2) Change X.java to comment out the throws. Recompile X.java. Do not recompile Y.java.

Run Y

Output: Caught

I am running java on Windows 7

Compiler

javac 1.6.0_35

Runtime

java version "1.6.0_35"
Java(TM) SE Runtime Environment (build 1.6.0_35-b10)
Java HotSpot(TM) Client VM (build 20.10-b01, mixed mode, sharing)
like image 217
user93353 Avatar asked Feb 06 '13 16:02

user93353


People also ask

Can a class implementing an interface have its own methods?

An implemented class can of course have methods NOT declared in its interface . But is bound to implement methods which are declared in the interface unless it is declared abstract .

How do you change a class to an interface in Java?

Press Ctrl+Shift+R and then choose Convert Abstract Class to Interface.

Why use interface for single implementation?

it's super easy to refer to one and figure which APIs are accessible for the clients to call. Lastly, it's better to practice using interfaces as a standard in a project than having to use it on a case by case bases (where you need multiple implementations). This ensures consistency in your project.

Why do we need interface instead of class?

The short answer: An abstract class allows you to create functionality that subclasses can implement or override. An interface only allows you to define functionality, not implement it. And whereas a class can extend only one abstract class, it can take advantage of multiple interfaces.


1 Answers

This is a limitation in Java right now. Create a sub-interface that extends your current interface and override the method without the exception if you really need it. Generally speaking, this is called a "binary change" and results in broken linking when the code runs, and is well-defined in the JLS (there's an entire chapter on it, JLS 13, you specifically want JLS 13.5).

Edit: after further investigation, it turns out I was wrong. From JLS 13.4.21:

Changes to the throws clause of methods or constructors do not break compatibility with pre-existing binaries; these clauses are checked only at compile time.

However, I'd still recommend not doing this since it means a checked exception can essentially become unchecked at runtime.

like image 189
Brian Avatar answered Oct 01 '22 16:10

Brian