несколько классов в одном файле: модификатор private здесь не разрешен

Я не могу понять, почему этот код не компилируется:

class A {
    public static void main(String[] args) {
        System.out.println("hi");
    }
}

private class B {
    int a;
}

Я сохраняю содержимое в файл с именем A.java и получаю сообщение об ошибке:

modifier private not allowed here // where I have defined class B

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

Спасибо !


person Jaguar    schedule 16.08.2010    source источник
comment
Внутренние классы могут быть закрытыми.   -  person Konstantin Burov    schedule 16.08.2010
comment
Нет, вроде не зависит от А   -  person Jaguar    schedule 16.08.2010


Ответы (7)


Из спецификации языка Java:

Модификаторы доступа protected и private относятся только к классам-членам внутри непосредственно включающего объявления класса.

Так что да, модификаторы private и protected не разрешены для объявлений классов верхнего уровня.

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

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

На защищенный класс-член можно ссылаться (1) из любого класса того же пакета и из (2) любого подкласса включающего класса. Сопоставить эту концепцию с классами высшего уровня сложно. Первый случай покрывается классом верхнего уровня без модификаторов доступа. Второй случай неприменим для классов верхнего уровня, потому что нет вмещающего класса или чего-то еще из другого пакета с особым отношением к этому классу (типа подкласса). Из-за этого я думаю, что protected не разрешено, потому что его основная концепция неприменима для классов верхнего уровня.

person Andreas Dolk    schedule 16.08.2010
comment
Спасибо, Андреас, но не могли бы вы объяснить мне, почему разработчики Java могли наложить это ограничение? Я знаю, что этот вопрос может показаться абсурдным, но мне любопытно. Спасибо ! - person Jaguar; 16.08.2010
comment
ХОРОШО. Получил логику для привата, а как быть с защищенным?? «Защищено», безусловно, более открыто, чем спецификатор «по умолчанию», который был разрешен! - person Jaguar; 16.08.2010

Сделайте B вложенным в A, например:

class A {
    public static void main(String[] args) {
        System.out.println("hi");
    }

    private class B {
        int a;
    }
}

Или переместите B в отдельный файл. Также вы можете придерживаться уровня доступа по умолчанию, таким образом, доступ к классу возможен только из пакета:

class A {
    public static void main(String[] args) {
        System.out.println("hi");
    } 
}

class B {
    int a;
}
person Konstantin Burov    schedule 16.08.2010
comment
Я не хочу вкладываться или перемещаться в другой файл. Я просто хочу знать причину ошибки - person Jaguar; 16.08.2010
comment
Ошибка на самом деле очевидна. Если вы не сделаете это вложенным или отдельным файлом, класс не будет доступен ниоткуда, так как он приватный. Вы также не можете сделать его общедоступным, потому что у java есть ограничение на один общедоступный класс верхнего уровня для каждого файла. - person Konstantin Burov; 16.08.2010
comment
Protected не имеет смысла для классов верхнего уровня. Так как, если он имеет уровень доступа по умолчанию (модификатор не указан), он доступен внутри пакета, если общедоступный -- он также доступен снаружи пакета. Protected ничего не добавляет к этому. Кстати, я забыл заметить, что вы можете использовать уровень доступа по умолчанию. Смотрите обновление ответа. - person Konstantin Burov; 16.08.2010

private и protected бессмысленно разрешать доступ к классу/интерфейсу верхнего уровня (не члена).

Они применимы только к членам класса, которые могут быть переменными, константами, конструкторами, методами, классами и интерфейсами.

Почему:

(1) private: В чем может быть смысл/цель, если мы определяем класс как private. Его область действия должна быть приватной для некоторой области. доступ по умолчанию уже является частным пакетом. И никто не хочет, чтобы класс был закрытым исходным файлом (угадывая причину), это может быть не очень хорошей практикой программирования, потому что Java-приложения, наконец, организованы в виде пакетов, а не с точки зрения исходных файлов. Любой исходный файл должен быть частью некоторого пакета, поэтому в широком/финальном представлении каждый класс/интерфейс является частью некоторого пакета, а не только какого-либо файла .java. Так что не применимо.

(2) защищено: если что-то защищено, оно должно быть доступно только внутри пакета и только для подклассов в других пакетах. Чтобы расширить класс в другом пакете, он должен быть доступен для всех классов в других пакетах, но protected говорит, что класс должен быть доступен только для расширенных классов. Это своего рода тупиковая ситуация. Так что не применимо.

Источник: Мои чтения и понимание

person Venkataswamy    schedule 01.02.2014
comment
Пока он не является общедоступным, класс может иметь имя, отличное от имени его файла. Класс также может иметь основной метод. Файл класса будет создан с именем класса, но не с именем исходного файла. Имя класса должно использоваться для его выполнения. - person Venkataswamy; 07.02.2014

Просто не иметь модификатора private/protected вообще.

person djna    schedule 16.08.2010
comment
Я хотел сказать, что пробовал и приватный, и защищенный отдельно, но это не работает в обоих случаях. - person Jaguar; 16.08.2010
comment
Я просто экспериментирую с контролем доступа, я просто хочу знать причину ошибки. - person Jaguar; 16.08.2010

B должен быть приватным для чего-то. Поместите его в определение класса A или создайте другой файл, B.java, и определите его там, но тогда он не может быть частным.

person linuxuser27    schedule 16.08.2010
comment
Это правило в Java, чтобы сделать класс/переменную частной или защищенной от чего-то? Разве у нас нет отдельных классов/переменных, закрытых или защищенных? - person Jaguar; 16.08.2010
comment
Мое утверждение было скорее абстрактным, чем концептуальным. Основная проблема заключалась в том, что вы объявляли другой класс в файле A.java. Оказалось, что вы хотели сделать B приватным для A или внутри «чего-то». Однако ваше утверждение о том, можем ли мы иметь отдельные классы private или protected, на самом деле не имеет смысла, потому что модификаторы имеют контекст только тогда, когда они относятся к чему-то. - person linuxuser27; 16.08.2010

Если вы не используете ключевое слово public для класса, по умолчанию он будет закрытым (виден только в файле).

В файле .java может быть только один общедоступный класс, все остальные должны быть закрытыми. Таким образом, класс A может быть общедоступным, а класс B не нуждается в каких-либо модификаторах в вашем примере. Имя общедоступного класса должно совпадать с именем файла .java (например, A.java может содержать только один общедоступный класс с именем «A»).

person egbokul    schedule 16.08.2010
comment
Это неправильно. Класс верхнего уровня без модификатора является пакетом закрытым. На него можно ссылаться из любого класса в том же пакете. - person Andreas Dolk; 16.08.2010

A.java не может содержать два класса.

person fastcodejava    schedule 16.08.2010
comment
Да, это возможно, если только один из них является общедоступным (тот, который дает исходному файлу его имя), а все остальные не являются общедоступными (без модификатора доступа, доступного пакета), исходный файл может содержать несколько классов. - person Andrei Fierbinteanu; 16.08.2010