Java internal class _ Power node Java College collation

  • 2020-07-21 07:57:51
  • OfStack

An inner class is a definition of a second class within an outer class. The class name does not need to be the same as the folder. Inner classes can be static static or decorated with public, default, protected, and private. (The external top-level class that has the same class name and file name can only use public and default).

Note: Inner classes are a compile-time concept, and once they are compiled successfully, they become two completely different classes. For one external class named outer and its internally defined inner class named inner. After compilation, the outer. class and outer$inner. class categories appear. So the member variable/method name of the inner class can be the same as that of the outer class.

1. Member inner class

A member inner class, as a member of an external class, can directly use all the members and methods of the external class, even private's. Meanwhile, the external class needs to access all member variables/methods of the inner class through the object of the inner class.

Note that a member inner class cannot contain the variables and methods of static. Because a member inner class needs to create an external class before it can create its own, this is one more thing to understand, and I'm skipping over the details here.

outer.this is used to represent an external class object when a member inner class wants to refer to it.

You need to create an inner class object that you can use outer.inner  obj = outerobj.new inner();


public class Outer { 
  public static void main(String[] args) { 
    Outer outer = new Outer(); 
    Outer.Inner inner = outer.new Inner(); 
    inner.print("Outer.new"); 
    inner = outer.getInner(); 
    inner.print("Outer.get"); 
  } 
  //  Personal recommendation getxxx() To get the member inner class, especially if the constructor for the inner class has no arguments  
  public Inner getInner() { 
    return new Inner(); 
  } 
  public class Inner { 
    public void print(String str) { 
      System.out.println(str); 
    } 
  } 
} 

2. Local inner classes

Local inner classes are defined within methods and scopes. Thinking in Java gives two examples:

Defined within a method:


public class Parcel4 { 
  public Destination destination(String s) { 
    class PDestination implements Destination { 
      private String label; 
      private PDestination(String whereTo) { 
        label = whereTo; 
      } 
      public String readLabel() { 
        return label; 
      } 
    } 
    return new PDestination(s); 
  } 
  public static void main(String[] args) { 
    Parcel4 p = new Parcel4(); 
    Destination d = p.destination("Tasmania"); 
  } 
} 

Definition in scope:


public class Parcel5 { 
  private void internalTracking(boolean b) { 
    if (b) { 
      class TrackingSlip { 
        private String id; 
        TrackingSlip(String s) { 
          id = s; 
        } 
        String getSlip() { 
          return id; 
        } 
      } 
      TrackingSlip ts = new TrackingSlip("slip"); 
      String s = ts.getSlip(); 
    } 
  } 
  public void track() { 
    internalTracking(true); 
  } 
  public static void main(String[] args) { 
    Parcel5 p = new Parcel5(); 
    p.track(); 
  } 
} 

Local inner classes are compiled just like other classes 1, but with different scopes. They can only be used within the scope of the method or condition and cannot be referenced after exiting these scopes.

3. Nested inner classes

Nested inner classes are inner classes decorated with static. The inner class declared as static does not require the connection between the inner class object and the outer class object, which means that we can refer to outer.inner directly, neither creating the outer class nor creating the inner class.
There is one more difference between nested classes and regular inner classes: regular inner classes cannot have static data and static attributes, nor can they contain nested classes, but nested classes can. While nested classes cannot be declared as private, they are generally declared as public for easy invocation.

4. Anonymous inner classes

Sometimes I prefer to use an anonymous inner class instead of naming it because it has no name. Such as:


((Button) findViewById(R.id.start)).setOnClickListener(new Button.OnClickListener() { 
  @Override 
  public void onClick(View v) { 
    new Thread() { 
      @Override 
      public void run() { 
        // TODO Auto-generated method stub 
      } 
    }.start(); 
  } 
}); 

Anonymous inner classes cannot have access modifiers. Note that the new anonymous class is defined first. See the following example:


public class Outer { 
  public static void main(String[] args) { 
    Outer outer = new Outer(); 
    Inner inner = outer.getInner("Inner", "gz"); 
    System.out.println(inner.getName()); 
  } 
  public Inner getInner(final String name, String city) { 
    return new Inner() { 
      private String nameStr = name; 
      public String getName() { 
        return nameStr; 
      } 
    }; 
  } 
} 
// After the comment, the class is prompted at compile time Inner Can't find  
/* interface Inner { 
  String getName(); 
} */ 

Also in this example, note that the method parameter of the external class must be final when the method parameter needs to be used within the inner class. Here you can see that the formal parameter name is defined as final, while the formal parameter city is not defined as final if it is not used. Why is it defined as final? Find my own explanation on the Internet:

"This is a compiler design issue, which is easy to understand if you know how java works.

First, when the inner class is compiled, a separate.class file for the inner class is generated. This file is not in the same 1class file as the outer class.
When parameters passed by an external class are called by an internal class, they are called directly from the point of view of the java program, for example:


public void dosome(final String a,final int b){ 
 class Dosome{public void dosome(){System.out.println(a+b)}}; 
 Dosome some=new Dosome(); 
 some.dosome(); 
} 

The code looks like the a and b arguments that the inner class calls directly, but they are not, and the actual operation code is after the java compiler is compiled


class Outer$Dosome{ 
 public Dosome(final String a,final int b){ 
 this.Dosome$a=a; 
 this.Dosome$b=b; 
} 
 public void dosome(){ 
 System.out.println(this.Dosome$a+this.Dosome$b); 
} 
}} 

From the above code point of view, the inner class does not call the parameters passed in the method directly, but the inner class backs up the parameters passed in through its own constructor, and the inner method calls its own properties instead of the parameters of the outer class method.
Such understanding why it is easy to draw with final, because both from look is with a thing, in fact is not the case, if the inner class change the values of these parameters is not likely to affect the original parameters, but this is the consistency of the lost parameters, because they are from the point of view of a programmer with one thing, if the programmer at the time of program design, change the value of the parameter values, but actually called outside and found the value has not been changed, that would make people are very difficult to understand and accept, in order to avoid the embarrassment of problem, So the compiler designers set the parameters that the inner class can use to be final to get around this unintelligible error.

(final is used to make the reference unchangeable in order to avoid any change of the reference value, such as being modified by the method of the external class.)

Because the anonymous inner class, nameless, USES the default constructor, takes no arguments, what if you need arguments? The constructor with parameters of the class is required:


public class Outer { 
  public static void main(String[] args) { 
    Outer outer = new Outer(); 
    Inner inner = outer.getInner("Inner", "gz"); 
    System.out.println(inner.getName()); 
  } 
  public Inner getInner(final String name, String city) { 
    return new Inner(name, city) { 
      private String nameStr = name; 
      public String getName() { 
        return nameStr; 
      } 
    }; 
  } 
} 
abstract class Inner { 
  Inner(String name, String city) { 
    System.out.println(city); 
  } 
  abstract String getName(); 
} 

Note that the formal parameter, city, does not need to be defined as final because it is not used directly by the anonymous inner class, but by the constructor of the abstract class Inner.

Anonymous inner classes can be instantiated to achieve a constructor like effect:


public class Outer { 
  public static void main(String[] args) { 
    Outer outer = new Outer(); 
    Inner inner = outer.getInner("Inner", "gz"); 
    System.out.println(inner.getName()); 
    System.out.println(inner.getProvince()); 
  } 
  public Inner getInner(final String name, final String city) { 
    return new Inner() { 
      private String nameStr = name; 
      private String province; 
      //  Instance initialization  
      { 
        if (city.equals("gz")) { 
          province = "gd"; 
        }else { 
          province = ""; 
        } 
      } 
      public String getName() { 
        return nameStr; 
      } 
      public String getProvince() { 
        return province; 
      } 
    }; 
  } 
} 
interface Inner { 
  String getName(); 
  String getProvince(); 
} 

5. Inheritance of inner classes

The inheritance of inner class means that the inner class is inherited, the common class extents inner class. In this case, the code should be a little special, see the following examples:


public class InheritInner extends WithInner.Inner { 
  // InheritInner()  It doesn't compile, 1 You must add the formal parameter  
  InheritInner(WithInner wi) { 
    wi.super(); 
  } 
  public static void main(String[] args) { 
    WithInner wi = new WithInner(); 
    InheritInner obj = new InheritInner(wi); 
  } 
} 
class WithInner { 
  class Inner { 
  } 
}

You can see that the constructor of the subclass USES the external class object of the superclass. This object needs to be created from the outside and passed to the parameter.


Related articles: