Monday, September 12, 2011

Method Members

Every book I've read always mentioned about class members and interface members  but there isn't much written about method members (I don't know if that term fit). I did a lot of experiments and was able to come up with the golden rule on how to determine if a declaration on a method is valid:

    "Only inner classes and local variables are allowed inside a method and that the only allowed modifiers  are  final and abstract (for inner classes only )  "
So the following are all valid :
public class MemberTest {

    public void method1() {
        final int x = 1;
        int y = 2;
      
      
        abstract class InnerAbstractClass {
      
        }
      
        class Inner {
      
      
        }
      
        final class InnerFinal {
      
        }
           
    }   

}
note: an inner class is a non-static nested class


Invalid members:

public class InvalidMethodMembers {

    public void method1() {

       
        static class InnerAbstractClass {
       
        }
       

        final static class InnerStatic {
       
        }
       
        enum E { }
        interface I { } //a nested interface is explicitly static
       
       
    }
   
}

By now you might be wodering why I even bothered to come up with that statement LOL. but tell you what, said fact would really be  usefull on say your OCJP exam  where you can encounter tricky questions ,specially about the inner and nested class :) .



MingMing


for Clarice :)

Thursday, September 8, 2011

Inherittance , Overriding, and Hiding

For a while now , I thought overriding was , well overriding , where you override a method on a super class with your method with the same method signature. It was only when I've read about overriding's formal definition on the JLS when I realized that this was only partially true.

This article has the following sub-topics :
[I] formal definition of overriding
[II] hiding
[III] rules for hiding and overriding

[I] Formal definition of overriding


The JLS states that :

An instance method m1 declared in a class C overrides another instance method, m2,
declared in class A if all of the following are true:
  • C is a subclass of A.
  • The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
  • Either:
  • m2 is public, protected, or declared with default access in the same package as C, or
  • m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2, such that m3
  • overrides m2.
Moreover, if m1 is not abstract, then m1 is said to implement any and all
declarations of abstract methods that it overrides.

Let's dissect this to see what we can get :

An instance method m1 declared in a class C overrides another instance method, m2,
declared in class A if all of the following are true:

The definition specifically stated that overriding are for instance methods . So what are these methods? simple :P non-static methods (very noob indeed) ( This is the key in differentiating overriding over hiding )

From here on out we've narrowed down the scope of overriding . We just have to keep in mind that overriding are for non-static methods



The code above would print :
test overriding [ baby]

It's pretty obvious that the methods that you would override are from you're superclass, so I guess I'll proceed with the next statement

The signature of m1 is a subsignature (§8.4.2) of the signature of m2.

How could you determine that a method is a subsignature of the other? The JLS states :

The signature of a method m1 is a subsignature of the signature of a method m2 if
either:
• m2 has the same signature as m1, or
• the signature of m1 is the same as the erasure of the signature of m2

Two methods have the same signature if they have the same name and argument
types

oh oh :D so first we only need to worry about non-static methods, now what the JLS is saying is We should always remember that overriding is about methods having the same signatures, anything else is not overriding ( huwow stating the obvious haha)

see code below as an example:


The method print with the ellipses , is not overriding the print method on class A ( Yeah I hear you back there, and yes I admit I'm noob lol , and yeah I know it's overloading)

The next statements after that are boring to discuss lol.

I bet by now you have the following questions in mind,
Q.1 what will happen if the method from the parent class is static and your overriding method is non static?
Q.2 what if the method from parent class is non-static and the the overriding method is static?
Q.3 and what if the overriding and the overridden method are both static?

We have the following answers
Q.1 what will happen if the method from the parent class is static and your overriding method is non static?

public class C extends A{

//instance method, this is overriding
public void print(String x ){

System.out.println(x + " [baby] " ) ;
}


public static void main (String [] args) {

C c = new C () ;
c.print ("test overriding");
}

}

class A {

//isntance method
static public void print(String x ){

System.out.println(x + " [mama] " ) ;
}


}

A.1. This would result into a compile time error . (overridden method is static)

Q.2 what if the method from parent class is non-static and the the overriding method is static?
public class C extends A{

//instance method, this is overriding
public static void print(String x ){

System.out.println(x + " [baby] " ) ;
}


public static void main (String [] args) {

C c = new C () ;
c.print ("test overriding");
}

}

class A {

//isntance method
public void print(String x ){

System.out.println(x + " [mama] " ) ;
}


}
A.2. Same with the first answer, it would produce a compile time error. ( Overriding method is static )


Q.3 - what if the overriding and the overridden method are both static?
public class C2 extends A2{

//class method
public static void print(String x ){

System.out.println(x + " [baby] " ) ;
}


public static void main (String [] args) {

C2 c2 = new C2 () ;
c2.print ("test hiding");
}

}

class A2 {

//class method
public static void print(String x ){

System.out.println(x + " [mama] " ) ;
}


}

A.3 The code would compile, but this is actually not overriding , this one is called hiding. Yes that's the difference , you're probably cursing yourself by now knowing that It's the sole difference lol :))

overriding = non-static
hiding = static :)

[II] Hiding

So basically, Hiding is overriding , except that you use this for static methods

Well that one went well :))

[III] rules for hiding and overriding

We still have these lingering questions in mind ( since we mentioned that only the method signatures should be the same ) :
Q.1 What if they have different return types?
Q.2 What if the overridden method is throwing an exception?
Q.3. What if they have different access modifiers?
Q.4 Why am I still writing this blog entry? LOL


Q.1 What if they have different return types?
A.1 This is allowed , provided that the overriding method's return type is return-type-substitutable for the overridden method.
you didn't see that coming huh? :D all this technical words are getting into you're head huh? makes you wanna scratch your head huh? lol (corny mo bert). how can a lone soul like me determine if a return type is return-type-substitutable?
JLS! Basa!
A method declaration d1 with return type R1 is return-type-substitutable for another
method d2 with return type R2, if and only if the following conditions hold:

  • If R1 is void then R2 is void.
  • If R1 is a primitive type, then R2 is identical to R1.
  • If R1 is a reference type then:
  • R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or
  • R1 = |R2|
If R1 is void then R2 is void. The code below fairly displays this rule. if you have a void return type on the parent class' instance method, you're overriding method should also be void. The code below would generate a compile time error (Attempting to use incompatible return types)


class A {

//isntance method
public int print(String x ){

System.out.println(x + " [mama] " ) ;
}


}

public class C extends A{

//instance method, this is overriding
public void print(String x ){

System.out.println(x + " [baby] " ) ;
}

public static void main (String [] args) {

C c = new C () ;
c.print ("test overriding");
}

}

If R1 is a primitive type, then R2 is identical to R1

We all know the primitives, int , short, long, double , float etc. , So the rule is that , they should always be identical (just like the rule about void return types ) , The code below would generate a compile time error (Similar to those on the previous code example)

class A {

//isntance method
public double print(String x ){

System.out.println(x + " [mama] " ) ;
return 1;
}


}

public class C extends A{

//instance method, this is overriding
public int print(String x ){

System.out.println(x + " [baby] " ) ;
return 1;
}

public static void main (String [] args) {

C c = new C () ;
c.print ("test overriding");
}

}

If R1 is a reference type then:

  • R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or
  • R1 = |R2|
to give you an example of the rule regarding R1 being a subtype of R2, refer to the code below:


the code would compile just fine. however if we change the return type of the method in C3. we would get a compile time error stating that we are attempting to use incompatible return type:





Q.2 What if the overridden method is throwing an exception?
An overriding class is only allowed to throw an exception that is not new or that is not broader than the exception.

Consider the following code :



The code would compile just fine, but if we interchange the exception types on the overriding and overridden methods we would get the following compile time error:



Q.3. What if they have different access modifiers?

The overriding instance method's access modifier should be less restrictive than the instance method that we are trying to override.
the order of the access modifiers based on restriction is as follows ( descending )

  • private
  • default
  • protected
  • public.
You could check the example below to understand further :



IF you try to use public on the parent class, and use a private access modifier on the child class, you would get the following exception :




Q.4 Why am I still writing this blog entry? LOL
be passionate on what you do and everything else will follow.