Thursday, July 29, 2010

Inner Classes in Java

As we all know what an inner class is so lets try to know few more rules about Inner Classes.

Inner classes cannot have static members. only static final variables.

Interfaces are never inner.

Static classes are not inner classes.

Inner classes may inherit static members that are not compile-time constants even though they may not declare them.

Nested classes that are not inner classes may declare static members freely, in accordance with the usual rules of the Java programming language. Member interfaces are always implicitly static so they are never considered to be inner classes.A statement or expression occurs in a static context if and only if the innermost method, constructor, instance initializer, static initializer, field initializer, or explicit constructor invocation statement enclosing the statement or expression is a static method, a static initializer, the variable initializer of a static variable, or an explicit constructor invocation statement.

A blank final field of a lexically enclosing class may not be assigned within an inner class.


For Example:

class HasStatic {
static int j = 100;
}

class Outer{

final int z=10;

class Inner extends HasStatic {
static final int x = 3;
static int y = 4;
}

static class Inner2 {
public static int size=130;
}

interface InnerInteface {
public static int size=100;
}
}

public class InnerClassDemo {

public static void main(String[] args) {

Outer outer=new Outer();
System.out.println(outer.new Inner().y);
System.out.println(outer.new Inner().x);
System.out.println(outer.new Inner().j);

System.out.println(Outer.Inner2.size);

System.out.println(Outer.InnerInteface.size);
}
}

Hence it gives compilation problems as y cannot be used in inner class "Inner".

Also note Method parameter names may not be redeclared as local variables of the method, or as exception parameters of catch clauses in a try statement of the method or constructor. However, a parameter of a method or constructor may be shadowed anywhere inside a class declaration nested within that method or constructor. Such a nested class declaration could declare either a local class or an anonymous class.


For Example:
public class MethodParameterExamples {

public String s="bt";

public void m1(String s) {
s=this.s;
s="uk";

//abstract
class InnerClass extends MethodParameterExamples {

String s="ros";

public void m1() {
System.out.println(super.s=this.s);
}
}

InnerClass innerClass=new InnerClass();
innerClass.s=s;
innerClass.m1();

}

public static void main(String[] args) {

MethodParameterExamples methodParameterExamples=new MethodParameterExamples();
methodParameterExamples.m1("vij");
System.out.println(methodParameterExamples.s);

}

}

Hence Prints the output:
uk
bt

Now coming to Section Nested Inner Classes:

Consider the below program.


class WithDeepNesting {
boolean toBe;

WithDeepNesting(boolean b) { toBe = b;}

class Nested {
boolean theQuestion;

class DeeplyNested {

DeeplyNested(){
theQuestion = toBe || !toBe;
}
}
}

public static void main(String[] args) {

WithDeepNesting withDeepNesting=new WithDeepNesting(true);
WithDeepNesting.Nested nested=withDeepNesting.new Nested();
nested.new DeeplyNested();
System.out.println(nested.theQuestion);

}
}

Please note that Inner classes whose declarations do not occur in a static context may freely refer to the instance variables of their enclosing class. An instance variable is always defined with respect to an instance. In the case of instance variables of an enclosing class, the instance variable must be defined with respect to an enclosing instance of that class. So, for example, the class Local above has an enclosing instance of class Outer. As a further example:

Here, every instance of WithDeepNesting.Nested.DeeplyNested has an enclosing instance of class WithDeepNesting.Nested (its immediately enclosing instance) and an enclosing instance of class WithDeepNesting (its 2nd lexically enclosing instance). Hence it prints: true.

No comments: