Tag Archive for 'scjp'

Tricky example with polymorphism

Example

Can you predict the output of the following code?

class SubTest extends Test {
    public int aNumber;

    public SubTest() {
        aNumber = 17;
    }

    public void doubleANumber() {
        System.out.println("Inside SubTest.doubleANumber()");
        aNumber *= 2;
    }
}

public class Test {
    public int aNumber;

    public Test() {
        aNumber = 6;
    }

    public void doubleANumber() {
        System.out.println("Inside Test.doubleANumber()");
        aNumber *= 2;
    }

    public static void main(String[] args) {
        Test t = new SubTest();
        t.doubleANumber();
        System.out.println(”The value of aNumber is ” + t.aNumber);
    }
}

Result

The output is:
Inside SubTest.doubleANumber()
The value of aNumber is 6

As you see, it was not the reference type but the real object type of t variable that decided which method was invoked at runtime. This way, aNumber of SubTest class was modified. This variable shadowed aNumber of Test class. Therefore, Test.aNumber variable was untouched (didn’t change at all).

Threds: multiple call to run() method

You can call run() method of a thread many times. However, not a single new thread will be started. This way JVM will only execute the code from run() method. And this will not probably be what you tried to achieve.

Remember: to start a new thread, you need to call start() method, which among others, will execute run() method in a new concurrent context.

java.util.IllegalFormatConversionException when using System.out.format()

A few weeks ago I described how to format output using System.out.printl() and System.out.println() methods

Try to run the code below:

double avgAge = 245 / 34;
System.out.format("Average age is %d.", avgAge);

Without doubts you’ll get an exception thrown at runtime:

Average age is Exception in thread "main"
java.util.IllegalFormatConversionException:
d != java.lang.Double
    at java.util.Formatter$FormatSpecifier.failConversion(Unknown Source)
    at java.util.Formatter$FormatSpecifier.printInteger(Unknown Source)
    at java.util.Formatter$FormatSpecifier.print(Unknown Source)
    at java.util.Formatter.format(Unknown Source)
    at java.io.PrintStream.format(Unknown Source)

The reason is becase wrong conversion label was used. To recall, conversion label is ‘%’ sign followed by a letter b, c, d, f, or s inside System.out.format().

In the above example, %d meant that an integral type (byte, Byte, short, Short, int, Integer, long, Long, BigInteger) would be used. However, finally there was a floating point passed (avgAge). This example would work if this conversion label were used: %f.

So, remember to be careful with conversion label!

What happens if concate String value and int?

Can you predict the output/result of the following code?


String s = "A String ";
s += 12345;
System.out.print(s);

The answer is: “A String 12345“.

The reason for that is described in the desciption of String class in Java 2 Platform SE 5.0 API:

The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java.

Unreachable catch block

Always contruct try-catch blocks in a way that assumes catching Exceptions from more detailed to more generic.

Example


try {
    String [] tab = null;
    System.out.println(tab[3]);
} catch (Exception e) {
    System.out.println(”Exception”);
} catch (NullPointerException e) {
    System.out.println(”NullPointerException”);
}

The above presented snippet will cause compilation error:

Unreachable catch block for NullPointerException. It is already handled by the catch block for Exception

Solution


try {
    String [] tab = null;
    System.out.println(tab[3]);
} catch (NullPointerException e) {
    System.out.println(”NullPointerException”);
} catch (Exception e) {
    System.out.println(”Exception”);
}

This way, if you invoke this snippet you’ll get the following output on the screen: “NullPointerException”.

What if you extend an abstract class and implement an interface when both define a method with the same name?

Imagine you need to implement a class that extends an abstract class and implements an interface when both define a method with the same name - test().

Example


interface Implementable { public void test(); }
abstract class Superclass { public abstract void test(); }

public class Test extends Superclass implements Implementable {
    /* definition of load method(s)..... */
}

The following will not compile, getting (among others) duplicate method test() error:


interface Implementable { public void test(); }
abstract class Superclass { public abstract void test(); }

public class Test extends Superclass implements Implementable {
    public void Superclass.test() { }
    public void Implementable.test() { }
}

Solution

The correct implementation looks as follows:


interface Implementable { public void test(); }
abstract class Superclass { public abstract void test(); }

public class Test extends Superclass implements Implementable {
    public void test() { }
}

In such case, you need to define the body of test() method ONLY ONCE.

Formatting output

Usually to print some ouptut you’d use System.out.printl() or System.out.println() method. It’s easy to use but you can face some difficulties in providing output formatted in a specific way.

To format output you can use either of the following methods (they work the same)

  • System.out.format(String format, Object... args)
  • System.out.format(Locale l, String format, Object... args)
  • System.out.printf(String format, Object... args)
  • System.out.printf(Locale l, String format, Object... args)

This is the way how those methods should be used:

%[argIndex$][flags][width][.precision] conversion

where:

  • argIndex - index of the argument passed within the args array
  • flags:
    • - - left justify
    • + - print sign (e.g. +25, -45.7)
    • 0 - pad this argument with zeroes
    • , - use local specific separators (e.g. 124,567,678.877)
    • ( -enclose a negative number in parenthesis
  • width - minimum number of characters to print (nice to keep clean columns)
  • precision - number of digits that will be printed after decimal delimiter (for floating points)
  • conversion:
    • b - boolean
    • c - basic types that represent Unicode characters (char, Character, byte, Byte, short, Short)
    • d - integral types (byte, Byte, short, Short, int, Integer, long, Long, BigInteger)
    • f - floating point (float, Float, double, Double, BigDecimal)
    • s - string (for any argument type)

Exeptions and Errors

In the diagram below I present the hierarchy of most common Exceptions and Errors:


Object
 |
 |_ Throwable
    |
    |_ Error
    |   |
    |   |_ AssertionError
    |   |
    |   |_ LinkageError
    |   |   |
    |   |   |_ ExceptionInInitializerError
    |   |   |
    |   |   |_ NoClassDefFoundError
    |	|   |
    |   |_ VirtualMachineError
    |       |
    |       |_ StackOverflowError
    |
    |_ Exception
        |
        |_ RuntimeException
            |
            |_ NullPointerException
            |
            |_ IllegalArgumentException
            |   |
            |   |_ NumberFormatException
            |
            |_ IndexOutOfBoundException
            |   |
            |   |_ ArrayIndexOutOfBoundException
            |
            |_ ClassCastException
            |
            |_ IllegalStateException

Continue reading ‘Exeptions and Errors’

== might work the same as equals()

It’s a rule that == is used to compare references, not values. To compare values for equality equals() method should be used.
However, as of Java 5, you can also use == to check if two objects’ values are the same… But it works only for the following wrapper objects, if their primitive counterparts’ values are the same:

  • Boolean
  • Byte
  • Character for values: \u0000 (0) ÷ \u007f (127)
  • Byte and Integer for values: -128 ÷ 127

Generics

Mixing generics with legacy code


List<String> words = new ArrayList<String>();
words.add("house");
words.add("book");
addSth(words);

private void addSth(List list) {
   list.add(new Integer(6));
}
  • the above code compiles (but with warnings) and can work fine, at least to the place of addition (if the object was later retrieved from the List it could break down, e.g. words would be treated as List<String> but Integer objects was retrieved) - this code is unsafe
  • generic code is only for the compiler purposes; JVM knows nothing about what really the List holds
  • at runtime both legacy and Java 5 code (with generics) look the same, like pre-generic version

List<String> words = new ArrayList<String>();
System.out.println(words instanceof List<String>);   // WON'T COMPILE

The above code won’t compile since all instances of a generic class have the same runtime class, regardless of their actual type parameters.

Instead, you should do as below:


List<String> words = new ArrayList<String>();
System.out.println(words instanceof List);   // OK

This is also worth a look:


Collection<String> words = new ArrayList<String>();
List<Integer> numbers = new ArrayList<Integer>();
System.out.println(words.getClass() == numbers.getClass()); // produces "true"

Continue reading ‘Generics’