Вопрос:

Почему я не могу объявить статические методы в интерфейсе?

java interface methods static

97694 просмотра

14 ответа

43229 Репутация автора

Тема говорит о большей части - что является причиной того, что статические методы не могут быть объявлены в интерфейсе?

public interface ITest {
    public static String test();
}

Приведенный выше код дает мне следующую ошибку (по крайней мере в Eclipse): «Недопустимый модификатор для метода интерфейса ITest.test (); разрешены только публичные и абстрактные».

Автор: Henrik Paul Источник Размещён: 22.08.2008 05:16

Ответы (14)


7 плюса

10465 Репутация автора

Статические методы не являются методами экземпляра. Там нет контекста экземпляра, поэтому реализовывать его из интерфейса имеет мало смысла.

Автор: Ryan Farley Размещён: 22.08.2008 05:18

18 плюса

59149 Репутация автора

Я отвечу на ваш вопрос с примером. Предположим, у нас есть класс Math со статическим методом add. Вы бы назвали этот метод так:

Math.add(2, 3);

Если бы Math был интерфейсом вместо класса, он не мог бы иметь никаких определенных функций. Поэтому говорить что-то вроде Math.add (2, 3) бессмысленно.

Автор: Kyle Cronin Размещён: 22.08.2008 05:19

44 плюса

34322 Репутация автора

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

Автор: Espo Размещён: 22.08.2008 05:20

2 плюса

21187 Репутация автора

Интерфейс используется для полиморфизма, который применяется к объектам, а не к типам. Поэтому (как уже отмечалось) нет смысла иметь статический элемент интерфейса.

Автор: Rob Cooper Размещён: 22.08.2008 05:27

-2 плюса

114192 Репутация автора

Возможно, пример кода поможет, я собираюсь использовать 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

85 плюса

38215 Репутация автора

Решение

Здесь есть несколько проблем. Во-первых, это проблема объявления статического метода без его определения. Это разница между

public interface Foo {
  public static int bar();
}

а также

public interface Foo {
  public static int bar() {
    ...
  }
}

Первое невозможно по причинам, которые упоминает Эспо : вы не знаете, какой класс реализации является правильным определением.

Java может позволить последнее; и на самом деле, начиная с Java 8, это так!

Автор: James A. Rosen Размещён: 22.08.2008 02:29

11 плюса

30956 Репутация автора

Причина заключается в принципе дизайна, что 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:48

4 плюса

18110 Репутация автора

Там очень хороший и лаконичный ответ на ваш вопрос здесь . (Это показалось мне настолько простым и понятным способом объяснить это, что я хочу связать это отсюда.)

Автор: Zarkonnen Размещён: 06.02.2009 12:19

3 плюса

6344 Репутация автора

Кажется, что статический метод в интерфейсе мог бы поддерживаться в 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..., чтобы избавиться от неоднозначной проблемы.

Автор: Xiè Jìléi Размещён: 17.09.2013 04:09

0 плюса

129 Репутация автора

Недопустимая комбинация модификаторов: статические и абстрактные

Если член класса объявлен как статический, его можно использовать с именем класса, которое ограничено этим классом, без создания объекта.

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

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

Автор: Sankar Размещён: 02.10.2013 10:32

0 плюса

182 Репутация автора

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

Автор: ip_x Размещён: 15.12.2013 05:00

5 плюса

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:19

1 плюс

1408 Репутация автора

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:49

0 плюса

4 Репутация автора

В Java 8 интерфейсы теперь могут иметь статические методы.

Например, у Comparator есть статический метод naturalOrder ().

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

Автор: Ishara Размещён: 21.02.2019 11:20
Вопросы из категории :
32x32