«Язык программирования Java предоставляет механизмы для управления доступом, чтобы предотвратить зависимость пользователей пакета или класса от ненужных деталей реализации этого пакета или класса».
Контроль доступа - это скрытие деталей реализации. Интерфейс не имеет реализации, которую нужно скрывать.
«Это очень неправильно» ... как всегда, зависит от контекста.
JacksOnF1re
5
Это не так уж плохо, как кажется. Частные методы в интерфейсе могут быть доступны только методами по умолчанию в том же интерфейсе. Одно из преимуществ - помочь разбить реализацию методов по умолчанию на значимые более мелкие функции без нарушения инкапсуляции.
@SebiSebi, момент, когда осознаешь, что Java - это живой язык.
Arashsoft
@Arashsoft, OP запрашивает поля.
Pacerier
19
Методы частного интерфейса являются частью Java 9 как часть JEP-213 . Поскольку интерфейсы в Java 8 могут иметь методы по умолчанию , частные методы позволяют нескольким методам по умолчанию использовать общий частный метод.
Начиная с Java 8, интерфейсы могут иметь методы по умолчанию, а с Java 9 интерфейс может иметь частные методы, к которым можно получить доступ только с помощью методов по умолчанию в том же интерфейсе.
Интерфейс используется для описания API, который предоставляется любым классом, реализующим интерфейс. Поскольку интерфейс из его определения не имеет состояния, в нем нет смысла объявлять элементы поля.
В мире Java член - это поле, метод, конструктор или класс.
emory
7
Реализовать такой интерфейс было бы невозможно. Ответ на заданный мною вопрос убедительно свидетельствует о том, что было бы невозможно (без радикального изменения правил) реализовать интерфейс с частными методами - это оставляет открытым вопрос о том, почему защищенные и пакетные частные методы не разрешены.
classOuterClass{
voidrun( MyInterface x ){
x . publicMethod ( ) ; // why not?
x . protectedMethod ( ) ; // why not?
x . packagePrivateMethod ( ) ; // why not?
x . privateMethod ( ) ; // why not?
}
interfaceMyInterface{
publicabstractvoidpublicMethod( ); // OKprotectedabstractvoidprotectedMethod( ); // why not?abstractvoidpackagePrivateMethod( ); // in interface default is public, but why not package privateprivatevoidprivateMethod( ); // impossible to implement
}
classMyImplimplementsMyInterface{
publicvoidpublicMethod( ){ } // okprotectedvoidprotectedMethod( ){ } // no sweatvoidpackagePrivateMethod( ){ } // no sweatprivatevoidprivateMethod( ){ } // not happening
}
}
Приведенный ниже код должен достичь желаемого результата. Несмотря на то, что все методы являются общедоступными, только общедоступный метод фактически является общедоступным. Защищенный метод эффективно защищен. packagePrivateMethod фактически является packagePrivate. privateMethod фактически является частным.
classWorkAround{
voidrun( MyPrivateInterface x ){
x . publicMethod ( ) ;
x . protectedMethod ( ) ;
x . packagePrivateMethod ( ) ;
x . privateMethod ( ) ;
}
publicinterfaceMyPublicInterface{ voidpublicMethod( ); }
protectedinterfaceMyProtectedInterfaceextendsMyPublicInterface{ voidprotectedMethod( ); }
interfaceMyPackagePrivateInterfaceextendsMyProtectedInterface{ voidpackagePrivateMethod( ); }
privateinterfaceMyPrivateInterfaceextendsMyPackagePrivateInterface{ voidprivateMethod( ); }
}
В соответствии с Javaязыком программирования область действия private membersограничена тем, classв котором он объявлен, и может быть доступна только с помощью методов этого class. Но intefaceне имеет тела метода, поэтому нет смысла объявлять закрытые члены внутри interface.
Java разрешает частные методы в интерфейсе в Java 9 . Эти стандартные методы были введены в Java 8. Вполне возможно , что несколько методов по умолчанию хотят поделиться каким - то кодом, то этот код может быть перемещен в частный метод , не подвергая его внешний мир. Эта ошибка была исправлена, и начиная с JDK 9 build 54, компилятор возродил поддержку методов частного интерфейса.
publicinterfaceIData{
defaultvoidprocessData(int data){
validate(data);
// do some work with it
}
defaultvoidconsumeData(int data){
validate(data);
// do some work with it
}
privatevoidvalidate(int data){
// validate data
}
}
Рассмотрим стандартные методы java 8. Интерфейс I имеет методы A и B по умолчанию с большим количеством общего кода. Для рефакторинга вам нужен метод C, который будет содержать только общий код и вызываться A и B. В Java 8 это будет метод по умолчанию, который доступен всем разработчикам интерфейса. в Java 9 C может быть частным методом, видимым только для методов по умолчанию в I.
Иван Крылов
2
частные поля не были бы полностью бесполезными, поскольку другие поля и внутренние классы могли бы получить к ним доступ.
Однако частные методы не могли быть реализованы даже во вложенных классах, что делало их почти бесполезными. Вы можете прочитать их, используя отражение, но это скорее крайний случай.
Частные члены не имеют смысла в интерфейсе. Интерфейс - это способ доступа к классу с помощью определенных методов, в которых вам не нужно видеть внутренние компоненты этого класса.
Члены класса, объявленные закрытыми, не наследуются подклассами этого класса. Только члены класса, объявленные защищенными или общедоступными, наследуются подклассами, объявленными в пакете, отличном от того, в котором объявлен класс.
Ага, не могу. Для всех, кто комментирует, почему этого не следует делать:
Представьте, что у меня есть класс A, который использует интерфейс I. Класс B расширяет класс A, поэтому также наследует все методы интерфейса в A.
Теперь представьте, что мне нужен частный метод в классе A, но я хочу, чтобы он был определен в контракте и для других классов (возможно, класс C, который не обязательно расширяет класс B или A).
Возможно, для метода «инициализации», который мне нужен для всех классов, использующих интерфейс I. Но, очевидно, я не хочу, чтобы метод инициализации был общедоступным ... поскольку его следует использовать только один раз или по мере необходимости, а не только потому, что вы хотите использовать его все волей-неволей.
Единственное решение - это обходной путь или просто принудительное использование метода init в самих классах без интерфейса.
Я не слишком понимаю причину, но все же иногда может пригодиться. Очевидно, Oracle соглашается, поскольку они разрешают методы частного интерфейса в JDK 9.
То, что я сделал, в любом случае для себя, заключалось в том, что я поместил простую логическую переменную, таким образом, метод интерфейса (который должен быть частным) может быть помечен как истинный (инициализированный = истинный) после того, как был установлен один раз. Затем при повторном вызове метод просто ничего не делает. Таким образом, метод интерфейса может быть реализован как общедоступный, но поскольку конструктор (моего класса) сначала вызывает метод, он устанавливает для переменной значение true, и поэтому он не может быть вызван снова.
В противном случае вам придется попробовать другой обходной путь, если вы хотите, чтобы его использовали только внутренние механизмы класса ... возможно, сам метод устанавливает и выключает флаг, когда он его использует. Когда флаг установлен в false, метод ничего не делает (это может быть, когда кто-то вызывает его извне класса). Однако, когда его вызывают собственные методы классов, они быстро устанавливают флаг в значение true, затем вызывают метод, а затем устанавливают флаг в значение false ??
В конце концов вроде немой. Возможно, сейчас лучше просто поместить частный класс в сам класс и вообще вырезать интерфейс.
Ответы:
Из спецификации языка Java, (Контроль доступа) :
Контроль доступа - это скрытие деталей реализации. Интерфейс не имеет реализации, которую нужно скрывать.
источник
В Java 9 возможны частные методы в интерфейсах.
Спецификации Java 9
источник
Методы частного интерфейса являются частью Java 9 как часть JEP-213 . Поскольку интерфейсы в Java 8 могут иметь методы по умолчанию , частные методы позволяют нескольким методам по умолчанию использовать общий частный метод.
источник
Начиная с Java 8, интерфейсы могут иметь методы по умолчанию, а с Java 9 интерфейс может иметь частные методы, к которым можно получить доступ только с помощью методов по умолчанию в том же интерфейсе.
источник
Интерфейс используется для описания API, который предоставляется любым классом, реализующим интерфейс. Поскольку интерфейс из его определения не имеет состояния, в нем нет смысла объявлять элементы поля.
источник
Реализовать такой интерфейс было бы невозможно. Ответ на заданный мною вопрос убедительно свидетельствует о том, что было бы невозможно (без радикального изменения правил) реализовать интерфейс с частными методами - это оставляет открытым вопрос о том, почему защищенные и пакетные частные методы не разрешены.
class OuterClass { void run ( MyInterface x ) { x . publicMethod ( ) ; // why not? x . protectedMethod ( ) ; // why not? x . packagePrivateMethod ( ) ; // why not? x . privateMethod ( ) ; // why not? } interface MyInterface { public abstract void publicMethod ( ) ; // OK protected abstract void protectedMethod ( ) ; // why not? abstract void packagePrivateMethod ( ) ; // in interface default is public, but why not package private private void privateMethod ( ) ; // impossible to implement } class MyImpl implements MyInterface { public void publicMethod ( ) { } // ok protected void protectedMethod ( ) { } // no sweat void packagePrivateMethod ( ) { } // no sweat private void privateMethod ( ) { } // not happening } }
Приведенный ниже код должен достичь желаемого результата. Несмотря на то, что все методы являются общедоступными, только общедоступный метод фактически является общедоступным. Защищенный метод эффективно защищен. packagePrivateMethod фактически является packagePrivate. privateMethod фактически является частным.
class WorkAround { void run ( MyPrivateInterface x ) { x . publicMethod ( ) ; x . protectedMethod ( ) ; x . packagePrivateMethod ( ) ; x . privateMethod ( ) ; } public interface MyPublicInterface { void publicMethod ( ) ; } protected interface MyProtectedInterface extends MyPublicInterface { void protectedMethod ( ) ; } interface MyPackagePrivateInterface extends MyProtectedInterface { void packagePrivateMethod ( ) ; } private interface MyPrivateInterface extends MyPackagePrivateInterface { void privateMethod ( ) ; } }
источник
В соответствии с
Java
языком программирования область действияprivate members
ограничена тем,class
в котором он объявлен, и может быть доступна только с помощью методов этогоclass
. Ноinteface
не имеет тела метода, поэтому нет смысла объявлять закрытые члены внутриinterface
.источник
Java разрешает частные методы в интерфейсе в Java 9 . Эти стандартные методы были введены в Java 8. Вполне возможно , что несколько методов по умолчанию хотят поделиться каким - то кодом, то этот код может быть перемещен в частный метод , не подвергая его внешний мир. Эта ошибка была исправлена, и начиная с JDK 9 build 54, компилятор возродил поддержку методов частного интерфейса.
public interface IData{ default void processData(int data) { validate(data); // do some work with it } default void consumeData(int data) { validate(data); // do some work with it } private void validate(int data) { // validate data } }
источник
Потому что они были бы бесполезны.
Не было бы возможности вызвать частный метод.
Частные члены - это деталь реализации. Интерфейс касается публичной роли, которую может взять на себя класс.
источник
частные поля не были бы полностью бесполезными, поскольку другие поля и внутренние классы могли бы получить к ним доступ.
Однако частные методы не могли быть реализованы даже во вложенных классах, что делало их почти бесполезными. Вы можете прочитать их, используя отражение, но это скорее крайний случай.
источник
Частные члены не имеют смысла в интерфейсе. Интерфейс - это способ доступа к классу с помощью определенных методов, в которых вам не нужно видеть внутренние компоненты этого класса.
Частные участники не согласны с этим.
источник
Источник
Итак, у вас нет рабочих методов в интерфейсе, которые могут работать с этим частным ненаследуемым полем. Тогда почему оно должно существовать?
источник
Ага, не могу. Для всех, кто комментирует, почему этого не следует делать:
Представьте, что у меня есть класс A, который использует интерфейс I. Класс B расширяет класс A, поэтому также наследует все методы интерфейса в A.
Теперь представьте, что мне нужен частный метод в классе A, но я хочу, чтобы он был определен в контракте и для других классов (возможно, класс C, который не обязательно расширяет класс B или A).
Возможно, для метода «инициализации», который мне нужен для всех классов, использующих интерфейс I. Но, очевидно, я не хочу, чтобы метод инициализации был общедоступным ... поскольку его следует использовать только один раз или по мере необходимости, а не только потому, что вы хотите использовать его все волей-неволей.
Единственное решение - это обходной путь или просто принудительное использование метода init в самих классах без интерфейса.
Я не слишком понимаю причину, но все же иногда может пригодиться. Очевидно, Oracle соглашается, поскольку они разрешают методы частного интерфейса в JDK 9.
То, что я сделал, в любом случае для себя, заключалось в том, что я поместил простую логическую переменную, таким образом, метод интерфейса (который должен быть частным) может быть помечен как истинный (инициализированный = истинный) после того, как был установлен один раз. Затем при повторном вызове метод просто ничего не делает. Таким образом, метод интерфейса может быть реализован как общедоступный, но поскольку конструктор (моего класса) сначала вызывает метод, он устанавливает для переменной значение true, и поэтому он не может быть вызван снова.
В противном случае вам придется попробовать другой обходной путь, если вы хотите, чтобы его использовали только внутренние механизмы класса ... возможно, сам метод устанавливает и выключает флаг, когда он его использует. Когда флаг установлен в false, метод ничего не делает (это может быть, когда кто-то вызывает его извне класса). Однако, когда его вызывают собственные методы классов, они быстро устанавливают флаг в значение true, затем вызывают метод, а затем устанавливают флаг в значение false ??
В конце концов вроде немой. Возможно, сейчас лучше просто поместить частный класс в сам класс и вообще вырезать интерфейс.
источник