Java Internal classes

Source: Internet
Author: User
Tags class definition date now

This article is the sixth chapter of the Java Core Technology Volume 1 in the interface and internal classes on the internal class reading summary.

The inner class (inner class) in Java is a class that is defined inside another class. So what's the use of internal classes? Here are mainly the reasons for the existence of three internal classes:

    1. An inner class method can access the data in the scope where the class definition resides, including private data. That is, if Class B is defined in Class A, then Class B can access the data in Class A, even private data, but class A cannot access private data in class B;
    2. Inner classes can be hidden from other classes in the same package. In a package, when you define a class, even if you do not add access to the keyword, the class is accessible to other classes within the package, but if it is defined as an inner class, it is equivalent to hiding the other classes within the package;
    3. Using an anonymous (anonymous) inner class is convenient when you want to define a callback function and do not want to write a large amount of code.

In C + + and Java Inner class concepts are similar to nested classes. A nested class is contained within the scope of the perimeter class.

Java's inner class is another feature that makes internal analogy with C + + nested classes more useful. An object of an inner class has an implicit reference that references a perimeter class object that instantiates the inner object. With this pointer, you can access the full state of the perimeter class object.

1 accessing object state using an internal class

The syntax of the inner class is more complex, and a simple example is used to illustrate how the inner class is used. The following code constructs a Talkingclock class, which defines a timeprinter class. Two parameters are required to construct a talkingclock: time interval interval and switch ringtone flag beep:

public class Talkingclock {private int interval;private boolean beep;public talkingclock (int interval,boolean beep) {...} public void Start () {...} public class Timeprinter implements actionlistener{
<span style= "White-space:pre" ></span>//an inner classpublic Void actionperformed (ActionEvent event) {
<span style= "White-space:pre" ></SPAN>..}}
The Timeprinter class here is located inside the Talkingclock class. However, this is not to say that each talkingclock has a Timeprinter instance domain. Also, Timeprinter objects are constructed by methods of the Talkingclock class.

The Timeprinter class is defined as follows:

public class Timeprinter implements Actionlistener{public void Actionperformed (ActionEvent event) {Date now=new date (); System.out.println ("At the tone,the time is" +now), if (beep) toolkit.getdefaulttoolkit (). Beep ();}}

The Timeprinter class here has only one method actionperformed, but this method uses the variable beep of the peripheral class Talkingclock class, without beep the instance field or variable. That is, within the class, it can access its own data domain, or it can access the data fields of the perimeter classes that created it.

How does the inner class use the variables of the outer class? An object in an inner class always has an implicit reference to the outer class object that created it:


This reference is not visible in the definition of an inner class. To illustrate this concept, we can refer to references to external class objects as outer. The Actionperformed method will then be equivalent to the following form:

public class Timeprinter implements Actionlistener{public void Actionperformed (ActionEvent event) {Date now=new date (); System.out.println ("At the tone,the time is" +now), if (outer.beep) Toolkit.getdefaulttoolkit (). Beep ();}}
References to external classes are set in the constructor. The compiler modifies the constructors of all the inner classes, adding a parameter referenced by an external class. Because Timeprinter does not have a constructor defined, the compiler generates a default constructor for this class, with the following code:

Public Timeprinter (Talkingclock clock) {        outer=clock;}
Note, however, that outer is not a Java keyword.

Once the Timeprinter object is created in the Start method, the compiler passes the this reference to the constructor of the current Talkingclock:

ActionListener listener=new Timeprinter (this);

Note that the above code is automatically added by the compiler. The following is a complete definition of the Talkingclock class:

Import Java.awt.*;import java.awt.event.*;import Java.util.date;import Javax.swing.timer;public class TalkingClock { private int Interval;private Boolean beep;public talkingclock (int interval,boolean beep) {this.interval=interval; This.beep=beep;} public void Start () {ActionListener listener=new timeprinter (); Timer t=new timer (interval,listener); T.start ();} public class Timeprinter implements Actionlistener{public void Actionperformed (ActionEvent event) {Date now=new date (); System.out.println ("At the tone,the time is" +now), if (beep) toolkit.getdefaulttoolkit (). Beep ();}}}
Run the code with the following results:


2 Special syntax rules for inner classes

Above, the inner class has an implicit reference outer that has an outer class. In fact, it is more complicated to use the formal syntax referenced by an external class. The following expression:

Outerclasss.this

Represents a reference to an external class. For example, you can write the Actionperformed method for the Timeprinter inner class as follows:

public void actionperformed (ActionEvent event) {        ...        if (TalkingClock.this.beep) Toolkit.getdefaulttoolkit (). Beep ();}
Conversely, you can use the following syntax format to write more explicitly the constructor of an inner class object:

Outerobject.new innerclass (construction parameters);
Like what:

ActionListener listener=this.new Timeprinter ();

Here, the external class reference of the newly constructed Timeprinter object is set to the this reference in the method that creates the inner class object. This is in fact superfluous.

Within an external class, you can also refer to an inner class like this:

Outerclass.innerclass

3 How the compiler handles internal classes

The inner class is a compiler phenomenon that is independent of the virtual machine. The compiler translates the inner class into a regular class file that separates the external class name from the internal class name, and the virtual machine does not know.

In the example above, we can see the. class file under the compiled Bin folder. For the above project, there are two. class files:

Talkingclock.class and Talkingclock$timeprinter.class

Indicates that the compiler will use an internal class as a regular class file. So what's so special about this class?

You can use JAVAP to decompile the. class file to see the specific information for this class, enter the command Javap-private Talkingclock$timeprinter, and the results are as follows:


As can be seen, in the compiled file, there is our own method of writing actionperformed, in addition to this there is a final variable this$0, that is, an implicit reference to the external class, the name is a compiler synthesized, in its own code can not be used, There is also a compiler-generated constructor in which there is an external class parameter.

Now that the compiler is able to convert automatically, can it be implemented without the internal classes?

First, Timeprinter is defined as a general class, and a this pointer is passed when the Timeprinter object is constructed in Talkingclock, outside the Talkingclock class. In Timeprinter, the beep instance inside the Talkingclock is accessed using the incoming Talkingclock pointer.

The problem arises that, in the Talkingclock class, the Beep is private and the external class cannot be accessed.

In other words, the internal class has access privileges to the external classes, so how does the compiler save the access privilege?

Use JAVAP to decompile the Talkingclock class to see the results:


In addition to our own definition of instance fields and methods, there is a static method Access$0, this method has a parameter, is the reference of this class. The return type of this method is exactly the type of beep to be used by the inner class. That is, the inner class gets the private member variable of the outer class by calling this method. That

if (beep)

is equivalent to:

if (access$0 (outer))

This can be risky, after all, everyone can access the private members of the external class through the Access$0 method. However, this method is hidden in the compiled bytecode, it is difficult to find the exact address of this method. Of course, it is not possible to use access$0 as an illegal method name in your own code.

4 Local Inner class

In the above example, the Timeprinter class is used only once in the Start method in the Talkingclock class. At this point, you can define the inner class as a local inner class.

public void Start () {<span style= "White-space:pre" ></span>class Timeprinter implements actionlistener{ public void actionperformed (ActionEvent event) {Date now=new date (); System.out.println ("At the tone,the time is" +now), if (beep) toolkit.getdefaulttoolkit (). Beep ();}} ActionListener listener=new Timeprinter (); Timer t=new timer (interval,listener); T.start ();}
A local inner class cannot be decorated with public or private access specifiers, and its scope is scoped to the block that declares the local class.

The advantage of a local class is that it can be completely hidden from the outside world, even if other methods in the Talkingclock class are inaccessible.

This example runs the same result as the above example.

5 access to the final variable by an external method

Local classes have the advantage of not only accessing the external classes that contain them, but also accessing local variables, compared to other inner classes. However, these variables must be declared final. The following code puts interval and beep in the Start method:

public void Start (int interval,final Boolean beep) {class Timeprinter implements Actionlistener{public void Actionperformed (ActionEvent event) {Date now=new date (); System.out.println ("At the tone,the time is" +now), if (beep) toolkit.getdefaulttoolkit (). Beep ();}} ActionListener listener=new Timeprinter (); Timer t=new timer (interval,listener); T.start ();}

Here, interval and beep are the arguments for start, so the Talkingclock class does not need to define these two member variables.

However, since the Timeprinter class is inside start, it should be able to access the variable.

In order to be able to clearly see the internal problems, consider the control process:

(1) Call the Start method;

(2) Call the constructor of the inner class Timeprinter in order to initialize the object variable listener;

(3) Passing the listener reference to the timer constructor, the timer starts to time, and the Start method ends. At this time, the beep parameter variables in the Start method no longer exist;

(4) Then, the Actionperformed method executes if (beep);

Can beep variable already lost, Ah, actionperformed method How also know beep value? The possible reason is that the inner class timeprinter the listener when it is constructed. Use JAVAP to see the definition of the inner class:


You can see that in addition to your own definition, there is a final variable val$beep, and the auto-generated constructor has a Boolean parameter in addition to the reference parameter of an external class, which starts with passing the beep variable. This confirms our speculation. In fact, when an object is created, beep is passed to the constructor and stored in the Val$beep domain. The compiler must check access to local variables, establish corresponding data fields for each variable, and copy local variables into the constructor to initialize the data fields to a copy of the local variables.

The beep variable is declared final, and it can no longer be modified after it is initialized, guaranteeing that the local variable and the copy in the local class remain consistent.

However, what if you need to modify this final value? For example, you need to update the counters within a closed scope. Here, count the number of times the CompareTo method was called during the sorting process.

At this point, final cannot succeed because it cannot be updated. However, the final variable can be modified using the following technique:

public static int count () {final int[] counter=new int[1];D ate[] dates=new date[100];for (int i=0;i<dates.length;i++) { Dates[i]=new Date () {public int compareTo (date other) {Counter[0]++;return Super.compareto (other);}};} Arrays.sort (dates); return counter[0];}
This defines an array of length 1, although it is not possible to make reference to another array, but the contents of the array can be changed.

The above code results are as follows:

99

6 Anonymous Inner class

Take a step further in the use of the local inner class. If you create only one object of this class, you do not have to name it. This class is called an anonymous inner class (anonymous inner classes). such as this:

public void Start (int interval,final boolean beep) {ActionListener listener=new ActionListener () {public void Actionperformed (ActionEvent event) {Date now=new date (); System.out.println ("At the tone,the time is" +now), if (beep) toolkit.getdefaulttoolkit (). Beep ();}}; Timer t=new timer (interval,listener); T.start ();}
The meaning of this syntax is to create a new object for the class that implements the ActionListener interface, the Actionperformed method that needs to be implemented inside the {}.

The usual syntax format is:

New Supertype (construction parameters) {        Inner class methods and data}

Where supertype can be an interface, the inner class will implement this interface, or it can be a class, so the inner class will extend it.

If the code for an inner class is small, you can use an anonymous inner class.

7 Static Inner class

If an inner class does not need to refer to an external class object, then an inner class can be hidden inside the outer class. To do this, you can declare the inner class as static in order to cancel the resulting reference.

The following is a typical example of using static internal classes. If you want to calculate the maximum and minimum values for an array, if you use two methods, you need to traverse the Group two times. If you get the maximum and minimum values in a single traversal, you need to return two results. To do this, you define a pair class that contains two values:

Class Pair{private double first;private double second;public Pair (double first,double second) {This.first=first; This.second=second;} Public double GetFirst () {return first;} Public double Getsecond () {return second;}}
Then define a method Minmax that can return the result of the pair type. The complete code is as follows:

public class Arrayalg {public static class Pair{private double First;private double second;public Pair (double first,double Second) {This.first=first;this.second=second;} Public double GetFirst () {return first;} Public double Getsecond () {return second;}} public static Pair Minmax (double[] values) {Double min=double.min_value;double max=double.max_value;for (double x: Values) {if (min>x) min=x;if (max<x) max=x;} return new Pair (Min,max);}}

Only inner classes can be declared as static. The object of a static inner class is the same as all inner classes except that it does not have the referential privilege to produce its outer class object. In this example, it must be defined as static because the inner class is defined in a static method.

Java Internal classes

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.