A comprehensive understanding of inner classes in Java programming

  • 2020-04-01 04:13:39
  • OfStack

Java inner classes and their instantiation
In Java, it is allowed to define another Class within a Class (or method, or block of statements), called the Inner Class, or sometimes Nested Class.

There is a logical ownership relationship between the inner class and the outer class that encapsulates it. Generally, it is only used in the class or statement block that defines it. Some functional logic without general meaning is implemented.

The main reasons for using inner classes are:
Internal classes can access data in external classes, including private data.
Inner classes can be hidden from other classes in the same package.
Using anonymous inner classes is handy when you want to define a callback function and you don't want to write a lot of code.
Reduces class name conflicts.

Here's an example:


public class Outer {
  private int size;
  public class Inner {
    private int counter = 10;
    public void doStuff() {
      size++;
    }
  }
  public static void main(String args[]) {
    Outer outer = new Outer();
    Inner inner = outer.new Inner();
    inner.doStuff();
    System.out.println(outer.size);
    System.out.println(inner.counter);
    //Compilation error. The external class cannot access the variables of the inner class
    System.out.println(counter);
  }
}

This code defines an Outer class called Outer, which contains an Inner class called Inner. Comment out the error statement, compile, and two.class files are generated: Outer. Class and Outer$Inner. Class. That is, inner classes are compiled into separate bytecode files.

Inner classes are a compiler phenomenon, independent of the virtual machine. The compiler translates the inner class into a regular class file with a $mark separating the outer class name from the inner class name, which the virtual machine knows nothing about.

Note: you must have an object of an external class before you can generate an object of an internal class, because the internal class needs to access the member variables in the external class, and the member variables must be instantiated to make sense.

Inner classes are a new feature in Java 1.1 that some programmers see as a laudable improvement, but the syntax of inner classes is complex, seriously undermining good code structure and violating the design philosophy that Java is simpler than C++.

Inner classes seem to have added some nice, interesting, unnecessary features, and are Java starting to go down the path of destruction that so many languages suffer from? This tutorial is not intended to give a "yes" answer to this question.

Java static inner classes, anonymous inner classes, member inner classes, and local inner classes
Inner classes can be static, using public, protected, and private access controls, while outer classes can only use public, or default.
Member inner class

A class that is defined directly inside an outer class (not inside a method or a code block) is a member inner class that can directly use all the variables and methods of an outer class, even if they are private. An external class that wants to access the member variables and methods of an internal class needs to get them through the object of the inner class.

Look at the following code:


public class Outer{
  private int size;
  public class Inner {
    public void dostuff() {
      size++;
    }
  }
  public void testTheInner() {
    Inner in = new Inner();
    in.dostuff();
  }
}

A member inner class is like a normal member of an outer class.

A member inner class can use various modifiers, including public, protected, private, static, final, and abstract, or not.

If there is a static modifier, it is at the class level, otherwise at the object level. The class level can be accessed directly from an external class, and the object level needs to be an external object before it can be accessed.

You cannot declare any static members in a non-static inner class.

Inner classes can call each other, for example:


class A {
  //B, C can call each other
  class B {}
  class C {}
}


Member access to inner classes

An object of an inner class records references to the outer class object on which it depends as a member variable, so that the outer class object can be found and its members accessed. The member variable is automatically added to the non-static inner class with the name convention "outclassname.this".

1) when using the non-static variables and methods defined in the inner class, first create the object of the outer class, then create the object of the inner class by the "outobjectname.new" operator, and then call the method of the inner class, as shown below:


public class Demo{
  public static void main(String[] args) {
    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();
    inner.dostuff();
  }
}
class Outer{
  private int size;
  class Inner{
    public void dostuff() {
      size++;
    }
  }
}

2) the static internal class is equivalent to the static member of its external class. There is no dependency relationship between its object and the external class object, so it can be created directly. Here's an example:


public class Demo{
  public static void main(String[] args) {
    Outer.Inner inner = new Outer.Inner();
    inner.dostuff();
  }
}
class Outer{
  private static int size;
  static class Inner {
    public void dostuff() {
      size++;
      System.out.println("size=" + size);
    }
  }
}

Operation results:


size=1

3) because an inner class can directly access the components of its outer class, it will also cause a naming conflict when there are attributes or methods with the same name in the inner class and its outer class. Therefore, when making multi-layer calls, it should be specified as follows:


public class Outer{
  private int size;
  public class Inner{
    private int size;
    public void dostuff(int size){
      size++; //Local variable size;
      this.size; //Size of inner class
      Outer.this.size++; //Size of the external class
    }
  }
}

Local inner class

A Local inner class is a class defined in a block of code. They are only visible in the block of code that defines them.

Local classes have several important features:

They are only visible in the code block where they are defined; You can use any local final variable in the block of code that defines them; A local class cannot be static, and a static member cannot be defined inside. Local classes can not be decorated with public, private, protected, only the default;

A local class can be abstract.

Look at the following code:


public class Outer {
  public static final int TOTAL_NUMBER = 5;
  public int id = 123;
  public void func() {
    final int age = 15;
    String str = "http://www.weixueyuan.net";
    class Inner {
      public void innerTest() {
        System.out.println(TOTAL_NUMBER);
        System.out.println(id);
        //System. The out. Println (STR); Invalid, only the final variables of local methods can be accessed
        System.out.println(age);
      }
    }
    new Inner().innerTest();
  }
  public static void main(String[] args) {
    Outer outer = new Outer();
    outer.func();
  }
}

Operation results:


5
123
15


Anonymous inner class

An anonymous inner class is a special form of a local inner class, in which there is no variable name pointing to an instance of the class, and the actual class implementation is written in the inner class.

Note: anonymous classes must inherit from a parent or implement an interface.

Do not use anonymous inner classes to implement abstract methods:


abstract class Person {
  public abstract void eat();
}
class Child extends Person {
  public void eat() {
    System.out.println("eat something");
  }
}
public class Demo {
  public static void main(String[] args) {
    Person p = new Child();
    p.eat();
  }
}

Operation results:


eat something

As you can see, we inherited the Person class with Child, and then implemented an instance of the Child, transforming it up to a reference to the Person class. However, if the Child class here is used only once, wouldn't it be troublesome to write it as a separate class?

This is where anonymous inner classes are introduced. Using anonymous inner classes:


abstract class Person {
  public abstract void eat();
}
public class Demo {
  public static void main(String[] args){
    
    //Inherit the Person class
    new Person() {
      public void eat() {
        System.out.println("eat something");
      }
    }.eat();
  }
}


As you can see, the anonymous class inherits the Person class and implements the methods of the abstract class in braces.

Since the syntax of inner classes is complex and rarely used in actual development, this tutorial is not intended to go into depth, and you should not make inner classes the focus of your Java learning.


Related articles: