Packages and Inheritance in Java with Examples

package in java is used to group class and interfaces. This helps developer to avoid conflict when there are huge numbers of classes. If we use this package the classes we can create a class/interface with same name in different packages. By using packages we can import the piece of again in another class. There many built in packages in java like > 1.java.util > 2.java.lang > 3.java.io We can define our own user defined packages.

Using Packages to create classes with the same name

First Test.class:

package foo.bar
public class Test {
}

Also Test.class in another package

package foo.bar.baz
public class Test {
}

The above is fine because the two classes exist in different packages.

Using Package Protected Scope

In Java if you don’t provide an access modifier the default scope for variables is package-protected level. This means that classes can access the variables of other classes within the same package as if those variables were publicly available.

package foo.bar

public class ExampleClass {
    double exampleNumber;
    String exampleString;

    public ExampleClass() {
        exampleNumber = 3;
        exampleString = "Test String";
    }
    //No getters or setters
}
package foo.bar

public class AnotherClass {
     ExampleClass clazz = new ExampleClass();

     System.out.println("Example Number: " + clazz.exampleNumber);
     //Prints Example Number: 3
     System.out.println("Example String: " + clazz.exampleNumber);
//Prints Example String: Test String
}

This method will not work for a class in another package:

package baz.foo

public class ThisShouldNotWork {
      ExampleClass clazz = new ExampleClass();
      System.out.println("Example Number: " + clazz.exampleNumber);
      //Throws an exception
      System.out.println("Example String: " + clazz.exampleString);
      //Throws an exception
}

Inheritance

Inheritance is a basic object oriented feature in which one class acquires and extends upon the properties of another class, using the keyword extends. For Interfaces and the keyword implements, see interfaces.

Related Article: Programming to an interface in Java

With the use of the extends keyword among classes, all the properties of the superclass (also known as the Parent Class or Base Class) are present in the subclass (also known as the Child Class or Derived Class)

public class BaseClass {

      public void baseMethod(){
           System.out.println("Doing base class stuff");
      }
}

public class SubClass extends BaseClass {

}

Instances of SubClass have inherited the method baseMethod():

SubClass s = new SubClass();
s.baseMethod(); //Valid, prints "Doing base class stuff"

Additional content can be added to a subclass. Doing so allows for additional functionality in the subclass without any change to the base class or any other subclasses from that same base class:

public class Subclass2 extends BaseClass {

     public void anotherMethod() {
            System.out.println("Doing subclass2 stuff");
     }
}

Subclass2 s2 = new Subclass2();
s2.baseMethod(); //Still valid , prints "Doing base class stuff"
s2.anotherMethod(); //Also valid, prints "Doing subclass2 stuff"

Fields are also inherited:

public class BaseClassWithField {
     public int x;
}
public class SubClassWithField extends BaseClassWithField {
     public SubClassWithField(int x) {
           this.x = x; //Can access fields
     }
}

private fields and methods still exist within the subclass, but are not accessible:

public class BaseClassWithPrivateField {

     private int x = 5;

     public int getX() {
          return x;
     }
}

public class SubClassInheritsPrivateField extends BaseClassWithPrivateField {
 
     public void printX() {
          System.out.println(x); //Illegal, can't access private field x
         System.out.println(getX()); //Legal, prints 5
     }
}
SubClassInheritsPrivateField s = new SubClassInheritsPrivateField();
int x = s.getX(); //x will have a value of 5.

In Java, each class may extend at most one other class.

public class A{}
public class B{}
public class ExtendsTwoClasses extends A, B {} //Illegal

This is known as multiple inheritance, and while it is legal in some languages, Java does not permit it with classes. As a result of this, every class has an unbranching ancestral chain of classes leading to Object, from which all classes descend.

Abstract Classes

An abstract class is a class marked with the abstract keyword. It, contrary to non-abstract class, may contain abstract – implementation-less – methods. It is, however, valid to create an abstract class without abstract methods.

An abstract class cannot be instantiated. It can be sub-classed (extended) as long as the sub-class is either also abstract, or implements all methods marked as abstract by super classes.

An example of an abstract class:

public abstract class Component {
    private int x, y;
    public setPosition(int x, int y) {
         this.x = x;
         this.y = y;
    }
    
    public abstract void render();
}

The class must be marked abstract, when it has at least one abstract method. An abstract method is a method that has no implementation. Other methods can be declared within an abstract class that have implementation in order to provide common code for any sub-classes.

Attempting to instantiate this class will provide a compile error:

//error: Component is abstract; cannot be instantiated
Component myComponent = new Component();

However a class that extends Component, and provides an implementation for all of its abstract methods and can be instantiated.

public class Button extends Component {

       @Override
       public void render() {
           //render a button
       }
}

public class TextBox extends Component {

      @Override
      public void render() {
           //render a textbox
      }
}

Instances of inheriting classes also can be cast as the parent class (normal inheritance) and they provide a polymorphic effect when the abstract method is called.

Component myButton = new Button();
Component myTextBox = new TextBox();

myButton.render(); //renders a button
myTextBox.render(); //renders a text box

Abstract classes vs Interfaces

Abstract classes and interfaces both provide a way to define method signatures while requiring the extending/implementing class to provide the implementation.

There are two key differences between abstract classes and interfaces:

  • A class may only extend a single class, but may implement many interfaces.
  • An abstract class can contain instance (non-static) fields, but interfaces may only contain static fields.

Version < Java SE 8

Methods declared in interfaces could not contain implementations, so abstract classes were used when it was useful to provide additional methods which implementations called the abstract methods.

Version ≥ Java SE 8

Java 8 allows interfaces to contain default methods, usually implemented using the other methods of the interface, making interfaces and abstract classes equally powerful in this regard.

Anonymous subclasses of Abstract Classes

As a convenience java allows for instantiation of anonymous instances of subclasses of abstract classes, which provide implementations for the abstract methods upon creating the new object. Using the above example this could look like this:

Component myAnonymousComponent = new Component() {
     @Override
     public void render() {
             // render a quick 1-time use component
     }
}

Using ‘final’ to restrict inheritance and overriding

Final classes

When used in a class declaration, the final modifier prevents other classes from being declared that extend the class. A final class is a “leaf” class in the inheritance class hierarchy.

// This declares a final class
final class MyFinalClass {
      /* some code / 
} 

// Compilation error: cannot inherit from final MyFinalClass class MySubClass extends MyFinalClass { 
     / more code */
}

Use-cases for final classes

Final classes can be combined with a private constructor to control or prevent the instantiation of a class. This can be used to create a so-called “utility class” that only defines static members; i.e. constants and static methods.

public final class UtilityClass {
      // Private constructor to replace the default visible constructor
      private UtilityClass() {}

      // Static members can still be used as usual
      public static int doSomethingCool() {
            return 123;
      }
}

Immutable classes should also be declared as final. (An immutable class is one whose instances cannot be changed after they have been created; see the Immutable Objects topic. ) By doing this, you make it impossible to
create a mutable subclass of an immutable class. That would violate the Liskov Substitution Principle which requires that a subtype should obey the “behavioral contract” of its supertypes.

From a practical perspective, declaring an immutable class to be final makes it easier to reason about program behavior. It also addresses security concerns in the scenario where untrusted code is executed in a security
sandbox. (For instance, since String is declared as final, a trusted class does not need to worry that it might be tricked into accepting mutable subclass, which the untrusted caller could then surreptitiously change.)

One disadvantage of final classes is that they do not work with some mocking frameworks such as Mockito.
Update: Mockito version 2 now support mocking of final classes.

Final methods

The final modifier can also be applied to methods to prevent them being overridden in sub-classes:

public class MyClassWithFinalMethod {

       public final void someMethod() {
       }
}

public class MySubClass extends MyClassWithFinalMethod {

      @Override
      public void someMethod() { // Compiler error (overridden method is final)
      }
}

Final methods are typically used when you want to restrict what a subclass can change in a class without forbidding subclasses entirely.

The final modifier can also be applied to variables, but the meaning of final for variables is unrelated to inheritance.

Leave a Comment