Note that there are some explanatory texts on larger screens.

plurals
  1. POOverloaded package-private method causes compilation failure - Is this a JLS oddity or javac bug?
    primarykey
    data
    text
    <p>I've come across an oddity of the JLS, or a JavaC bug (not sure which). Please read the following and provide an explanation, citing JLS passage or Sun Bug ID, as appropriate.</p> <p>Suppose I have a contrived project with code in three "modules" -</p> <ol> <li>API - defines the framework API - think Servlet API</li> <li>Impl - defines the API implementation - think Tomcat Servlet container</li> <li>App - the application I wrote</li> </ol> <p>Here are the classes in each module:</p> <p>API - <code>MessagePrinter.java</code></p> <pre><code>package api; public class MessagePrinter { public void print(String message) { System.out.println("MESSAGE: " + message); } } </code></pre> <p>API - <code>MessageHolder.java</code> (yes, it references an "impl" class - more on this later)</p> <pre><code>package api; import impl.MessagePrinterInternal; public class MessageHolder { private final String message; public MessageHolder(String message) { this.message = message; } public void print(MessagePrinter printer) { printer.print(message); } /** * NOTE: Package-Private visibility. */ void print(MessagePrinterInternal printer) { printer.print(message); } } </code></pre> <p>Impl - <code>MessagePrinterInternal.java</code> - This class depends on an API class. As the name suggests, it is intended for "internal" use elsewhere in my little framework.</p> <pre><code>package impl; import api.MessagePrinter; /** * An "internal" class, not meant to be added to your * application classpath. Think the Tomcat Servlet API implementation classes. */ public class MessagePrinterInternal extends MessagePrinter { public void print(String message) { System.out.println("INTERNAL: " + message); } } </code></pre> <p>Finally, the sole class in the App module...<code>MyApp.java</code></p> <pre><code>import api.MessageHolder; import api.MessagePrinter; public class MyApp { public static void main(String[] args) { MessageHolder holder = new MessageHolder("Hope this compiles"); holder.print(new MessagePrinter()); } } </code></pre> <p>So, now I attempt to compile my little application, MyApp.java. Suppose my API jars are exported via a jar, say api.jar, and being a good citizen I only referencd that jar in my classpath - not the Impl class shiped in impl.jar.</p> <p>Now, obviously there is a flaw in my framework design in that the API classes shouldn't have any dependency on "internal" implementation classes. However, what came as a surprise is that MyApp.java didn't compile at all. </p> <pre><code>javac -cp api.jar src\MyApp.java src\MyApp.java:11: cannot access impl.MessagePrinterInternal class file for impl.MessagePrinterInternal not found holder.print(new MessagePrinter()); ^ 1 error </code></pre> <p>The problem is that the compiler is trying to resolve the version print() to use, due to method overloading. However, the compilation error is somewhat unexpected, as one of the methods is package-private, and therefore not visible to MyApp.</p> <p>So, is this a javac bug, or some oddity of the JLS? </p> <p>Compiler: Sun javac 1.6.0_14</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload