Общественный конструктор частного класса

Я новичок в Java. Я хочу знать, что такое использование публичного конструктора в частном классе. Частный класс внутри класса может быть инициализирован из одного и того же класса, а затем использовать его для создания конструктора частного класса?

public class MainActivity extends Activity {
     private class AcceptThread extends Thread {
        public AcceptThread() {

        }
    }
}

Ответы

Ответ 1

Кажется, что нет никаких реальных вариантов использования публичных или защищенных модификаторов с частными классами. Если у вас есть несколько классов в одном файле (но не вложенных или локальных), вам нужны не-частные конструкторы для создания экземпляров частных классов.

// X.java

public class X {
    private Y y = new Y();
}

class Y {
    Y () {
        // if this were private, X wouldn't be able to create an instance of Y
    }
}

Фактически, для создания экземпляра в этом случае было бы достаточно обычного или protected видимости. Все неличные модификаторы позволяют создавать экземпляры из других классов в одном пакете, но практически одинаковы.

  • Частный класс не виден для классов за пределами пакета, поэтому public методы здесь бесполезны.
  • Частный класс не может быть расширен за счет классов за пределами пакета, поэтому protected также не нужна.
  • Даже при использовании отражений публичный конструктор недоступен по умолчанию из других пакетов и будет IllegalAccessException. Сначала он проверяет видимость класса, а затем видимость элемента.

Модификатор по умолчанию является наиболее ограничивающим модификатором, который позволяет вам напрямую вызвать конструктор из других классов, поэтому пакет-частный, по-видимому, является наиболее подходящей видимостью для конструктора, а также любых других неличных методов. Это также имеет то преимущество, что если вы измените видимость класса в будущем, вы случайно не выставите публикующего конструктора или какие-либо методы.

Ответ 2

Вы знаете, я задаю себе этот вопрос почти каждый раз, когда я делаю частный внутренний класс, но я всегда предполагал, что может быть какая-то (возможно, изобретательная) причина для публичного конструктора. Поэтому ответ @kapep заставил меня покалывать и поощрять найти способы, чтобы требовать от публичного конструктора частного частного класса, но чем больше я думаю и экспериментирую с ним, тем больше я думаю, что дырки подключены.

Возможные углы, все из которых не помогли мне:

  • Сериализация: при отключении объекта, суперкласс которого не является сериализуемым, суперклассу нужен конструктор no-arg, доступный из подкласса. Поэтому protected должна быть всегда достаточной.

  • Отражающие инструменты: код, который использует отражение, чтобы получить внутренний конструктор класса через возвращаемый экземпляр. Ошибка, потому что видимость типа сначала проверяется, как указал @kapep, хотя он оставляет довольно интересное сообщение об ошибке:

    Исключение в потоке "main" java.lang.IllegalAccessException: класс A не может получить доступ к члену класса contrived.B $ C с модификаторами "public"

  • Внутреннее расширение класса shenanigans: не пытайтесь это дома:

    package a;
    class Outer {
      private class Inner {
      }
    }
    
    package b;
    // compile error: Outer.Inner has private access in Outer
    class Extender extends a.Outer.Inner {
      Extender(a.Outer outer) {
        outer.super();
      }
    }
    

    Сначала казалось перспективным, но я не зашел слишком далеко.


В конце концов, я не смог найти способ сделать публичный конструктор в частном внутреннем классе полезным.

Тогда почему это технически законно, несмотря на то, что это бесполезно? Вероятно, потому, что компилятор автоматически вставляет конструктор без аргумента arg, когда никакой другой конструктор не предоставляется. Следовательно, язык не должен запрещать эти конструкции. Однако больше артефакта, чем причина.