Friday, March 12, 2010

Compilation failures one should know in Java

Those of you who are preparing for SCJP are aware that nearly every question has 'compilation will fail' as an option. Here is a short random list of the compilation failures one should watch out for. No list of this nature can be comprehensive but it does include many useful hints.

while (false) {} // immediate error on the line
while (true) {}; // immediate error on the line following the loop
but while (true) {break;}
System.out.println(""); will compile.

throw new RuntimeException; // the line following is unreachable

go(1) when go(short i); // cannot down cast int to short have to say go((short) 1)

assert (): go(); where void go() // need a string and cannot have void

final X f = new X(); and then f=null; // cannot assign anything to reference
final int x=5; then x++ // especially with interface constants

importing static from a different package whose access is defined as default

We can define unused variables. It is not a compilation failure but just like unused imports.

switch case has a non-compile time literal (ie it is not defined and initiated final on the same line. It is not good enough to declare it as final on one line and then initialize it on the next).

You can't change the return type of overridden method, if return is int in parent then can't return Integer or short in the child. The temptation because of covariant returns is that it may be possible. An overridden method can return the child of a class defined in the parent. However it is a compile error to return parent to a child return type. If expecting Number m() return Integer; is fine, and Integer m() return Integer; is fine but Integer m() return Number; will not compile.

Calling super or instance from static block. Always ensure that an object exists in main before invocation of methods.

Using join, sleep or wait without handling InterruptedException or throwing InterrupedException from run(). The latter breaches the contract of Runnable interface by throwing an unexpected checked exception.

Method with no return type will not compile

new myrunnable().start will not compile. Has to be new Thread(myrunnable).start

class X is not correct nor is class

import static with just the class name fails

There is no such thing as super.super to invoke parent's parent.

You cannot override a static method with a non-static or vice versa.

try {} System.out.println("Here"); catch () {} will fail. No statements between try and catch.

parse needs to catch ParseException

run() cannot throw InterruptedException // no checked exception can be thrown which interface didn't define

for(String s:aa) // declaration has to be within foreach and s should not have been declared before. However it is OK to have s being used in multiple foreach as each has just the local scope.

assert 1 > 2: go(); // will not compile if from within main or any static block if go() not static

inner classes cannot have static members so be wary of their definitions.

import static java.lang.Integer.MAX_VALUE; then import static java.lang.Short.MAX_VALUE; as MAX_VALUE already defined.

declaring enum in a method fails

void doMore() {throw new IOException) fails becuase checked exception must say doMaore() throws IOException

If we catch Exception() then compiler won't allow any child of it to follow it. The order matters.

Putting long in switch expression, it can only be int or thing which can convert to in like char, byte, short

trying to use uninitialized local variable in a method or trying to prefix them with access modifier. Only valid modifier within method is final. Watch out for private int i = 5 in a method.

enum outside class can not be marked static, final, abstract, private or protected. Within the class it can be marked static, private or protected but not abstract or final.
myenum xx= new myenum(); won't compile. Enums are just initialised.

Trying to cast char into a String. char is a primitive and String is an object so S = c fails.

Instance variables cannot be marked strictfp, native, synchronized, abstract. final and transient are fine.

Not having a proper main() method is a runtime error, not a compiler error!

char c = -1; is illegal but char c = (char) -1 is OK. Char is unsigned integer literal with max value of 65535;

byte a = 3; byte b = 2; but byte c = a + b; will not compile as the result is an int. However byte c = 3 +5 is OK as within range and the compiler knows.

float f = 23.4; will not compile as 23.4 is a double.
A variable defined within the initialisation block is not visible to the program, ie {int j = 1;} j cannot be seen anywhere. Trying to use it later will not compile.

int i = 5; static {i = 7;} will not work as i is non-static.

You can't widen an Integer into a Long. The wrapper classes are different objects.

if (5 && 6) will not compile. The expression has to evaluate to boolean

if (x=6) is an illegal argument to if. It is just assigning. Can get away with this with boolean otherwise compile fails.

Integer i = new Integer(4); switch (i) is wrong if used as a case expression in switch statement.

continue statements must be inside a loop; otherwise, you’ll get a compiler error. break statements must be used inside either a loop or switch statement.

Labelled continue and break statements must be inside the loop that has the same label name; otherwise, the code will not compile.

Object test() { return (Double) 2.7;} works Object test() { return (Float) 2.7;} doesn't works 2.7 boxes to Double

Short n = new Short((short) 3); without the cast it fails. However it is ok to say Short s = 555; Integer i = 1 etc as long as they are within range.

More importantly it is fine to compare the incompatible wrapper types like Integer, Short etc with relational operators like greater than or greater than or equal to but not right to use ==. For relational comparisons of greater than, less than etc. it auto unboxes and doesn't complain.

boolean equals(Object o) {return true;} doesn't compile. hashCode(), toString() too are PUBLIC methods. As they are without public modifier they are improper override.

Watch out for missing semicolon in the definition of anonymous inner class.

The compiler will complain if you try to invoke any method on an anonymous inner class reference that is not in the superclass class definition.

Beware of sticking static in front of run() it will not compile as being improper override.

The public access modifier is the only one that allows code from outside a package to access methods in a package regardless of inheritance. If we are overriding a method in a subclass in a different package then the method must be public.

While using an interface from a different package, it must be declared public or we will not be able to use it. Just default package will not work.

No comments:

Post a Comment