Java новое ключевое слово со стати c внутренний класс - PullRequest
2 голосов
/ 06 апреля 2020

Я знаю, что эти вопросы задавались ранее, но в основном довольно специфично c относительно определенной библиотеки. И данные ответы на самом деле не объясняли мне, что происходило.

Вот почему я создал довольно простой тестовый сценарий и попытался поиграть с ним, но все еще есть некоторые знаки вопроса! Онлайн Java Пример

Простой код состоит из двух файлов:

Main.java

public class Main
{
    public static void main(String[] args) {
        // this works, and inner1 and inner2 seem to be new instances
        Outer.Inner inner1 = new Outer.Inner();
        Outer.Inner inner2 = new Outer.Inner();
        inner1.setName("Mario");
        inner1.say();
        inner2.setName("Luigi");
        inner2.say();

        // if Inner is not a public static class this gives this error:
        // error: an enclosing instance that contains Outer.InnerNoStatic is required
        Outer.InnerNoStatic inner3 = new Outer.InnerNoStatic();
    }
}

Outer.java

public class Outer {
    public static class Inner {
        private String name;

        public void say() {
            System.out.println("Hi " + name);
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public class InnerNoStatic {
        public void say() {
            System.out.println("Hi from InnerNoStatic");
        }
    }
}

Так что, похоже, что даже если класс Inner объявлен с помощью stati c, мы создаем два новых экземпляра с именами inner1 и inner2. Почему это называется stati c тогда?

И, в свою очередь, если я удалю stati c, как в InnerNoStatic, как мне go узнать о получении экземпляра этого класса?

Ответы [ 4 ]

1 голос
/ 06 апреля 2020

Non-stati c внутренние классы всегда имеют ссылку на соответствующий внешний класс. В результате такой класс может быть создан только классом Outer.

Напротив, внутренний класс stati c не имеет ссылки на класс Outer и может быть создан любым другим объектом, если это позволяет видимость. Это очень похоже на поведение методов stati c, которые не требуют вызова экземпляра объекта.

1 голос
/ 06 апреля 2020

Таким образом, кажется, что даже несмотря на то, что класс Inner объявлен с stati c, мы создаем два новых экземпляра, называемых inner1 и inner2. Почему тогда это называется stati c?

static подразумевает большую независимость для вложенного класса. Он предназначен главным образом для увеличения инкапсуляции, читабельности, удобства обслуживания и является хорошим способом логически группировать классы.

И, в свою очередь, если я удалю данные c, как в InnerNoStati c, как мне go узнать о получении экземпляра этого класса?

Синтаксис немного отличается, потому что вам нужен экземпляр Outer.

Outer.InnerNoStatic inner3 = new Outer(). new InnerNoStatic();
1 голос
/ 06 апреля 2020

static здесь диктует, как Inner и InnerNoStatic используются по отношению к Outer.

Поскольку Inner является c в Outer, оно не привязано к любой конкретный c экземпляр Outer (как всегда, член stati c принадлежит классу, а не какому-либо конкретному экземпляру этого класса). Это объясняет, как это компилируется:

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

InnerNoStatic, однако, является членом экземпляра (вот что: если он не stati c, он привязан к данному члену). И это объясняет, почему компилятор вызывает ошибку здесь:

Outer.InnerNoStatic inner3 = new Outer.InnerNoStatic();

Поскольку InnerNoStatic должен быть привязан к экземпляру Outer, вам нужно использовать такой экземпляр для создания inner3:

Outer.InnerNoStatic inner3 = new Outer().new InnerNoStatic(); //note the calls

Вы также можете использовать существующий экземпляр.

Outer outer = new Outer();
Outer.InnerNoStatic inner3 = outer.new InnerNoStatic();

В обоих этих случаях экземпляр Outer используется для создания экземпляра InnerNoStatic (просто нет переменной, указывающей к объекту Outer, созданному с помощью new Outer().new InnerNoStatic())


Примечание: new Outer.Inner(); легко спутать с new Outer().new Inner();. Это не одно и то же (в первом случае «Outer» в основном играет роль пространства имен, тогда как во втором new Outer() создает объект Outer). То есть один вызов конструктора (Inner()) в первом, но два вызова конструктора во втором (Outer() и Inner()).

1 голос
/ 06 апреля 2020

Так что, похоже, что даже несмотря на то, что класс Inner объявлен с stati c, мы создаем два новых экземпляра, называемых inner1 и inner2. Почему тогда он называется stati c?

Объекты внутреннего класса "stati c" не привязаны к объектам его окружающего класса, в отличие от не "stati c" внутренние классы. Наличие внутреннего класса «stati c» вместо перемещения этого класса на «верхний уровень» является удобным способом сигнализации пользователю о том, что объекты этого внутреннего класса практически не используются отдельно от внешнего класса, как, например, Map.Entry.

И, в свою очередь, если я удалю данные c, как в InnerNoStati c, как мне go получить экземпляр этого класса?

Например

public class Outer {

  private InnerNoStatic innerNoStatic = new InnerNoStatic();

  public InnerNoStatic getInnerNoStatic () {
    return innerNoStatic;
  }
  // ...

и

Outer.InnerNoStatic innerNoStatic = new Outer().getInnerNoStatic();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...