Почему я не могу объявить статические методы в интерфейсе?
97694 просмотра
14 ответа
Тема говорит о большей части - что является причиной того, что статические методы не могут быть объявлены в интерфейсе?
public interface ITest {
public static String test();
}
Приведенный выше код дает мне следующую ошибку (по крайней мере в Eclipse): «Недопустимый модификатор для метода интерфейса ITest.test (); разрешены только публичные и абстрактные».
Автор: Henrik Paul Источник Размещён: 17.05.2019 03:03Ответы (14)
85 плюса
Здесь есть несколько проблем. Во-первых, это проблема объявления статического метода без его определения. Это разница между
public interface Foo {
public static int bar();
}
а также
public interface Foo {
public static int bar() {
...
}
}
Первое невозможно по причинам, которые упоминает Эспо : вы не знаете, какой класс реализации является правильным определением.
Java может позволить последнее; и на самом деле, начиная с Java 8, это так!
Автор: James A. Rosen Размещён: 22.08.2008 02:2944 плюса
Причина, по которой у вас не может быть статического метода в интерфейсе, заключается в том, как Java разрешает статические ссылки. Java не будет беспокоиться о поиске экземпляра класса при попытке выполнить статический метод. Это связано с тем, что статические методы не зависят от экземпляра и, следовательно, могут выполняться прямо из файла класса. Учитывая, что все методы в интерфейсе являются абстрактными, ВМ должна была бы искать конкретную реализацию интерфейса, чтобы найти код, стоящий за статическим методом, чтобы он мог быть выполнен. Это противоречит принципу разрешения статических методов и может привести к несогласованности в языке.
Автор: Espo Размещён: 22.08.2008 05:2018 плюса
Я отвечу на ваш вопрос с примером. Предположим, у нас есть класс Math со статическим методом add. Вы бы назвали этот метод так:
Math.add(2, 3);
Если бы Math был интерфейсом вместо класса, он не мог бы иметь никаких определенных функций. Поэтому говорить что-то вроде Math.add (2, 3) бессмысленно.
Автор: Kyle Cronin Размещён: 22.08.2008 05:1911 плюса
Причина заключается в принципе дизайна, что Java не допускает множественного наследования. Проблема множественного наследования может быть проиллюстрирована на следующем примере:
public class A {
public method x() {...}
}
public class B {
public method x() {...}
}
public class C extends A, B { ... }
Что произойдет, если вы вызовете Cx ()? Будет ли выполнен Ax () или Bx ()? Каждый язык с множественным наследованием должен решить эту проблему.
Интерфейсы позволяют в Java своего рода ограниченное множественное наследование. Чтобы избежать проблемы, описанной выше, им не разрешено иметь методы. Если мы посмотрим на ту же проблему с интерфейсами и статическими методами:
public interface A {
public static method x() {...}
}
public interface B {
public static method x() {...}
}
public class C implements A, B { ... }
Та же проблема здесь, что произойдет, если вы вызываете Cx ()?
Автор: Mnementh Размещён: 26.09.2008 08:487 плюса
Статические методы не являются методами экземпляра. Там нет контекста экземпляра, поэтому реализовывать его из интерфейса имеет мало смысла.
Автор: Ryan Farley Размещён: 22.08.2008 05:185 плюса
Теперь Java8 позволяет нам определять даже статические методы в интерфейсе.
interface X {
static void foo() {
System.out.println("foo");
}
}
class Y implements X {
//...
}
public class Z {
public static void main(String[] args) {
X.foo();
// Y.foo(); // won't compile because foo() is a Static Method of X and not Y
}
}
Примечание: Методы в Интерфейсе по-прежнему являются публичными абстрактными по умолчанию, если мы явно не используем ключевые слова default / static, чтобы сделать их Методами по умолчанию и Статическими методами, соответственно.
Автор: Anandaraja_Srinivasan Размещён: 28.03.2014 11:194 плюса
Там очень хороший и лаконичный ответ на ваш вопрос здесь . (Это показалось мне настолько простым и понятным способом объяснить это, что я хочу связать это отсюда.)
Автор: Zarkonnen Размещён: 06.02.2009 12:193 плюса
Кажется, что статический метод в интерфейсе мог бы поддерживаться в Java 8 , ну, мое решение - просто определить их во внутреннем классе.
interface Foo {
// ...
class fn {
public static void func1(...) {
// ...
}
}
}
Эта же техника также может быть использована в аннотациях:
public @interface Foo {
String value();
class fn {
public static String getValue(Object obj) {
Foo foo = obj.getClass().getAnnotation(Foo.class);
return foo == null ? null : foo.value();
}
}
}
Внутренний класс всегда должен быть доступен в форме, Interface.fn...
вместо того Class.fn...
, чтобы избавиться от неоднозначной проблемы.
2 плюса
Интерфейс используется для полиморфизма, который применяется к объектам, а не к типам. Поэтому (как уже отмечалось) нет смысла иметь статический элемент интерфейса.
Автор: Rob Cooper Размещён: 22.08.2008 05:271 плюс
Java 8 Изменил мир, вы можете иметь статические методы в интерфейсе, но это заставляет вас обеспечивать реализацию для этого.
public interface StaticMethodInterface {
public static int testStaticMethod() {
return 0;
}
/**
* Illegal combination of modifiers for the interface method
* testStaticMethod; only one of abstract, default, or static permitted
*
* @param i
* @return
*/
// public static abstract int testStaticMethod(float i);
default int testNonStaticMethod() {
return 1;
}
/**
* Without implementation.
*
* @param i
* @return
*/
int testNonStaticMethod(float i);
}
Автор: Kumar Abhishek Размещён: 05.02.2016 09:490 плюса
Недопустимая комбинация модификаторов: статические и абстрактные
Если член класса объявлен как статический, его можно использовать с именем класса, которое ограничено этим классом, без создания объекта.
Если член класса объявлен как абстрактный, вам нужно объявить класс абстрактным и предоставить реализацию абстрактного члена в его унаследованном классе (подклассе).
Вам необходимо предоставить реализацию абстрактному члену класса в подклассе, где вы собираетесь изменить поведение статического метода, также объявленного как абстрактный, который ограничен базовым классом, что не является правильным
Автор: Sankar Размещён: 02.10.2013 10:320 плюса
Так как статические методы не могут быть унаследованы. Так что нет смысла помещать его в интерфейс. Интерфейс - это контракт, которому должны следовать все его подписчики. Размещение статического метода в интерфейсе заставит подписчиков реализовать его. что теперь становится противоречащим факту, что статические методы не могут быть унаследованы.
Автор: ip_x Размещён: 15.12.2013 05:000 плюса
В Java 8 интерфейсы теперь могут иметь статические методы.
Например, у Comparator есть статический метод naturalOrder ().
Требование, чтобы интерфейсы не могли иметь реализации, также было смягчено. Интерфейсы теперь могут объявлять реализации метода «по умолчанию», которые похожи на обычные реализации с одним исключением: если вы наследуете и реализацию по умолчанию от интерфейса, и обычную реализацию от суперкласса, реализация суперкласса всегда будет иметь приоритет.
Автор: Ishara Размещён: 21.02.2019 11:20-2 плюса
Возможно, пример кода поможет, я собираюсь использовать C #, но вы должны быть в состоянии следовать.
Давайте представим, что у нас есть интерфейс под названием IPayable
public interface IPayable
{
public Pay(double amount);
}
Теперь у нас есть два конкретных класса, которые реализуют этот интерфейс:
public class BusinessAccount : IPayable
{
public void Pay(double amount)
{
//Logic
}
}
public class CustomerAccount : IPayable
{
public void Pay(double amount)
{
//Logic
}
}
Теперь давайте представим, что у нас есть коллекция различных учетных записей, для этого мы будем использовать общий список типа IPayable
List<IPayable> accountsToPay = new List<IPayable>();
accountsToPay.add(new CustomerAccount());
accountsToPay.add(new BusinessAccount());
Теперь мы хотим заплатить $ 50,00 на все эти счета:
foreach (IPayable account in accountsToPay)
{
account.Pay(50.00);
}
Итак, теперь вы видите, как интерфейсы невероятно полезны.
Они используются только для созданных объектов. Не на статических классах.
Если бы вы сделали статическую оплату, при циклическом просмотре списка IPayable в accountsToPay не было бы способа выяснить, следует ли вызывать pay на BusinessAcount или CustomerAccount.
Автор: FlySwat Размещён: 22.08.2008 05:35Вопросы из категории :
- java В чем разница между int и Integer в Java и C #?
- java Как я могу определить IP моего маршрутизатора / шлюза в Java?
- java Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?
- java Как округлить результат целочисленного деления?
- java Преобразование списка <Integer> в список <String>
- interface Почему я не могу объявить статические методы в интерфейсе?
- interface Интерфейс против Базового класса
- interface Разница между интерфейсами Runnable и Callable в Java
- interface Должны ли методы в интерфейсе Java быть объявлены с модификатором открытого доступа или без него?
- interface Множественное наследование в C #
- methods Является ли Java «передачей по ссылке» или «передачей по значению»?
- methods Регулярное выражение, которое будет соответствовать объявлению метода Java
- methods Как получить переменные экземпляра в Python?
- methods В чем разница между @staticmethod и @classmethod?
- static Возможны ли статические переменные класса?
- static Почему основной метод Java статичен?
- static Неразрешенный внешний символ на статических членах класса
- static What is the lifetime of a static variable in a C++ function?