Thursday, 24 July 2014

What is a reasonable order of Java modifiers (abstract, final, public, static, etc.)?

It is reasonable to use the order according to the Java Virtual Machine Specification, Table 4.4
  • public           
  • protected
  • private
  • abstract
  • static
  • final
  • transient
  • volatile
  • synchronized
  • native
  • strictfp

Can you override Static Methods in Java?

  • Well... the answer is NO if you think from the perspective of how an overriden method should behave in Java. But, you don't get any compiler error if you try to override a static method. That means, if you try to override, Java doesn't stop you doing that; but you certainly don't get the same effect as you get for non-static methods.
  •  Overriding in Java simply means that the particular method would be called based on the run time type of the object and not on the compile time type of it (which is the case with overridden static methods).
  •  Okay... any guesses for the reason why do they behave strangely? Because they are class methods and hence access to them is always resolved during compile time only using the compile time type information. 
  • Accessing them using object references is just an extra liberty given by the designers of Java and we should certainly not think of stopping that practice only when they restrict it :-)

Example: let's try to see what happens if we try overriding a static method:-

class SuperClass{
......
public static void staticMethod(){
System.out.println("SuperClass: inside staticMethod");
}
......
}

public class SubClass extends SuperClass{

......
//overriding the static method
public static void staticMethod(){
System.out.println("SubClass: inside staticMethod");
}

......

public static void main(String []args){
......
SuperClass superClassWithSuperCons = new SuperClass();
SuperClass superClassWithSubCons = new SubClass();
SubClass subClassWithSubCons = new SubClass();

superClassWithSuperCons.staticMethod();

superClassWithSubCons.staticMethod();
subClassWithSubCons.staticMethod();
...
}

}


Output:-

SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod

  • Notice the second line of the output. Had the staticMethod been overriden this line should have been identical to the third line as we're invoking the 'staticMethod()' on an object of Runtime Type as 'SubClass' and not as 'SuperClass'. 
  • This confirms that the static methods are always resolved using their compile time type information only.

Tuesday, 15 July 2014

Difference between string object and string literal

When you do this:

String str = "abc";

You are calling the intern() method on String. This method references an internal pool of 'String' objects. If the String you called intern() on already resides in the pool, then a reference to that String is assigned to str. If not, then the new String is placed in the pool, and a reference to it is then assigned to str.

Given the following code:

String str = "abc";
String str2 = "abc";
boolean identity = str == str2;

When you check for object identity by doing == (you are literally asking - do these two references point to the same object?), you get true.

However, you don't need to intern() Strings. You can force the creation on a new Object on the Heap by doing this:

String str = new String("abc");
String str2 = new String("abc");
boolean identity = str == str2;

In this instance, str and str2 are references to different Objects, neither of which have been interned so that when you test for Object identity using ==, you will get false.

In terms of good coding practice - do not use == to check for String equality, use .equals() instead.

Saturday, 14 June 2014

When initialization occurs in an interface?


    • According to Java language specification, initialization of an interface consists of executing the initializers for fields declared in the interface. Before a class is initialized, its direct superclass must be initialized.
    • But interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized. Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.
    • Following is example for this :
    • The reference to J.i is to a field that is a compile-time constant; therefore, it does not cause I to be initialized. The reference to K.j is a reference to a field actually declared in interface J that is not a compile-time constant; this causes initialization of the fields of interface J, but not those of its superinterface I, nor those of interface K. Despite the fact that the name K is used to refer to field j of interface J, interface K is not initialized.
    • System.out.println(J.i); // The i variable is inherited from I but since it is a constant - you don't have to go through the whole process of initializing I, just reference it and get on with things.
    • System.out.println(K.j); // now this is more complicated. Since the variable holds something other than a constant, the first thing that we have to do is initialize J so that we can figure out what to DO to come up with the value of j.
    • Initializing interface J causes variable j to be initialized first: executing Test.out("j",3) which prints j=3, and setting the variable j to 3 (note the return type on the method). Now jj is initialized executing Test.out("jj",4) which prints jj=4 and sets the variable jj to 4.
    • Now that initialization is done we can evaluate and execute the println for K.j which prints the current value of j which is 3.

      An Array of Characters is Not a String

      • In the Java programming language, unlike C, an array of char is not a String, and neither a String nor an array of char is terminated by '\u0000' (the NULL character)
      • A String object is immutable, that is, its contents never change, while an array of char has mutable elements.
      • The method toCharArray in class String returns an array of characters containing the same character sequence as a String. The class StringBuffer implements useful methods on mutable arrays of characters.

      Array Store Exception

      For an array whose type is A[], where A is a reference type, an assignment to a component of the array is checked at run time to ensure that the value being assigned is assignable to the component.

      If the type of the value being assigned is not assignment-compatible with the component type, an ArrayStoreException is thrown.



      • The variable pa has type Point[] and the variable cpa has as its value a reference to an object of type ColoredPoint[]. 
      • A ColoredPoint can be assigned to a Point; therefore, the value of cpa can be assigned to pa.
      • A reference to this array pa, for example, testing whether pa[1] is null, will not result in a run-time type error. 
      • This is because the element of the array of type ColoredPoint[] is a ColoredPoint, and every ColoredPoint can stand in for a Point, since Point is the superclass of ColoredPoint.
      • On the other hand, an assignment to the array pa can result in a run-time error. At compile time, an assignment to an element of pa is checked to make sure that the value assigned is a Point. 
      • But since pa holds a reference to an array of ColoredPoint, the assignment is valid only if the type of the value assigned at run time is, more specifically, a ColoredPoint. 
      • The Java Virtual Machine checks for such a situation at run time to ensure that the assignment is valid; if not, an ArrayStoreException is thrown.

      Friday, 30 May 2014

      Initialization of Fields in Interfaces

      Every declarator in a field declaration of an interface must have a variable initializer, or a compile-time error occurs.

      The initializer need not be a constant expression. It is a compile-time error if the initializer of an interface field uses the simple name of the same field or another field whose declaration occurs textually later in the same interface.

      It is a compile-time error if the keyword this or the keyword super  occurs in the initializer of an interface field, unless the occurrence is within the body of an anonymous class. At run time, the initializer is evaluated and the field assignment performed exactly once, when the interface is initialized.

      Note that interface fields that are constant variables  are initialized before other interface fields. This also applies to static fields that are constant variables in classes . Such fields will never be observed to have their default initial values , even by devious programs.

      Example : Forward Reference to a Field
      interface Test {
          float f = j;
           int j = 1;
           int k = k + 1;
      }

      This program causes two compile-time errors, because j is referred to in the initialization of f before j is declared, and because the initialization of k refers to k itself.