简体   繁体   English

如何在Java中实例化内部类真正起作用?

[英]How instantiating an inner class in Java really works?

I'm making an instance from an inner class, but I can't understand what does this syntax mean. 我正在从内部类中创建一个实例,但是我不明白该语法的含义。

OuterClass outerObject = new OuterClass();

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

I know that I can't get an object from an inner class without getting an object from the outer one OuterClass outerObject = new OuterClass(); 我知道,如果不从外部类中获取对象,就无法从内部类中获取对象OuterClass outerObject = new OuterClass(); , then we use the object from the outer class outerObject to get an instance from the inner class outerObject.new InnerClass(); ,然后使用外部类externalObject的对象从内部类outerObject.new InnerClass();获得实例outerObject.new InnerClass(); , so what does OuterClass.InnerClass actually means as it is not explained in the Java documentation as it states: ,因此OuterClass.InnerClass的实际含义是,因为Java文档中没有说明,因为它指出:

To instantiate an inner class, you must first instantiate the outer class. 要实例化内部类,必须首先实例化外部类。 Then, create the inner object within the outer object with this syntax OuterClass.InnerClass innerObject = outerObject.new InnerClass(); 然后,使用以下语法在外部对象内创建内部对象: OuterClass.InnerClass innerObject = outerObject.new InnerClass();

If I recall correctly, the syntactic meaning is as follows: 如果我没记错的话,语法含义如下:

OuterClass.InnerClass innerObject = outerObject.new InnerClass(); 
           InnerClass                                             The class InnerClass
          .                                                       which is an inner class of
OuterClass                                                        OuterClass
                      innerObject                                 has an instance named innerObject
                                  =                               which is assigned the value
                                                new InnerClass()  of a new InnerClass instance
                                               .                  such that when you use
                                                                  OuterClass.this from within
                                                                  InnerClass methods invoked on
                                                                  innerObject, it refers to
                                    outerObject                   outerObject.

The key here is that inner classes are created through a reference to the outer class. 这里的关键是内部类是通过对外部类的引用来创建的。 If your InnerClass is static (one InnerClass for the entire OuterClass class), you'll see that the reference to the outer class is static: 如果您的InnerClass是静态的(整个OuterClass类一个InnerClass),您将看到对外部类的引用是静态的:

static class InnerClass { ... }
...
//Initialization will become:
OuterClass.InnerClass innerObject = new OuterClass.InnerClass();
                                        ^ this part is a static OuterClass reference

On the other hand, in your current scenario (InnerClass is not static), the inner class must be created with a reference to the OuterClass in the form of an object - outerObject . 另一方面,在您当前的情况下(InnerClass不是静态的),必须使用对象outerObject的形式对outerObject的引用来创建内部类。 Furthermore, you are actually able to access outerObject from within InnerClass by referring to OuterClass.this : 此外,你实际上可以访问outerObject参照从内部将InnerClass OuterClass.this

OuterClass.java OuterClass.java

public class OuterClass
{
  class InnerClass
  {
    public OuterClass getOuterClassReference()
    {
      return OuterClass.this;
    }
  }
}

Main.java Main.java

class Main
{
  public static void main(String[] args)
  {
    OuterClass outerObject = new OuterClass();
    OuterClass.InnerClass innerObject = outerObject.new InnerClass(); 
    System.out.println(outerObject);
    System.out.println(innerObject.getOuterClassReference());
    System.out.println(outerObject == innerObject.getOuterClassReference());
  }
}

Output: 输出:

OuterClass@36baf30c @在OuterClass 36baf30c
OuterClass@36baf30c @在OuterClass 36baf30c
true 真正

Here, 36baf30c in the output is an arbitrary memory address. 此处,输出中的36baf30c是任意存储器地址。 These two output lines will always be the same. 这两条输出线将始终相同。 As you can clearly see, referring to OuterClass.this from within an InnerClass instance will return the OuterClass instance that was provided at initialization. 正如你可以清楚地看到,参照OuterClass.this从实例将InnerClass内将返回在初始化提供的实例在OuterClass。 This is part of the reason that you can't just call new InnerClass() - the reference OuterClass.this cannot be initialized properly without being provided with an instance. 这是,你不能只是调用的原因之一new InnerClass() -参考OuterClass.this不能在没有设置有一个实例正确初始化。

This is the name of the class, and it's likely named this way to make it easier for the compiler to find the definition. 这是类的名称,并且可能以这种方式命名,以使编译器更容易找到定义。

If you declare your variable as just being of type InnerClass , it will look for the file InnerClass.java , but there is no such file. 如果将变量声明为InnerClass类型,它将查找文件InnerClass.java ,但没有此类文件。

The dot notation indicates that it's actually a member of OuterClass , so it will look for the definition within the file OuterClass.java . 点符号表示它实际上是OuterClass的成员,因此它将在文件OuterClass.java查找定义。

This is the same thing as using a class from a library, 这与使用库中的类相同,

com.example.MyLibrary.ExternalClass myExternalObject;

JVM does not make a difference between OuterClass and InnerClass : both classes are POJO and separate classes. JVM不作之间的差异OuterClassInnerClass :这两个类是POJO和单独的类。 But InnerClass is not static and therefore it has internal this refers to the instance of OuterClass (therefore it should be created only with existed OuterClass instance) InnerClass不是static ,因此它具有内部this是指的实例OuterClass (因此它应该只存在创建OuterClass实例)

public class OuterClass {
    public class InnerClass {
        public OuterClass getOuterClassReference() {
            return OuterClass.this;
        }
    }
}

OuterClass outerObject = new OuterClass();
OuterClass.InnterClass innerObject = outerObject.new InnerClass(); // innerObject has this reference to outerObject

public class OuterClass {
    public static class InnerClass {}
}

OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = new OuterClass.InnerClass(); // innerObject does not have this reference to outerObject

In other words, you can emulate InnterClass by yourself like this: 换句话说,您可以像这样自己模仿InnterClass

public class OuterClass {   
}

public class InnerClass {
    private final OuterClass outer;

    public InnerClass(OuterClass outer) {
        this.outer = outer;
    }   
}

Outerclass.Innerclass is just a part of the Innerclass' full path. Outerclass.Innerclass只是Innerclass完整路径的一部分。
The full path would be something like packagename.Outerclass.Innerclass . 完整路径类似于packagename.Outerclass.Innerclass

Thus, OuterClass.InnerClass innerObject = outerObject.new InnerClass(); 因此, OuterClass.InnerClass innerObject = outerObject.new InnerClass(); is really no different from something like: 确实与以下内容没有什么不同:
java.util.ArrayList<T> varName = new java.util.ArrayList<T>();

You can define the inner class as static member of OuterClass 您可以将内部类定义为OuterClass的静态成员

public class OuterClass {
    public static class StaticInnerClass {
        int i = 0;

        public String call() {
            i++;
            return this.getClass().getName() + " i=" + i;
        }
    }
}

so defining the static inner class the compile knows that members is a class, the memory area is instanced at compile time (it is accessible in static way) and you can apply the new operator and the new operator instances the class in another memory area. 因此,在定义静态内部类时,编译器知道成员是一个类,该存储区在编译时被实例化(可以以静态方式访问),并且您可以将new运算符和new运算符实例应用于另一个存储区中的类。

For example in a main class 例如在主班

public class Main {
    public static void main(String[] args) {

        /**
         * https://stackoverflow.com/questions/57581397/how-instantiating-an-inner-class-in-java-really-works
         *
         * @@@ New instance of Inner class
         */
        OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass();

        System.out.println(staticInnerClass.call());
        System.out.println(staticInnerClass.call());


        staticInnerClass = new OuterClass.StaticInnerClass();
        System.out.println("\n" + staticInnerClass.call());
        System.out.println(staticInnerClass.call());
    }
}

with output 带输出

// new of inner class and i = 0
innerclass.OuterClass$StaticInnerClass i=1
innerclass.OuterClass$StaticInnerClass i=2

// new of inner class and i = 0 
innerclass.OuterClass$StaticInnerClass i=1
innerclass.OuterClass$StaticInnerClass i=2

References: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html . 参考: https : //docs.oracle.com/javase/tutorial/java/javaOO/nested.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM