Wednesday 25 January 2012

Abstract Classes Have Constructors in decompiled code

1) In Java , we have default constructors provided for classes by the compiler (in case one is not declared).

2) The abstract classes can't be instantiated by using the new operator because they don't provide full implementation of all the methods.

Then does it make sense to have constructors inside abstract classes. Let us find it using a sample abstract class:
public abstract class Test{
   public abstract void doSomething();
}

The decompiled code for this class will show the truth about constructors in abstract classes in Java
public abstract class Test
{
    public Test()
    {
    }
    public abstract void doSomething();
}


Why?

The reason is that when a class extends any other class and an instance of the subclass is created then the constructor calls are chained and the super class constructors are invoked. This rule is no exception for abstract class

Moreover, having constructors in a class doesn't necessarily mean that instance of that class will be created using the new operator, but the constructors are intended for writing any initializing code.

Saturday 21 January 2012

Java Puzzler - double chars

The following compiles and produces an output. Can you explain why?

char ch = 'A';
ch *= 1.5;
System.out.println(ch); // prints 'a'

Here is a hint for a simpler example.

byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40

Checking the oddity of a integer number in java

From Jashua Bloch's "Java Puzzlers" book.

// Wrong way to check the oddity
public boolean isOdd(int num){
return (num % 2 == 1) // Broken- for all -ve odd numbers
}

The reason for this would be clear once you read about modulus operator.

// Right Solution
public boolean isOdd(int num){
return (num % 2 != 0)
}

// Much better and Faster
public boolean isOdd(int num){
return (num & 1)
}

Java puzzler: Initiating array of integer to object reference

Can you tell whether the following code will compile or not?

Object o = new int[10];

The answer to this is yes....because Arrays are object only....and super class of an array is java.lang.Object class.

Wednesday 18 January 2012

Java try-catch-finally and return simply


Consider this code :

boolean test () {
try {
return true;
}
finally {
return false;
}
}

Can you guess what will be returned?
This will always return false. My question: why is this? Is there a particular philosophy behind this design decision made by Java? I appreciate any insight, thank you.

Edit: I'm particularly interested as to 'why' Java thinks it's ok to violate the semantics that I define. If I 'return' in a try block, the method should return right then and there. But the JVM decides to ignore my instruction and return from a subroutine that actually hasn't yet been reached.

Technically speaking, the return in the try block won't be ignored if a finally block is defined, only if that finally block also includes a return.

It's a dubious design decision that was probably a mistake in retrospect (much like references being nullable/mutable by default, and, according to some, checked exceptions). In many ways this behaviour is exactly consistent with the colloquial understanding of what finally means - "no matter what happens beforehand in the try block, always run this code." Hence if you return true from a finally block, the overall effect must always to be to return true, no?

In general, this is seldom a good idiom, and you should use finally blocks liberally for cleaning up/closing resources but rarely if ever return a value from them.


Tuesday 17 January 2012

Concatenating integers in java

Suppose we have following values:

int a=1; 
int b=0;
int c=2;
int d=2;
int e=1;


If we want to concatenate these we can use 2 approaches:

Approach 1 : Using usual mathematics
int result = a * 10000 + b * 1000 + c * 100 + d * 10 + e;
String s = Integer.toString(result);

Approach 2 : Appending using StringBuilder
StringBuffer sb = new StringBuffer();
sb.append(a).append(b).append(c)...

Concatenating chars using + operator

Lets look at the following code snippet:
char c1 = 'A';
char c2 = 'B';

Lets try + operator first:

System.out.print(c1+c2);

Can you guess the output....it is not 'ab' but it 131 (= 65+66) i.e. sum of ascii value of 'A' and 'B'.

So it is not parallel to concatenating strings, but how should we concatenate 2 char's ?

Solution 1: Append using StringBuilder
StringBuilder sb = new StringBuilder('a').append('b').append('c');
System.out.println(sb.toString);

Solution 2 : Neater style using + operator for string concatenation
System.out.println("" + char1 + char2 + char3...);

Solution 3 : Using char array
System.out.println(new String(new char[]{a,b,c}));

Comparing the approaches
You should generally use second approach, third doesn't seem normal though and first approach looks like optimization flick. The approach selection depends on the char's having values at compile time or they are provided at the run time. So first read this article.

If the characters are constant, this is fine:
String s = "" + 'a' + 'b' + 'c';

If however they aren't, consider this:

String concat(char... chars) {
  if (chars.length == 0) {
    return "";
  }
  StringBuilder s = new StringBuilder(chars.length);
  for (char c : chars) {
    s.append(c);
  }
  return s.toString();
}

as an appropriate solution.

However some might be tempted to optimise:
String s = "Name: '" + name + "'"; // String name;
into this:
String s = new StringBuilder().append("Name: ").
append(name).append("'").toString();
While this is well-intentioned, the bottom line is DON'T.

Why? As another answer correctly pointed out: the compiler does this for you. So in doing it yourself, you're not allowing the compiler to optimise the code or not depending if its a good idea, the code is harder to read and its unnecessarily complicated.

For low-level optimisation the compiler is better at optimising code than you are.

Let the compiler do its job. In this case the worst case scenario is that the compiler implicitly changes your code to exactly what you wrote. Concatenating 2-3 Strings might be more efficient than constructing a StringBuilder so it might be better to leave it as is. The compiler knows whats best in this regard.

Caution for approach 3

System.out.println(new String(new char[]{a,b,c}));
Though String constructor provides method of concatenating char's, but + operator don't allow so....
So the output of this approach will be :

char alphabets =  {a,b,c};
System.out.println("Alfa "+alphabets);

Output expected may be Alfa abc but actually it is Alfa [C@16f0472.To get the above effect use following :
System.out.println(letters + " easy as " +String.valueOf(alphabets));