Подтвердить что ты не робот

Частный класс как возвращаемый тип из общедоступного метода

Почему это действительно?

Foo.java

public class Foo {

    public Bar getBar() {
        return new Bar();
    }

    private class Bar {}

}

Если Bar является приватным, как пользователи этого класса используют этот метод? Полиморфизм может быть использован, конечно, но не должно ли это быть недопустимым, и декларация должна указывать это как возвращение объекта?

4b9b3361

Ответ 1

Я только что немного поработал над этим и не смог найти окончательного ответа. Похоже, что это просто надзор со стороны разработчиков языка Java, и поскольку на самом деле он не наносит никакого вреда, он остался. Не похоже на то, чтобы поместить метод public в класс private. Ничто не мешает вам это делать, хотя нет никакого способа получить доступ к этому методу public.

Конечно, NetBeans дает вам предупреждение "Экспорт непубличного типа через открытый API" при попытке сделать это. Я ожидаю, что большинство других сред даст аналогичное предупреждение.

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

Вы могли бы захотеть сделать это, если переданный Object используется как "дескриптор", который передается, но не работает. В этом случае, хотя для класса public было бы гораздо разумнее использовать все методы private, чтобы предотвратить их действие вне вашего класса (или определить интерфейс public для возврата и иметь private реализует класс).

Итак, ответ кажется:

Вероятно, он не должен быть прав, но поскольку он не наносит никакого вреда, он никогда не блокировался.

Здесь есть хороший ответ по аналогичной теме:

Экспорт непубличного типа через общедоступный API

Ответ 2

Почему это действительно?

Поскольку клиентский код в месте вызова может ожидать Object (или вообще ничего не ожидающего), нет никакой проблемы с вызовом этого метода из любой точки:

Object o = new Foo().getBar();

Ответ 3

public class Foo {

    private String myString;

    public String getMyString() {
        return myString;
    }

}

Это также верно. Почему внутренние классы ведут себя по-другому?

Создание Bar private делает его невидимым для внешнего мира так же, как создание полей private.

Одно важное предостережение состоит в том, что даже если вы можете вызвать getBar() на объект Foo, вы не можете вызывать методы этой ссылки (из-за видимости).

Итак, главное, что вы можете сделать это, но вы не должны делать это.

Единственная ситуация, которую я могу себе представить, - это когда Foo также является внутренним классом, а внешний класс Foo хочет использовать Bar.

Ответ 4

Он действителен, потому что Bar отображается классу Foo. Таким образом, он компилируется.

Конечно, другой класс не может видеть Bar и, следовательно, не может использовать возвращаемое значение.

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

public class FooBar {

   public void invokeBar() {
        Foo foo = new Foo();
        foo.getBar();
   }
}

Ответ 5

Открытый метод, возвращающий закрытый класс, может быть полезен, поэтому вам нужно будет вызывать метод из любой области (например, для изменения внутреннего состояния Foo) и для внутреннего использования, если вам нужен какой-либо результат в дополнение просто вызвать метод.

Ответ 6

Внутренний класс

Внутренние классы представляют особый тип отношений, который может иметь доступ ко всем членам (членам данных и методам) внешнего класса, включая private. Вложенные классы могут привести к более читабельному и поддерживаемому коду, поскольку он логически группирует классы только в одном месте.

Ответ 7

Это одна из форм вложенных типов. Такое объявление класса называется внутренним классом. Если вы объявите внутренний класс статичным, то он будет известен как вложенный класс верхнего уровня. Другие формы вложенных типов, доступные в Java, - это локальный класс; класс, объявленный и определенный внутри блока, то есть метод или конструктор или блок инициализатора. Четвертая форма вложенного типа - анонимный класс; класс без какого-либо имени, объект которого используется, когда класс определен.

Что касается вашего случая, то есть внутреннего класса, все классы внутри класса могут быть объявлены с помощью общих, частных и защищенных спецификаций доступа. Все классы с включенным классом, а также с окружающим классом разделяют доверительные отношения. Это означает, что все частные члены внутреннего класса, а также частные члены окружающего класса разделяются между собой. Однако вы не можете получить доступ к объекту внутреннего класса без объекта включения класса.

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

class Bar {
    private static int x;

    public void getFoo() {
        System.out.println(new Foo().y);
    }

    private class Foo {
        private int y;
        public void getBar() {
            System.out.println(Bar.x);
        }
    }
}

public class Test{
    public static void main(String[] a) {
        Bar b = new Bar();
        //Bar.Foo f = new Bar.Foo(); This is completely illegal syntax.     
    }
}

Лучший пример, который может иметь для внутреннего класса, - это отношение класса Accounts, которое включает класс и класс Transaction, который является внутренним классом. Один класс Accounts может иметь более одного объекта Transaction, но объект Transaction не может существовать без объекта Accounts.

Хотя возвращение объекта частного внутреннего класса бесполезно, поскольку оно становится невидимым вне его класса. Как объясняется вышеприведенный пример классов Accounts и Transaction. Transaction не может существовать без объекта Accounts.