Java internal class summary and usage instructions

Source: Internet
Author: User

From: http://blog.sina.com.cn/s/blog_56898c310100a3i3.html

An internal class refers to defining another class within an external class. An internal class is a member of an external class and is attached to an external class. Internal classes can be static and can be modified using protected and private (while external classes can only make

Use public and default package access permissions ). Internal classes include the following types: member Internal classes, partial internal classes, static internal classes, and anonymous internal classes.

Why Internal classes?

Typically, an internal class inherits from a class or implements an interface, and the code operation of the internal class creates its peripheral class object. So you can think that the internal class provides a window for entering its peripheral class. Use internal classes to suck the most

The reason is:

Each internal class can inherit from one (Interface) implementation independently, so no matter whether the peripheral class has inherited a (Interface) implementation, it has no impact on the internal class. If no internal class is provided, multiple

It is difficult to solve some design and programming problems. From this perspective, the internal class makes the multi-inheritance solution complete. The interface solves some problems, while the internal class effectively implements "Multi-inheritance"

".

A: Member internal class

As a member of an external class, it is in parallel with the attributes and methods of the external class.

Publicclass outer {
Privatestaticinti = 1;
Privateintj = 10;
Privateintk = 20;

Publicstaticvoidouter_f1 (){
}

Publicvoidouter_f2 (){
}

// The static member cannot be defined in the member's internal class.
// All members of the external class can be accessed in the member internal class.
Class inner {
// Static int inner_ I = 100; // static variables cannot be defined in the internal class
Intj = 100; // instance variables of internal and external classes can coexist.
Intinner_ I = 1;

Void inner_f1 (){
System. Out. println (I );
// Directly use the variable name to access the internal class's own variables in the internal class
System. Out. println (j );
// You can use this. variable name to access the internal class's own variables.
System. Out. println (this. J );
// Access instance variables with the same name as the internal class in the internal class using the external class name. This. variable name
System. Out. println (outer. This. J );
// If the internal class does not have a variable with the same name as the external class, you can directly use the variable name to access the external class variable.
System. Out. println (k );
Outer_f1 ();
Outer_f2 ();
}
}

// Access the internal class of the member using non-static methods of the external class
Publicvoidouter_f3 (){
Inner inner = new inner ();
Inner. inner_f1 ();
}

// The static method of the external class accesses the internal class of the member, which is the same as the internal class of the external class access member.
Publicstaticvoidouter_f4 (){
// Step 1 create an external Class Object
Outer out = new outer ();
// Step 2: create an internal class object based on the external Class Object
Inner inner = out. New inner ();
// Step 3: Access the internal class
Inner. inner_f1 ();
}

Publicstaticvoid main (string [] ARGs ){
// Outer_f4 (); // The output result of this statement is the same as that of the following three statements:
// If You Want To directly create an internal class object, you cannot assume that you only need to add the outer name of the peripheral class,
// You can generate an internal class object as usual, but you must use an object of this peripheral class
// Create an object of its internal class:
// Outer. Inner outin = out. New inner ()
// Therefore, unless you already have an object of the peripheral class, it is impossible to generate an object of the internal class. Because
// The object of the internal class is quietly linked to the object of the created peripheral class. If you use a static internal class,
// You do not need to reference its peripheral class objects.
Outer out = new outer ();
Outer. Inner outin = out. New inner ();
Outin. inner_f1 ();
}
}

Note: Internal classes are a compilation concept. Once compiled successfully, they become completely different. For an external class named outer and its internal defined internal class named inner. After compilation

Outer. Class and outer $ inner. Class.

B: Local internal class

The internal class defined in the method is called a local internal class. Similar to local variables, the local internal class cannot have access specifiers because it is not part of the peripheral class, but it can access constants in the current code block, and the peripheral class

All members.

Publicclass outer {
Privateints = 100;
Privateintout_ I = 1;

Publicvoid F (finalint K ){
Finalint S = 200;
Int I = 1;
Finalint J = 10;

// Defined inside the Method
Class inner {
Ints = 300; // a variable with the same name as an external class can be defined.

// Static int M = 20; // static variables cannot be defined
Inner (int K ){
Inner_f (k );
}

Intinner_ I = 100;

Voidinner_f (int K ){
// If the internal class does not have a variable with the same name as the external class, you can directly access the instance variables of the external class in the internal class.
System. Out. println (out_ I );
// You can access the local variables of the external class (that is, the variables in the method), but the variables must be final
System. Out. println (j );
// System. Out. println (I );
// If the internal class has a variable with the same name as the external class, you can directly use the variable name to access the variable of the internal class.
System. Out. println (s );
// Use this. variable name to access internal class variables
System. Out. println (this. s );
// Use the external class name. This. The internal class variable name accesses the external class variable
System. Out. println (outer. This. s );
}
}
New inner (k );
}

Publicstaticvoid main (string [] ARGs ){
// To access a local internal class, you must first have an external class object.
Outer out = new outer ();
Out. F (3 );
}
}

C: static internal class (nested class): (Note: The first two internal classes are similar to variables, so you can refer to the variables)

If you do not need to associate an internal class object with its peripheral class object, you can declare the internal class as static. This is usually called a nested class ). To understand the meaning of applying static to internal classes, you

You must remember that a reference is implicitly saved for a common internal class object, pointing to the peripheral class object created for it. However, this is not the case when the internal class is static. Nested classes mean:

1. To create nested class objects, you do not need the objects of its peripheral class.
2. Non-static peripheral class objects cannot be accessed from nested class objects.

Publicclass outer {
Privatestaticinti = 1;
Privateintj = 10;
Publicstaticvoidouter_f1 (){
}

Publicvoidouter_f2 (){
}

// Static internal classes can be modified using public, protected, and private.
// Static or non-static members can be defined in the static internal class.
Staticclass inner {
Staticintinner_ I = 100;
Intinner_j = 200;
Staticvoidinner_f1 (){
// The static internal class can only access static members of the external class (including static variables and static methods)
System. Out. println ("outer. I" + I );
Outer_f1 ();
}

Voidinner_f2 (){
// The static internal class cannot access non-static members of the external class (including non-static variables and non-static methods)
// System. Out. println ("outer. I" + J );
// Outer_f2 ();
}
}

Publicvoidouter_f3 (){
// Static members of the external class to access the internal class: internal class. Static members
System. Out. println (inner. inner_ I );
Inner. inner_f1 ();
// Non-static members of the internal class accessed by the external class: instantiate the internal class.
Inner inner = new inner ();
Inner. inner_f2 ();
}

Publicstaticvoid main (string [] ARGs ){
Newouter (). outer_f3 ();
}
}

Generating a static internal class does not require external class members: this is the difference between the static internal class and the member internal class. Objects of static internal classes can be directly generated: outer. Inner in = new outer. Inner ();

Is generated as an external class object. In this way, the static internal class is actually a top-level class (normally, you cannot place any code inside the interface, but the nested class can be part of the interface because it is static. Just

Place the nested class in the interface namespace, which does not violate the interface rules)

D: anonymous internal class (from thinking in Java 3th)

To put it simply, an anonymous internal class is an internal class without a name. Under what circumstances do I need to use an anonymous internal class? If the following conditions are met, it is appropriate to use an anonymous internal class:

· Only use one instance of the class.
· Classes are used immediately after definition.
· The class is very small (Sun recommends following four lines of code)
· Naming classes does not make your code easier to understand.
When using anonymous internal classes, remember the following principles:
· No constructor is allowed for anonymous internal classes.
· Anonymous internal classes cannot define any static members, methods, and classes.
· Anonymous internal classes cannot be public, protected, private, or static.
· Only one instance of the anonymous internal class can be created.
· An anonymous internal class must be behind New and be used to implicitly implement an interface or implement a class.
· Because the anonymous internal class is a local internal class, all restrictions on the local internal class take effect.

The following example looks a bit strange:

// Return an anonymous internal class in the Method
Public class parcel6 {
Public contents cont (){
Return new contents (){
Private int I = 11;

Public int value (){
Return I;
}
}; // A semicolon is required here
}

Public static void main (string [] ARGs ){
Parcel6 P = new parcel6 ();
Contents c = P. cont ();
}
}

The cont () method combines the following two actions: the generation of the return value, and the definition of the class that represents the returned value! Further, this class is anonymous and has no name. Worse, it looks like you're about to create

Contents object:

Return new contents ()

However, before arriving at the end of the statement, you say, "Wait, I want to insert a class definition here ":

Return new contents (){
Private int I = 11;
Public int value () {return I ;}
};

This strange syntax refers to: "Creating an object that inherits an anonymous class from contents ." The reference returned by the new expression is automatically converted to a reference to contents. The syntax of the anonymous internal class is as follows:

Simple Form:

Class mycontents implements contents {
Private int I = 11;
Public int value () {return I ;}
}
Return new mycontents ();

In this anonymous internal class, the default contents is generated using the contents constructor. The following code shows what to do if your base class needs a constructor with parameters:

Public class parcel7 {
Public wrapping wrap (int x ){
// Base constructor call:
Return new wrapping (x) {// pass constructor argument.
Public int value (){
Return super. Value () * 47;
}
}; // Semicolon required
}
Public static void main (string [] ARGs ){
Parcel7 P = new parcel7 ();
Wrapping W = P. Wrap (10 );
}
}

Simply pass the appropriate parameters to the constructors of the base class. Here, X is passed to new wrapping (X ). The semicolon at the end of an anonymous internal class is not used to mark the end of this internal class (in C ++ ). Actually,

It marks the end of the expression, but the expression exactly contains the internal class. Therefore, this is consistent with the semicolon used elsewhere.

If you define a member variable in an anonymous class, you can also initialize it:

Public class parcel8 {
// Argument must be final to use inside
// Anonymous inner class:
Public destination DEST (final string DEST ){
Return new destination (){
Private string label = DEST;
Public String readlabel () {return label ;}
};
}
Public static void main (string [] ARGs ){
Parcel8 P = new parcel8 ();
Destination d = P. DEST ("Tanzania ");
}
}

If you have an anonymous internal class that uses an object defined externally, the compiler will require its parameter reference to be final, just like a parameter in DEST. If you forget it, you will get a compilation error message.

. If you simply assign values to a member variable, the method in this example is okay. But what if you want to do something similar to the constructor? It is impossible to have a named constructor in an anonymous class (because it

No name at all !), However, through instance initialization, you can create a constructor for the anonymous internal class. Do as follows:

Abstract class base {
Public base (int I ){
System. Out. println ("base constructor, I =" + I );
}
Public abstract void F ();
}

Public class anonymousconstructor {
Public static base getbase (int I ){
Return new base (I ){
{
System. Out. println ("Inside instance initializer ");
}
Public void F (){
System. Out. println ("in anonymous F ()");
}
};
}
Public static void main (string [] ARGs ){
Base base = getbase (47 );
Base. F ();
}
}

In this example, the variable I must be final. Because I is passed to the constructor of the base class of the anonymous class, it is not directly used within the Anonymous class. The following example shows the "parcel" format with instance initialization. Note:

The Dest () parameters must be final because they are used within the Anonymous class.

Public class parcel9 {
Public destinationdest (final string DEST, final float price ){
Return new destination (){
Private int cost;
// Instance initialization for each object:
{
Cost = math. Round (price );
If (Cost & gt; 100)
System. Out. println ("over budget! ");
}

Private string label = DEST;
Public String readlabel () {return label ;}
};
}
Public static void main (string [] ARGs ){
Parcel9 P = new parcel9 ();
Destination d = P. DEST ("Tanzania", 101.395f );
}
}

In the initialization part of the instance, you can see that there is a piece of code that cannot be executed as a part of the member variable initialization (that is, the IF Statement ). Therefore, for anonymous classes, the actual effect of instance Initialization is

Constructor. Of course, it is restricted: you cannot reload instance initialization, so you can only have one constructor.

Access external resources from multi-layer nested classes

It doesn't matter how many layers an internal class is nested. It can transparently access all the members of all the peripheral classes it embeds, as shown below:

Class MNA {
Private void F (){}
Class {
Private void g (){}
Public Class B {
Void H (){
G ();
F ();
}
}
}
}
Public class multinestingaccess {
Public static void main (string [] ARGs ){
MNA = new MNA ();
MNA. a mnaa = MNA. New ();
MNA. A. B mnaab = MNAA. New B ();
Mnaab. H ();
}
}

In MNA. A. B, calling methods g () and F () does not require any conditions (even if they are defined as private ). This example also shows how to create the basic syntax of multi-layer nested internal class objects from different classes.

. The ". New" syntax produces the correct scope, so you do not have to specify the class name when calling the constructor.

Overload of internal classes

What happens when you create an internal class, inherit its peripheral class, and redefine the internal class? That is to say, can internal classes be overloaded? This seems to be a very useful idea, but it is within the "reload"

The class is like a method of the peripheral class, but it does not actually play any role:

Class egg {
Private yolk y;

Protectedclass yolk {
Public yolk (){
System. Out. println ("egg. yolk ()");
}
}

Public egg (){
System. Out. println ("New egg ()");
Y = New Yolk ();
}
}

Publicclass bigegg extends egg {
Publicclass yolk {
Public yolk (){
System. Out. println ("bigegg. yolk ()");
}
}

Publicstaticvoid main (string [] ARGs ){
New bigegg ();
}
}

Output result:

New egg ()
Egg. yolk ()

The default constructor is automatically generated by the compiler. The default constructor of the base class is called here. You may think that since the bigegg object is created, the yolk used should be "overloaded", but you can

This is not the case.

This example shows that when you inherit a peripheral class, the internal class has not changed significantly. These two internal classes are two completely independent entities, each in their own namespace. Of course

It is also possible to assume an internal class:

Class egg2 {
Protected class yolk {
Public yolk (){
System. Out. println ("egg2.yolk ()");
}

Public void F (){
System. Out. println ("egg2.yolk. F ()");
}
}

Private yolk y = New Yolk ();

Public egg2 (){
System. Out. println ("New egg2 ()");
}

Public void insertyolk (yolk YY ){
Y = YY;
}

Public void g (){
Y. F ();
}
}

Public class bigegg2 extends egg2 {
Public class yolk extends egg2.yolk {
Public yolk (){
System. Out. println ("bigegg2.yolk ()");
}

Public void F (){
System. Out. println ("bigegg2.yolk. F ()");
}
}

Public bigegg2 (){
Insertyolk (New Yolk ());
}

Public static void main (string [] ARGs ){
Egg2 e2 = new bigegg2 ();
E2.g ();
}
}

Output result:

Egg2.yolk ()
New egg2 ()
Egg2.yolk ()
Bigegg2.yolk ()
Bigegg2.yolk. F ()

Currently, bigegg2.yolk explicitly inherits this internal class through the extends egg2.yolk and reloads the methods in it. The insertyolk () method of egg2 enables bigegg2 to transform its own yolk object upwards.

And then pass it to reference y. Therefore, when G () calls Y. F (), the new version of F () after the overload is executed. The second call to egg2.yolk () is the bigegg2.yolk constructor that calls its base class constructor. We can see that when calling g,

The new version of F () is called.

Inheritance of internal classes (thinking in Java 3th p294)

Because the constructor of the internal class needs to use the reference of its peripheral class object, it becomes a little complicated when you inherit an internal class. The problem is that the reference of the "secret" peripheral class object must be initialized

The inherited class does not have the default object to be joined. To solve this problem, we need to use special syntax to clarify the associations between them:

Class withinner {
Class inner {
Inner (){
System. Out. println ("this is a constructor in withinner. Inner ");
};
}
}

Public class inheritinner extends withinner. Inner {
//! Inheritinner () {}// won't compile
Inheritinner (withinner WI ){
WI. Super ();
System. Out. println ("this is a constructor in inheritinner ");
}

Public static void main (string [] ARGs ){
Withinner Wi = new withinner ();
Inheritinner II = new inheritinner (WI );
}
}

Output result:

This is a constructor in withinner. Inner
This is a constructor in inheritinner

As you can see, inheritinner only inherits from internal classes, rather than peripheral classes. However, to generate a constructor, the default constructor is not good, and you cannot just pass a reference pointing to a peripheral class object. In addition

You must use the following syntax in the constructor:

Enclosingclassreference. Super ();

In this way, necessary references are provided before the program can be compiled and passed.

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.