Back to the main page
Methods called from constructors
Methods called from constructors should be made final or private to prevent them being overridden. Methods overridden in subclasses can be called prior to the subclass itself being fully loaded.
class Superclass {
static {
System.out.println("1");
}
{
System.out.println("3");
}
Superclass() {
System.out.println("4");
initialise();
}
void initialise() {
}
}
class Subclass extends Superclass {
static char INITIAL_VALUE_A = 'a';
final char INITIAL_VALUE_B = 'b';
static final char INITIAL_VALUE_C;
char a, b, c;
static {
System.out.println("2");
INITIAL_VALUE_C = 'c';
}
{
System.out.println("5");
}
void initialise() {
a = INITIAL_VALUE_A;
b = INITIAL_VALUE_B;
c = INITIAL_VALUE_C;
}
}
public class ConstructorMethods {
public static void main(String[] args) {
Subclass s = new Subclass();
System.out.println(s.a);
System.out.println(s.b);
System.out.println(s.c);
}
}
The output from running the code above shows that neither a, b nor c has been set correctly because INITIAL_VALUE_A, INITIAL_VALUE_B nor INITIAL_VALUE_C had been set prior to the initialise method running.
> java ConstructorMethods
1
2
3
4
5
>
Interfaces
Since Java 8, interfaces can include default and static method implementations, providing java with a certain level of multiple inheritance.
Interfaces are implicitly public and do not need to be declared as such. Similarly all methods are implicitly public and constants implicitly public static.
interface MyInterface<C> {
String MY_STRING = "my string";
void myAbstractMethod();
default void myDefaultMethod() {
// ...
}
static void myStaticMethod() {
// ...
}
}
Variable Hiding
Subclasses can declare variables which hide superclass variables of the same name and type. The superclass variables may still be accessed, possibly accidentally, if the calling object reference is of a type matching the superclass.
class Superclass {
int var = 1;
}
class Subclass extends Superclass {
int var = 2;
}
public class HidingVariables {
public static void main(String[] args) {
Subclass subclass = new Subclass();
Superclass superclass = subclass;
// The following outputs 2,1
System.out.println(subclass.var + "," + superclass.var);
}
}
Inner class variable and method visibility
Inner classes can see the containing class's public and private variables. Likewise the containing class can see the inner class's public and private variables.
class VariableVisibility {
public short publicShort;
private int privateInt;
class Inner {
public int publicInt;
private int privateInt;
void print() {
System.out.print(publicInt + ", " + privateInt + ", ");
System.out.println(publicShort + ", " +
VariableVisibility.this.privateInt);
}
}
public static void main(String[] args) {
VariableVisibility v = new VariableVisibility();
v.publicShort = 3;
v.privateInt = 4;
Inner i = v.new Inner();
i.publicInt = 1;
i.privateInt = 2;
// below outputs 1, 2, 3, 4
i.print();
}
}
Static nested classes can call the containing class's static methods and vice versa.
class OuterClass {
static class StaticNestedClass {
int i;
void nestedPrint() {
staticOuterPrint(i);
}
static void staticNestedPrint() {
System.out.println("2");
}
}
static void staticOuterPrint(int i) {
System.out.println(i);
}
public static void main(String[] args) {
StaticNestedClass staticNested = new OuterClass.StaticNestedClass();
staticNested.i = 1;
// below outputs 1
staticNested.nestedPrint();
// below outputs 2
OuterClass.StaticNestedClass.staticNestedPrint();
}
}
Inner classes declared inside methods
Inner classes declared inside methods are known as local inner classes.
Static members and variables are not allowed inside local inner classes except for static final variables. Since Java 8, this also includes effectively final static variables, e.g. those that get assigned once but never changed. Interfaces are inherently static and so cannot be declared either.
class OuterClass2 {
void myMethod() {
class LocalInnerClass {
static final int MY_INT = 5;
static int MY_INT2 = 5;
// gives compilation error: Illegal static declaration in inner class LocalInnerClass
interface myInterface {}
// gives compilation error: interface not allowed here
}
}
}
Qualified superclass constructor invocation
Below is an example of an qualified superclass constructor invocation. It allows an inner class's subclass's constructor to explicitly specify the newly created object's enclosing instance with respect to the direct superclass.
(expression).super(); must be the first line of the constructor.
Using this technique allows us to create instances of inner classes directly. We could also mix this with a singleton pattern for the container class such that all instances of the inner class shared the same containing class instance.
class A {
A() {
System.out.println("A");
}
class B {
B() {
System.out.println("B");
}
}
}
class C extends A.B {
C(A a, float f) {
// a qualified superclass constructor invocation.
a.super();
// alternatively, the line below could work instead
// new A().super();
System.out.println("C");
}
}
class D extends A {
D(A a) {
// below fails to compile because D doesn't extend an inner class
// a.super();
System.out.println("D");
}
}
public class QualifiedSuperclassConstructor {
public static void main(String str[]) {
new C(new A(), 5.0f);
System.out.println("-");
new D(new A());
}
}
Output from running the above code.
> java QualifiedSuperclassConstructor
A
B
C
-
A
A
D
>