1: Declarations, Initialization and ScopingS2C Home « 1: Declarations, Initialization and Scoping

In this lesson we look at all types of class declaration and extension and how to use interfaces and the package and import statements. We examine the declaration, initialization and usage of primitives, arrays, enums, and objects as static, instance, local variables and their respective scopes. After this we cover correct use of overriding and overloading of methods as well as identifying legal return values for methods. we investigate constructors to determine if a default constructor will be created, and if so, determine the behaviour of that constructor. We finish of this lesson by studying class instantiation and how to instantiate nested and non-nested classes.

Lets take a look at the points outlined at the Oracle Website for this part of the certification.

  • Section 1: Declarations, Initialization and Scoping

    1. Develop code that declares classes (including abstract and all forms of nested classes), interfaces, and enums, and includes the appropriate use of package and import statements (including static imports).

    2. Develop code that declares an interface. Develop code that implements or extends one or more interfaces.

    3. Develop code that declares an abstract class. Develop code that extends an abstract class.

    4. Develop code that declares, initializes, and uses primitives, arrays, enums, and objects as static, instance, and local variables. Also, use legal identifiers for variable names.

    5. Given a code example, determine if a method is correctly overriding or overloading another method, and identify legal return values (including covariant returns), for the method.

    6. Given a set of classes and superclasses, develop constructors for one or more of the classes. Given a class declaration, determine if a default constructor will be created, and if so, determine the behavior of that constructor. Given a nested or non-nested class listing, write code to instantiate the class.

Access Modifiers

The table below shows the types of access available in Java for our top-level classes.

Access modifier Description
publicA top-level class may be declared with the public access modifier, and if it is the class is accessible to all other classes everywhere.
no modifier
package-private / (the default)
If a top-level class has no explicit access modifier, which is the default and is also known as package-private, it is accessible only within its own package.
  • The only access modifier that can be used with a top-level class is public.
  • Only one class can be marked as public per source file.
  • If a class within a source file is marked as public then the name of the source file must exactly match the name of the public class (followed by the .java extension).
  • A source file can include multiple non-public classes.
  • If a source file contains no public class then there is no naming constraints on that source file, ie. it doesn't have to match the name of one of the non-public classes.
  • Aside from access modifiers classes can also be marked with the non-access modifiers abstract, final and strictfp. The strictfp is not part of the certification and so we won't go into details. When a class is marked as abstract it has to be subclassed; when a class is marked as final it can't be subclassed, so these two modifers can never be used together.
  • A class can extend a maximum of one other class.


/*
  Some code showing class rules
*/
class A { }                        // OK
private class A { }                // No, can only use public access modifier with top level class
protected class A { }              // No, can only use public access modifier with top level class
public class A { }                 // OK
public class B extends A { }       // OK
public class C extends B, A { }    // No, can only extend one class
abstract class D { }               // OK
final class E { }                  // OK
abstract final class F { }         // No, cannot use both abstract and final

PackagesTop

In Java we can keep libraries of related classes together using a package and this is in essence what the Java language is, a collection of packaged libraries.

  • If a class is part of a package then the package statement must be the first line of code in a source file.

There are two major benefits to the package approach adopted by Java.

  • A package provides the apparatus for us to group related classes together under the same umbrella.
    1. We need a way to uniquely identify classes and Java doesn't allow us to have two top-level classes with the same name, within the same namespace. By using packaging we can partition the namespace to alleviate naming conflicts.
    2. Within any reasonable sized system we will have classes that relate to different aspects of said system, such as the Model View Controller paradigm. Packaging allows us to separate concerns into areas such as a Model subpackage, a View subpackage and so on. This makes the whole development process easier and more manageable.
  • A package is part of the Java mechanism we use to enforce Encapsulation.
    1. By not marking members within a package with an access modifier, we are saying that these members are package-private and can only be accessed from within this package.
    2. By marking members with the protected access modifier, we are saying that these members can only be accessed from within this package or from a subclass outside the package.

The following table shows usage of a single package statement and an example of a multiple hierarchy package statement.

Package Form Example Description
Single package
package pkg;package A;This file is part of package A.
Multiple package hierarchy
package pkg.subPkg1.subPkg2...subPkgN;package A.B.C;This file is part of Package C, which is a subpackage of B, which is a subpackage of A.

ImportsTop

Java allows us to import parts of a package, or even the whole package if required for use in our code and we do this using the import keyword.

  • If a class uses the import keyword to import parts or all of a package, then the import keyword must follow the package statement if there is one, or must be the first line of code in a source file if there is no package statement.

The following table shows how to import a single class from a package and all classes from a package using the import statement.

Import Form Example Description
Single class import
import pkg.class;import java.rmi.Remote;Import the Remote class from java.rmi
Multiple class import
import pkg.subPkg1.subPkg2...subPkgN;import java.rmi.*;Import all java.rmi classes

Static Imports

With the introduction of java a new feature became available when using the import statement which is commonly known as static imports. When using the import keyword followed by static we can import all the static members of a class or interface.

The following table shows how to import a single static member from a package and all static members from a package using the import static statement.

Import Static Form Example Description
Single static member import
import static pkg.staticMember;import static java.lang.Math.acos;Import the acos static member from java.lang.Math
Multiple static member import
import static pkg.allStaticMembers;import static java.lang.Math.*;Import all java.lang.Math static members

Interface DeclarationTop

In the first part of this lesson we look at interfaces and the contracts we provide when using them. We create an interface using the interface keyword, instead of class in the definition. All interface methods are implicitly declared as public and abstract so there is no need to code these modifiers when creating the interface. Interface methods have no body and end in a semicolon. In fact you can think of an interface as a pure abstract class, which we will talk about below, because every method must be abstract. Lets start with some rules for declaring interfaces:

  • We must adhere to the contract specified in the interface when using it by providing concrete implementations of all methods within the interface.
  • Interface implementations must adhere to the rules for overrides which are discussed in the 1: Declarations, Initialization and Scoping lesson.
  • We can use an abstract class to implement an interface and by doing this defer the contract implementation of the interface to the first concrete subclass of the abstract class.
  • An interface can extend one or more other interfaces, it does not implement them.
  • A class can implement one or more interfaces.
  • A class can extend another class and implement one or more interfaces, but the extend keyword must come first.



/*
  Some code showing interface rules
*/
interface A { }                        // OK
interface B { }                        // OK
interface C { }                        // OK
class D { }                            
class E { }                            
abstract class F { }                   
interface B implements A { }           // No, an interface can't implement another interface
interface B extends A { }              // OK, an interface can extend another interface
interface B implements D { }           // No, an interface can't implement a class
interface B extends C, A { }           // OK, an interface can extend multiple interfaces
class D implements E { }               // No, a class can't implement another class
class D implements A { }               // OK
class D implements A, B { }            // OK, a class can implement one or more interfaces
class E extends D implements A { }     // OK, we can extend a class and implement an interface
class E implements A extends D { }     // No, extend keyword must come first
abstract class F implements A { }      // OK, an abstract class can implement an interface


Abstract ClassesTop

Abstract classes are used when the object in question is too abstract to make a concrete class. We saw an examples of this in the Abstraction lesson when we made the Vehicle and Truck classes abstract and make concrete subclasses such as Car and HGV. Of couse we could have abstracted these subclasses further to actual car and hgv types but that would have over complicated the focus of that lesson. There are a few rules involved when creating abstract classes:

  • Abstract classes can never be instantiated.
  • The whole purpose of an abstract class is to be subclassed, therefore an abstract class can never have a modifier of final.
  • If any method on a class is marked as abstract, then the class must also be marked as abstract.
  • An abstract class can contain abstract and non abstract methods.
  • An abstract class can extend an abstract class.



/*
  Some code showing abstract rules
*/
abstract class A { }           // OK

abstract class B extends A { 
    A a = new A();
}                              // No, you can never instantiate an abstract class

abstract final class C { }     // No, cannot use both abstract and final

class D {
    abstract void methodA(); 
}                              // No, if any method is marked as abstract, the class must be abstract

abstract class E {
    abstract void methodA(); 
}                              // OK

abstract class F {
    abstract void methodA(); 
    void methodB() {} 
}                              // OK, an abstract class can contain abstract and non abstract methods

abstract class G extends F {}  // OK, an abstract class can extend an abstract class


Variables in JavaTop

Java comes with two types of variables to choose from, primitives and reference, both of which can be declared as static variables, instance variables, method parameters and local variables. Java is a strongly typed language and as such cares about the type of the variables we declare. So what does this statement actually mean? Well whenever you declare a variable in Java, you have to give it a type, or the compiler complains when you come to compile your code. You also have to name the variable and there are rules on naming.

type diagram

Naming Rules and Keywords

These rules apply to all variables, as well as classes and methods (collectively known as identifiers)

  • Must start with a letter, the underscore symbol (_) or the dollar sign ($). A name can't start with a number or any other symbol.
  • You can use numbers after the first letter, you just can't start with a number.
  • The following reserved words used for literal values are unavailable for use as identifiers false, null and true.
  • You cannot use keywords recognized by the compiler. See the table below for the keywords you can't use.

Click a link in the table below to show lesson usage for any keyword you're interested in:

java Keywords
abstractassertbooleanbreakbytecasecatchcharclassconst *
continuedefaultdodoubleelseenumextendsfinalfinallyfloat
forgoto *ifimplementsimportinstanceofintinterfacelongnative
newpackageprivateprotectedpublicreturnshortstaticstrictfpsuper
switchsynchronizedthisthrowthrowstransienttryvoidvolatilewhile

Keywords marked with an asterisk (*) are not used.

Although not a rule as such it's also important to know that identifiers are case-sensitive.


Variable Scope

In Java we can declare variables anywhere within a block of code. A block starts with its opening curly brace and ends with its closing curly brace. A block and where it resides defines the type of the variable and the scope of the enclosed data. Therefore each time you start a new block of code you start a new scope. Scope determines the visibility and lifetime of the variables within it. Java comes with three kinds of scope and we name variables according to the scope they reside in as detailed in the table below.

Variable Scope Lifetime
staticStatic variables apply to the class as a whole and are declared within the class but outside a method.Exists for as long as the class it belongs to is loaded in the JVM.
See the Static Members lesson for more information.
instanceInstance variables apply to an instance of the class and are declared within the class but outside a method.Exists for as long as the instance of the class it belongs to.
See the Instance Variables & Scope lesson for more information.
localLocal variables apply to the method they appear in.Exists until the method it is declared in finishes executing.
See the Method Scope lesson for more information.

Access Modifiers

The table below shows the four types of access available in Java for members (variables, inner classes and methods).

Access modifier Description
publicA member may be declared with the public access modifier, and if it is the member is accessible to all other classes everywhere, assuming the class it resides in is accessible.
protectedA member may be declared with the protected access modifier, and if so, is only accessible within its own package and also by a subclass of its class in other packages..

See the Packages lesson for more information on packaging.
See the Inheritance Basics lesson for more information on subclassing.
no modifier
package-private / (the default)
If a member has no explicit access modifier it is only accessible within its own package.
privateA member may be declared with the private access modifier, and if it is the member is only accessible within its own class.

Non-access Modifiers

The table below shows the types of non-access modifiers available for use with variables.

static variable and instance variable modifiers local variable modifiers
final
transient
volatile
final

Primitive VariablesTop

The table below lists the eight primitive types available in java:

Primitive Types
Type Description Bit Width Range
boolean and char
booleantrue/false valuesJVM specifictrue or false
charCharacter160  to  65535 - ('\u0000' to '\uffff' Unicode)
signed numeric integers
byte8-bit integer8-128  to  127
shortShort integer16-32,768  to  32,767
intInteger32-2,147,483,648  to  2,147,483,647
longLong integer64-9,233,372,036,854,775,808  to  9,233,372,036,854,775,807
signed floating point
floatSingle-precision float32varies
doubleDouble-precision float64varies

Reference VariablesTop

Reference variables are concerned with objects and how we access them. The reference variable doesn't hold the object itself but some bits that act as a pointer to an address in memory where the object exists. How the JVM holds this bits isn't important for us as programmers, just the fact that this memory address pointer is used by the JVM to access a unique object. There are three steps involved in object creation:

object creation

So lets go through the three step process above:

  1. Declaration - Here. we declare a reference variable named moggy of type Cat and the JVM allocates space for it.
  2. Creation - Tells the JVM to allocate space on The Heap for a new Cat object.
  3. Assignment - Assign the new Cat object to the reference variable moggy.

ArraysTop

An array in Java is an object that contains a collection of values which can be a collection of primitive data types or a collection of reference variable types.

  • An array of primitives data types is a collection of values that constitute the primitive values themselves.
  • An array of reference variable types is actually a collection of pointer values which point to the memory address where each object is stored on The Heap.

Whichever variable type the array holds, primitive or reference, the array itself is still an object. In Java you can define a one dimensional array which is an object that refers to a collection of values repeated one or more times, or multi dimensional arrays which are a collection of array objects (arrays of arrays). Multi dimensional arrays may contain the same number of elements in each row or column and are known as regular arrays or an uneven number of elements in each row or column which are known as irregular arrays.

Array Creation

Array creation is a three step process as outlined below and can be achieved using separate statements or combined into a single statement.

  1. Array declaration
  2. Array allocation
  3. Array element initialization

Array Notes

As you can see from the table above there is a lot of ways to create arrays in Java. There are several points about arrays shown in the table above that we will highlight again here before we go into some code examples:

  • Array indexes are zero-based.
  • When declaring an array the square brackets can appear after the type, after the array name or in the case of multi dimensional arrays a combination of both.
  • After allocation of an array, each element of the array is initialized with the default for the array type:
    • object - null
    • boolean - false
    • char - /u0000
    • integer types (byte, short, int and long) - 0
    • floating-point types (float, double) - 0.0
  • For multiple statement array creation the new keyword is mandatory.
  • For single statement array creation the size of the array is calculated by the number of values that are assigned to the array and should not be specfied.

EnumsTop

In their simplest form enumerations are just a list of constants that define a new data type. Before java the only way to do this would have been using static final variable to define Java constants. The difference between using enumerations and static final variables to define Java constants, is that with static final variable we can't guarantee that another piece of code won't set an invalid value, instead of using one of our static final variables. With enumerations, objects of the enumerated type can only hold values defined in the list of constants such as months of the year and days of the week for example. Lets look at some code to see this in action:


/*
  Enumeration of soups
*/ 
enum Soup {
    TOMATO, CHICKEN, PRAWN
}

We create an enumeration using the enum keyword. The identifers TOMATO, CHICKEN and PRAWN are known as enumeration constants and are implicitly declared as public, static members of Soup. When we declare enumeration constants it's not obligatory to use all uppercase letters, but it lets others see this is a constant and so we use this convention here.

Overriding MethodsTop

A method override must adhere to the contract it has with the superclass method. This contract being, a method override must have exacly the same arguments and return type (or co-variant thereof) as the superclass method with the same method name. This is different to an overloaded method as discussed below and in the Objects & Classes section, in the Methods lesson, in which the argument lists has to be different. In fact if you change the argument lists, that's what you end up with an overloaded method. So to make sure we are doing a method override we need to keep the contract.

Overriding Method Rules

When we override a superclass method there are rules to adhere to:

  • A method override must have exacly the same arguments as the superclass method with the same method name or you end up with an overloaded method.
  • A method override must have the same return type (or co-variant thereof) as the superclass method with the same method name.
  • When we override a method, the overriding method can't be less accessible, but can be more accessible.
  • You cannot override a method marked with the final modifier.
  • You cannot override a method marked with the private access modifier. Even if you have a method in the subclass with the same method name and arguments as a private method in the superclass it knows nothing of that method as it can't see it and is just a normal non-overriding method
  • You cannot override a method marked with the static modifier as overridden methods pertain to instance methods and not the class. In fact if you use the same static method and parameters in a subclass as a static method in a superclass this is known as method hiding and is discussed in Static Overrides?.
  • An overriding method can throw any Error or RuntimeException exceptions, whether these are declared in the overridden method or not.
  • An overriding method must not throw any new checked exceptions or any checked exceptions that are higher up the inheritance tree than those declared in the overridden method.
  • An overriding method can throw checked exceptions that are lower in the inheritance tree than those declared in the overridden method, or throw fewer or none of the checked exceptions that were declared in the overridden method.


/*
  Some code showing method override rules
*/
import java.io.*; // Import IO exception classes

public class A { 
    void methodA(int i) { }
    final void methodB() {}
    private void methodC() {}
    protected void methodD(String s) {}
    protected void methodE(String s) {}
    void methodF(String s, int i) {}
    int methodG(String s, int i) { return i; }
    int methodH(long l, int i) { return i; }
    public A methodI() { 
        A a = new A();
        return a;
    }
    void methodJ() { }
    void methodK() { }
    void methodL() throws IOException { }
    void methodM() throws IOException { }
    void methodN() throws IOException { }
}


import java.io.*;  // Import IO exception classes

public class B extends A { 
    void methodA(int i) { }                     // OK, valid override
    void methodA(String s, int i) { }           // OK, this is an overloaded method
    final void methodB() {}                     // No, you can't override a method marked as final  
    void methodC() {}                           // OK, knows nothing of private method in superclass
    void methodD(String s) {}                   // No, override can't be less accessible
    public void methodE(String s) {}            // OK, override can be more accessible
    protected void methodF(int i, String s) {}  // OK, this is an overloaded method
    void methodF(String s, int i) { }           // OK, valid override
    int methodG(String s, int i) { return s; }  // No, imcompatible return types
    int methodH(long l, int i) { return i; }    // OK, valid override
    public B methodI() {
        B b = new B();
        return b;
    }                                           // OK, covariant (subtype) returned
    void methodJ() throws RuntimeException { }  // OK, overriding method can throw any Error  
                                                // or RuntimeExceptions, whether these are 
                                                // declared in the overridden method or not.
    void methodK() throws IOException { }       // No, an overriding method must not throw 
                                                // any new checked exceptions than are not 
                                                // declared in the overridden method.
    void methodL() throws Exception { }         // No, overriding method must not throw checked 
                                                // exceptions higher up the inheritance tree 
                                                // than those declared in the overridden method.
    void methodM() throws EOFException { }      // OK, overriding method can throw checked 
                                                // exceptions lower in the inheritance tree 
                                                // than those declared in the overridden method.
    void methodN() { }                          // OK, overriding method can throw fewer  
                                                // or none of the checked exceptions
                                                // that were declared in the overridden method.
}

Overloading MethodsTop

You can use the same method name more than once in a class or subclass and this is known as overloading. When using overloading each method must have different parameter lists so the compiler knows which method to call. Having the same parameter types is fine as long as the order differs.

Overloading Method Rules

When we overload a superclass method or a method in the same class there are rules to adhere to:

  • A method overload must have a different argument list to any like named methods in the same class.
  • A method overload must have a different argument list to any like named methods in a superclass or you end up with a method override and all the rules that apply when using overrides as listed in the section above.
  • A method overload has no constraints on return types.
  • A method overload has no constraints on accessibility.
  • A method overload has no constraints on checked exceptions.


/*
  Some code showing method override rules
*/
public class A { 
    void methodA(int i) { }
    final void methodB() {}
    protected void methodC(String s) {}
    void methodD(String s, int i) {}
    String methodE(String s, int i) { return s; }
    void methodF() { }
}


import java.io.*;  // Import IO exception classes

public class B extends A { 
    void methodA(int i) { }                    // OK, same parameter list as superclass so an override
    void methodA(String s, int i) { }          // OK, this is an overloaded method of superclass
    final void methodB(int i) {}               // OK, parameter list differs from superclass method 
                                               // marked as final, so valid overload  
    void methodC(int i) {}                     // OK, no constraints on subclass overload accessibility
    protected void methodD(int i, String s) {} // OK, this is an overloaded subclass method
    void methodD(String s, int i) { }          // OK, valid override
    int methodE(int i, String s) { return i; } // OK, no constraints on subclass overload return types
    void methodF(int i) throws IOException { } // OK, no constraints on subclass overload
                                               // checked exceptions  
    void methodG() {}                          
    void methodG(String s) {}                  // OK, overloaded in same class
}

ConstructorsTop

Constructors allow us to instantiate our objects via declaration, assignment and creation.

object creation
  1. Declaration - Here. we declare a reference variable named moggy of type Cat and the JVM allocates space for it.
  2. Creation - Tells the JVM to allocate space on The Heap for a new Cat object.
  3. Assignment - Assign the new Cat object to the reference variable moggy.

Access Modifiers

The table below shows the types of access available in Java for constructors.

Access modifier Description
publicA constructor may be declared with the public access modifier, and if it is the constructor is accessible to all other classes everywhere, assuming the class it resides in is accessible.
protectedA constructor may be declared with the protected access modifier, and if so, it is only accessible to the package the implementation is in.

See the Packages lesson for more information on packaging.
no modifier
package-private /
(the default)
If a constructor has no explicit access modifier, it is only accessible to the package the implementation is in.

See the Packages lesson for more information on packaging.
privateA constructor may be declared with the private access modifier, and if it is the constructor can only be constructed from within its own class.

Constructor Checklist


  • A constructor runs when we code the new() operator followed by a class name.
  • Constructors must have the same name as the class and no return type.
  • Constructors are used to initialize the instance variables (object state) of the object instance being constructed.
  • If you don't code a constructor in your class the compiler will put in a default no arguments constructor.
  • If you do code a constructor in your class, the compiler will NOT put in a default no arguments constructor, you will have to code it yourself.
  • We can have more than one constructor in a class and the constructors are then known as overloaded constructors.
  • When using overloaded constructors in a class, each constructor must have different argument lists so the compiler knows which constructor to use to construct our objects. Having the same argument types is fine as long as the order differs.
  • You can refer to any member of the current object from within a non-static method or constructor by using the this() keyword.
  • You can invoke one constructor from another constructor within the same class by calling this() and doing so is known as explicit constructor invocation and is the only way to invoke a constructor.
  • If we decide to use this() it must be the first statement within our constructor or we get a compiler error. This means we can't use this() and super() together.
  • We can use super() to invoke a superclass constructor and if we don't supply this explicitly, then the compiler inserts a no-args super() for us as the first statement in the constructor if we haven't used the this() keyword.
  • When explicitly coding super() we can supply arguments to invoke a constructor in the superclass matching the signature of our call.
  • When explicitly coding super() it must be the first statement within the constructor or we get a compiler error. This means we can't use super() and this() together.
  • When explicitly coding super() only methods and static variables can be used within the call.
  • Interfaces do not have constructors as they are not part of a particular classes inheritance tree.
  • Abstract classes do have constructors, although we can't code them, as they are part of a classes inheritance tree and so are called via super() on concrete subclass instantiation.


/*
  Some code showing constructor usage
*/
public class A { 
    public static void main(String args[]) { 
        A a = new A(); // OK, compiler puts in a default no arguments constructor so we can instantiate
    }
}   

public class B { 
    B() { } // OK, we code our own default no arguments constructor
}                                                

public class C { 
    void C() { } // OK, this is a method with the same name as the class as it has a return type
    public static void main(String args[]) { 
        C c = new C();
    }
}          
                                     
public class D { 
    D() { }
    D(int i) { } // OK, overloaded constructor
    public static void main(String args[]) { 
        D d = new D();
        D d2 = new D(5);
    }
}

public class E { 
    int i;    
    String s;

    E(int i) {
        this(i, "unknown"); // Invoke one constructor from another constructor within the same class
    }
    E(int i, String s) {
        this.i = i;
        this.s = s;
    }
    public static void main(String args[]) { 
        E e = new E(5);
    }
}

/*
  Following code will fail as compiler inserts a no arguments constructor for us which invokes 
  super() and there isn't a no arguments constructor in superclass
*/
public class F extends E { 
}

public class G extends E { 
    G(int i) { // here we invoke existing super constructor so works fine 
        super(i);
    }
    public static void main(String args[]) { 
        G g = new G(5);
    }
}

Nested ClassesTop

A nested class is only known to the enclosing class and shares its scope. This means that non-static nested classes have access to all the members and variables of the outer class. Conversely the outer class knows nothing of the internal working of the nested class. The benefits that all nested classes receive are:

  • When a class has a specific purpose that is only relevant to one other class it makes sense to put the helper class within the class that uses it and we can use a nested class for this purpose.
  • Because nested classes have access to all the outer classes members, including members with the private access modifier, it gives us a way to keep outer class members private while still being able to access them, thus increasing encapsulation.
  • Having nested classes allows us to have inner classes close to the top-level classes that enclose them, making code easier to understand and maintain.

Nested classes can be static, which are known as static member classes, or non-static, which are known as inner classes. The lesson on Nested Classes covers instantiation of all types of nested class so we will just cover the guidelines for each type here:

Static Member Classes

A static member class is associated with its outer class in the same way that static members of the outer class would be. This means that a static member class cannot refer to non-static variables and methods defined within the outer class and can only interact with them through an object reference.

Behaviourally, static member classes act like any other top-level class and essentially are top-level classes that have been nested in another top-level class to facilitate packaging, or are associated with the outer class but it makes no sense to attach them to an instance of that class.

Non-static Member Classes

This type of inner class is a member of the outer class just like instance variables and methods are and as such the same modifiers and rules apply as to amy member. We can instantiate a non-static member class as part of the outer class state or seperately when you don't want all outer instances to have an inner instance.

  • Using non-static member classes is very useful when we require a class that doesn't pass the IS-A test but is intrinsicly associated with its enclosing class.
  • A non-static member class is a member of a class just like any other member and as such can have the same modifers applied in its class declaration: these being abstract, final, private, protected, public, static and strictfp.
    • Of course using the static keyword in the class declaration means we have turned the non-static member class into a static member class and so no longer have access to any instance variables and methods.
  • If the class is required by other classes as well, then the class would be better suited as a standard top-level class instead.

Local Inner Classes

Local inner classes can be declared anywhere a local variable can be declared and have the same Method Scope. If you don't require the local inner class to be attached to an instance of the enclosing class, then the nested class should be declared in a static context. Local inner classes cannot contain static members and for readability the coding should be kept to a minimum.

  • The only valid modifers you can apply to a local inner class declaration are final or abstract.
  • Local inner classes can only be instantiated from within the method they are declared in.
  • When instantiating a local inner class, the instantiation code must come after the local inner class declaration.
  • The local inner class can only use final local variables defined within the method it resides in, outside those defined within itself and the outer instance.
  • When creating local inner classes and the code is quite robust, or the code needs to be accessible from more than one method, it is better to make a non-static member class.

Anonymous Inner Classes

The final type of inner classes we can use are anonymous inner classes which are different syntactically from anything else in Java and come with a lot of constraints:

  • Anonymous inner classes as the terminology implies have no name.
  • You can't execute the instanceof test against anonymous inner classes or any process that requires the name of the class.
  • Anonymous inner classes are not members of their enclosing class; in fact they are both declared and instantiated at the point of use.
  • Anonymous inner classes cannot contain any static members
  • Anonymous inner classes can be coded anywhere where an expression is legal, so keep the code to a minimum to maintain readability.
  • Anonymous inner classes can't be declared to extend a class and implement an interface
  • Anonymous inner classes can't implement multiple interfaces.
  • Anonymous inner classes can only invoke members inherited from the supertype

Related java Tutorials

Beginning Java - Primitive Variables
Beginning Java - Method Scope
Objects & Classes - Arrays
Objects & Classes - Class Structure and Syntax
Objects & Classes - Reference Variables
Objects & Classes - Reference Variables - The new Operator
Objects & Classes - Methods - Overloaded Methods
Objects & Classes - Methods - Overloaded varargs Ambiguities
Objects & Classes - Instance Variables & Scope
Objects & Classes - Constructors
Objects & Classes - Enumerations
OO Concepts - Abstraction - Abstract Classes
OO Concepts - Inheritance - Overriding Methods
OO Concepts - Inheritance Concepts - Accessing Superclass Overrides
Inheritance Concepts -Superclass Constructors
OO Concepts - Interfaces
OO Concepts - Nested Classes
Flow Control - Methods - Overridden Methods & Exceptions
API Contents - Packages
API Contents - Packages - Imports
API Contents - Packages - Static Imports

go to home page Homepage go to top of page Top