Basic operation of internal class (basic)

Inner class

The basic components in a class are member attributes and methods, but in any language, the structure also allows nesting. Therefore, other classes can be defined inside a class, and such a class becomes an internal class.

Basic definition of inner class

When it comes to internal classes, it must be an independent and perfect class structure. In addition to attributes and methods, you can continue to use class to define internal classes.

Example: basic definition of inner class

package org.demo.innerclass;

class Outer { //Outer represents an external class

    private String msg = "www.mldn.cn"; //Private member properties

    public void fun() { //Common method
        Inner in = new Inner();
        in.print();
    }

    class Inner { //The Inner class is defined inside the Outer
        public void print() {
            System.out.println(msg);//Properties in Outer class
            //If you want to use this MSG will report an error because this represents the current class object, but there is no such object in the Inner class
            //MSG, so an error will be reported. If you want to use this, you need outer this. msg
        }
    }
}

public class JavaDemo {
    public static void main(String[] args) {
        Outer out = new Outer();//Instantiated external class object
        out.fun();//Calling a method in an external class
    }
}

From the whole code, it is not difficult to understand the structure of the internal class. It can even be said that its structure is as clear as that of ordinary classes. So why provide a structure with inner classes? Because from the overall structure of the code, the structure of the internal class is unreasonable (you can dolly), so the biggest defect of the internal class itself is that it destroys the structure of the program, but this destruction must have a purpose, so it must have its advantages. If you want to better observe the advantages of the internal class, you can take the internal class outside.

Example: divide the above procedures into two categories

package org.demo.innerclass;

class Outer { //Outer represents an external class

    private String msg = "www.mldn.cn"; //Private member properties

    public void fun() { //Common method
        //Thinking 5: you need to pass the current object Outer to the Inner class
        Inner in = new Inner(this);
        in.print();
    }
    //Think 1: if you want the msg attribute to be accessed externally, you need to provide a getter method

    public String getMsg(){
        return this.msg;
    }

}

class Inner { //The Inner class is defined inside the Outer
    //Thinking 3: the instantiation of the Inner object requires the reference of the Outer class
    private Outer out ;
    //Think 4: you should get the Outer class object through the construction method of the Inner class
    public Inner(Outer out){
        this.out = out;
    }
    public void print() {
        //If you want to call the getter method in an external class, you must have an Outer class object
        System.out.println(this.out.getMsg());//In this way, another anonymous object is created, and the following is also new, which is a waste of space
    }

}

public class JavaDemo {
    public static void main(String[] args) {
        Outer out = new Outer();//Instantiated external class object
        out.fun();//Calling a method in an external class
    }
}
//Practice more, class association, but it's very troublesome

It can be found that the main purpose of tossing for a long time in the overall operation is to enable the Inner class to access the private properties in the Outer class, but the overall code is very troublesome when the internal class is not used, so we can draw the advantages of the internal class: easy access to the private properties in the external class. The significance of the internal class lies in accessing the private properties of the external class.

Description of internal class

Now that we have clearly recognized the advantages and structure of internal classes, we need to make some relevant descriptions of internal classes. The internal classes defined now belong to the form of ordinary internal classes. Ordinary classes often provide attributes and methods. It should be noted that although internal classes can easily access private members and methods in external classes, Similarly, external classes can easily access private members or private methods in internal classes.

Example: an external class accesses private properties in an internal class.

package org.demo.innerclass;

class Outer { //Outer represents an external class

    private String msg = "www.mldn.cn"; //Private member properties

    public void fun() { //Common method
        Inner in = new Inner();
        in.print();
        System.out.println(in.info); // Access the private properties of the internal class, which can be accessed directly
    }

    class Inner { //The Inner class is defined inside the Outer
        private String info = "It's a bad day today. I've got my clothes!";
        public void print() {
            System.out.println(msg);//Properties in Outer class
            //If you want to use this MSG will report an error because this represents the current class object, but there is no such object in the Inner class
            //MSG, so an error will be reported. If you want to use this, you need outer this. msg
        }

    }

}

public class JavaDemo {
    public static void main(String[] args) {
        Outer out = new Outer();//Instantiated external class object
        out.fun();//Calling a method in an external class
    }
}

After using the internal class, the access of private operations between the internal class and the external class does not need to be completed through setter s, getter s and other methods, and can be processed directly.

However, it should be noted that the internal class itself also belongs to a class. Although in most cases, the internal class is often wrapped by the external class, the external class can still generate the instantiation object of the internal class. At this time, the format of the instantiation object of the internal class is as follows:

External class Inner class inner class object = new outer class () New inner class (); If there are nested classes, continue to new.

For example:

Two level nesting:

Outer.Inner in = new Outer().new Inner();

Three level nesting:

Outer.Inner.Inner2 in = new Outer().new Inner().new Inner2();

Why write it like this? Let's look at a major problem

After the inner class is completed, an "Outer" will be automatically formed I n n e r . c l a s s " class writing piece , his in " Inner.class "class file, where" Inner.class "class file, in which the symbol" "is changed to" "in the program "

Therefore, the full name of the internal class is "external class. Internal class" (so it is clear why it is written in this way on the left of the equal sign). Private members can be accessed directly between internal classes and external classes. In this way, if an instantiated object is provided in the internal class, you must first ensure that the external class has been instantiated. If your external class is not instantiated, there will be no open space, and there will be no place for the member variables inside. If there is nothing, you can't access it.

Look at the following code: previously, a fun() method is defined inside the external class Outer, then the internal class is instantiated inside the fun() method, and then the print() method is called with the object of the internal class. Then instantiate the external class in other classes to call the fun() method, which is too cumbersome. If you want to call the print() method in the Inner class directly in other classes, how do you define it?

The answer is:

Outer.Inner in = new Outer().new Inner(); // Make sure that the external class has been instantiated first

package org.demo.innerclass;

class Outer { //Outer represents an external class
    private String msg = "www.mldn.cn"; //Private member properties
        /*public void fun() { //Common method
            Inner in = new Inner();
            in.print();
            System.out.println(info); // Access the private properties of the internal class, which can be accessed directly
        }*/
    class  Inner { //The Inner class is defined inside the Outer
      //  private String info = "the weather is bad today, so I have to collect my clothes!";
        public void print() {
            System.out.println(Outer.this.msg);//Properties in Outer class
            //If you want to use this MSG will report an error because this represents the current class object, but there is no such object in the Inner class
            //MSG, so an error will be reported. If you want to use this, you need outer this. msg
        }
    }
}

public class JavaDemo {
    public static void main(String[] args) {
        /*Outer out = new Outer();//Instantiated external class object
        out.fun();//Calling a method in an external class*/
        //I want to call the print() method in the Inner class. How can I instantiate it?
        //Inner in = new Inner();  This instantiation will directly report an error. You must instantiate the external class before you can instantiate the internal class
        Outer.Inner in = new Outer().new Inner();//Internal classes can only be accessed in this form
        in.print();
    }
}

If the Inner class only allows the Outer class to be used at this time, you can use private for private definition in this case.

This form of operation directly limits that your external class cannot generate instantiated objects of internal classes, and the Inner class cannot be used externally at this time.

package org.demo.innerclass;

class Outer { //Outer represents an external class
    private String msg = "www.mldn.cn"; //Private member properties

    public void fun() { //Common method
        Inner in = new Inner();
        in.print();
        System.out.println(in.info); // Access the private properties of the internal class, which can be accessed directly
    }

    private class Inner { //The Inner class is defined inside the Outer
        private String info = "It's a bad day today. I've got my clothes!";

        public void print() {
            System.out.println(Outer.this.msg);//Properties in Outer class

        }
    }
}

public class JavaDemo {
    public static void main(String[] args) {
        Outer out = new Outer();//Instantiated external class object
        out.fun();//Calling a method in an external class
    }
}

In Java, as the most basic structure, classes actually have similar abstract classes or interfaces. Internal class structures can be defined in free classes and interfaces (that is, the internal structure is not limited by you).

Example: define internal interface

package org.demo.innerclass;

interface IChannel{ //Define interface
    public void send(IMessage msg);
    interface IMessage{ //Internal interface
        public String getContent(); //Get message content
    }
}
 //How to implement the internal interface?
class ChannelImpl implements IChannel{
     // Only implementing the methods in one interface of IChannel will not report an error. The internal interface does not mean that it must be implemented
    public void send(IMessage msg) {
        System.out.println("send message" + msg.getContent());
    }
    class MessageImpl implements IMessage{
        public String getContent() {
            return "www.baidu.com";
        }
    }
}
public class JavaDemo {
    public static void main(String[] args) {
            IChannel channel = new ChannelImpl();
            channel.send(((ChannelImpl)channel).new MessageImpl());
            //channel.send((channel).new MessageImpl());  Remove the strong transfer error, because the channel is IChannel type, and it needs ChannelImpl type
           /* IChannel.IMessage in = new ChannelImpl().new MessageImpl();
            System.out.println(in.getContent());*/
        /** Check the following line
         *  Outer.Inner in = new Outer().new Inner();
         *  To call the method of internal interface, instantiate the object of new external interface subclass first, and then Subclass instantiation object of internal interface
         *  IChannel.IMessage in = new ChannelImpl().new MessageImpl(); This will be easier to understand
         */
    }
}

Let's continue to observe an internal abstract class. Internal abstract classes can be defined in ordinary classes, abstract classes and interfaces.

Example: observe the internal abstract class

package org.demo.innerclass;

import org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCodeHelper;

import java.nio.channels.Channel;

interface IChannel { //Define interface
    public void send();

    abstract class AbstractMessage { //Internal abstract class
        public abstract String getContent();
    }
}

class ChannelImpl implements IChannel {
    public void send() {
        AbstractMessage msg = new MessageImpl();
        System.out.println(msg.getContent());
    }

    class MessageImpl extends AbstractMessage {
        public String getContent() {
            return "www.baidu.com";
        }
    }
}

public class JavaDemo {
    public static void main(String[] args) {
        IChannel channel = new ChannelImpl();
        channel.send();
    }
}

There are also some more interesting structures in the internal class, that is, if an interface is defined now, the interface can be implemented internally by using the class in jdk1 After 8, the static method is added to the interface, which can not be controlled by the instantiated object. Now you can use this feature to complete the function.

Example: interface implementation inside the interface

package org.demo.innerclass;

interface IChannel { //Define interface
    public  void send();
    class ChannelImpl implements IChannel{
        @Override
        public void send() {
            System.out.println("hello");
        }
    }
    public static IChannel getInstance(){
        return new ChannelImpl();
    }

}
public class JavaDemo {
    public static void main(String[] args) {
        /*IChannel.ChannelImpl in = new IChannel.ChannelImpl();
        in.send();
        You can also implement it, but you also need to know the class name of the internal implementation class
        */
        IChannel channel = IChannel.getInstance();//Directly call the static method in the interface and return the implementation class of the interface
        channel.send();//Then call the send() method. It's wonderful!
    }
}

Internal class is a very flexible definition structure. As long as your syntax is satisfied, all kinds of requirements can be implemented for you. Therefore, in the future, I may often see static methods provided in abstract classes or interfaces, but I can't find the definition of abstract classes or interface subclasses, because they are written inside abstract classes and interfaces. At this time, it is often the implementation of abstract classes or interfaces in internal classes, which will be seen in many class libraries in the future.

static defines internal classes

If the static definition is used on the internal class, the internal class will become an "external class". Static defines a structure independent of the class, so the class structure is equivalent to an independent program class. It should be noted that the event class or method defined by static can only access static members, so the internal class defined by static can only access static properties or methods in the external class.

Example: using static to define internal classes

package org.demo.innerclass;

class Outer{
    private static final String MSG = "www.baidu.com";
    static class Inner{
        public void print(){
            System.out.println(Outer.MSG);
        }
    }
}
public class JavaDemo {
    public static void main(String[] args) {

    }
}

This completes the internal class operation defined by static, but the following one is key. At this time, the Inner class is an independent class. If you want to instantiate the Inner class object at this time, you only need to instantiate the object according to the * * external class. Internal class * * structure. The format is as follows (rather awkward):

General internal class External class Inner class inner class object = new outer class () New inner class ();
Static inner class External class Inner class inner class object = new outer class () Internal class ();

At this time, the class name has * * ". * *.

Example: instantiate static internal class object

package org.demo.innerclass;

class Outer{
    private static final String MSG = "www.baidu.com";
    static class Inner{
        public void print(){
            System.out.println(Outer.MSG);
        }
    }
}
public class JavaDemo {
    public static void main(String[] args) {
        Outer.Inner in = new Outer.Inner();
        //Outer.Inner() has a dot in the middle. You will see the dot in the class name later Yes, they should
        //I immediately realized that this is an internal class. If it can be instantiated directly, it must be a static internal class.
        in.print();
    }
}

If a "." is provided on the class name in the future development, You should immediately realize that this is an internal class structure. If you can instantiate it directly (new appears once), you should immediately realize that this is an internal class defined by static.

It is not commonly used in the form of static defining internal classes, but the form of static defining internal interfaces is the most commonly used.

Example: using static to define internal interfaces

package org.demo.innerclass;

interface IMessageWarp { //Message wrapping
    static interface IMessage { //Get message
        public String getContent();
    }

    static interface IChannel {
        public boolean connect();//Message sending channel
    }

    public static void send(IMessage msg, IChannel channel) {
        ; //message sending
        if (channel.connect()) {
            System.out.println(msg.getContent());
        } else {
            System.out.println("Message channel is not connected!");
        }
    }
}

class DefaultMessage implements IMessageWarp.IMessage {//Because it is an internal interface, it is necessary to set the internal interface after the external interface

    //If the IMessageWarp interface is also implemented, there is no need to duplicate the send() method, because the send() method is static
    public String getContent() {
        return "www.baidu.com";
    }
}

class NetChannel implements IMessageWarp.IChannel {
    @Override
    public boolean connect() {
        return true;
    }
}


public class JavaDemo {
    public static void main(String[] args) {
        IMessageWarp.send(new DefaultMessage(), new NetChannel());
    }
}

The reason why static is used to define internal interfaces is that these operations belong to a group of related definitions. With external interfaces, the main functions of these interfaces can be more clearly described and unified management can be done.

Method

Internal classes can be defined in any structure, including classes, methods and code blocks. However, in terms of actual development, there are many forms of defining internal classes in methods.

Example: observe the inner class defined in the method

package org.demo.innerclass;

class Outer {
    private String msg = "www.baidu.com";

    public void fun(long time) {
        class Inner {
            public void print() {
                System.out.println(Outer.this.msg);
                System.out.println(time);
            }
        }
        new Inner().print();//Method to directly instantiate the internal class object and call the method
    }
}

public class JavaDemo {
    public static void main(String[] args) {
        new Outer().fun(12311L);//Both method parameters and properties in the class can be accessed directly in the inner class
    }
}

At this time, the definition of the Inner inner class is provided inside the fun() method, and it can be found that the Inner class can directly access the private properties of the outer class or the parameters in the method, but the direct access to the parameters in the method is from jdk1 8 began to support (because of Lambda expressions), while in jdk1 Before 8, if the internal class defined in the method wants to access the parameters in the method, final must be appended before the parameters.

Example: in jdk1 8 previous program structure

package org.demo.innerclass;

class Outer {
    private String msg = "www.baidu.com";

    public void fun(final long time) {
        final String info = "I'm fine";
        class Inner {
            public void print() {
                System.out.println(Outer.this.msg);
                System.out.println(time);
                System.out.println(info);
                //JDK1. Before 8, it cannot be accessed directly without final modification
            }
        }
        new Inner().print();//Method to directly instantiate the internal class object and call the method
    }
}

public class JavaDemo {
    public static void main(String[] args) {
        new Outer().fun(12311L);//Both method parameters and properties in the class can be accessed directly in the inner class
    }
}

The reason why such restrictions are cancelled is mainly for the extended functions prepared by functional programming.

Anonymous Inner Class

Anonymous inner class is a simplified form of inner class processing, which is mainly used on abstract classes and subclasses of interfaces.

Example: observe a basic program structure

package org.demo.innerclass;

interface IMessage {
    public void send(String str);
}

class MessageImpl implements IMessage {
    @Override
    public void send(String str) {
        System.out.println(str);
    }
}

public class JavaDemo {
    public static void main(String[] args) {
        IMessage i = new MessageImpl();
        i.send("www.baidu.com");

    }
}
//Normal subclasses implement interface calling methods

If the MessageImpl in the IMessage interface is used only once, is it necessary to define it as a separate class? If you use it once and define a class for him alone, it feels very wasteful. Then, under such requirements, it is found that the defined subclasses are redundant, so we can use the form of anonymous internal classes to solve this problem. (this method is mostly used to add monitoring to buttons in Android.)

Example: using anonymous inner classes

package org.demo.innerclass;

interface IMessage {
    public void send(String str);
}

public class JavaDemo {
    public static void main(String[] args) {
        IMessage i = new IMessage() {
            public void send(String str) { //Anonymous inner class, and the implemented subclasses are anonymous
                System.out.println(str);
            }
        };
        i.send("www.baidu.com");
    }
}

Anonymous inner classes are not only used for abstract classes and interfaces, but are generally used for abstract classes and interfaces. Sometimes, in order to more conveniently reflect the use of anonymous internal classes, you can often use static methods to implement an internal anonymous internal class.

Example: define anonymous inner classes directly in the interface

package org.demo.innerclass;

interface IMessage {
    public void send(String str);

    public static IMessage getInstance() {
        return new IMessage() {
            @Override
            public void send(String str) {
                System.out.println(str);
            }
        };
    }
}

public class JavaDemo {
    public static void main(String[] args) {
        IMessage.getInstance().send("www.baidu.com");
    }
}
//Many times, anonymous inner classes can be used to handle operations

Compared with the inner class, the anonymous inner class is just a subclass with a fixed structure that has no name and can only be used once.

Tags: Java interface abstract class

Posted by thewitt on Tue, 03 May 2022 12:42:51 +0300