Сведения о вопросе

HEIGTH

15:51, 6th August, 2020

Теги

java   interface   methods   static    

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

Просмотров: 716   Ответов: 14

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

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

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



  Сведения об ответе

darknet

14:55, 29th August, 2020

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

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

и

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

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

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


  Сведения об ответе

repe

03:01, 19th August, 2020

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


  Сведения об ответе

PAGE

10:12, 18th August, 2020

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

Math.add(2, 3);

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


  Сведения об ответе

FAriza

03:45, 4th August, 2020

Причина кроется в принципе проектирования, что java не допускает множественного наследования. Проблему с множественным наследованием можно проиллюстрировать следующим примером:

public class A {
   public method x() {...}
}
public class B {
   public method x() {...}
}
public class C extends A, B { ... }

А что будет, если вы позвоните C.x()? Будет ли выполнено A.x() или B.x()? Каждый язык с множественным наследованием должен решить эту проблему.

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

public interface A {
   public static method x() {...}
}
public interface B {
   public static method x() {...}
}
public class C implements A, B { ... }

Та же проблема здесь, что произойдет, если вы вызовете C.x()?


  Сведения об ответе

PAGE

21:36, 15th August, 2020

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


  Сведения об ответе

screen

04:58, 23rd August, 2020

Теперь 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, чтобы сделать их методами по умолчанию и статическими методами соответственно.


  Сведения об ответе

ASSembler

13:14, 17th August, 2020

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


  Сведения об ответе

VERSUION

15:57, 5th August, 2020

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


  Сведения об ответе

dump

22:17, 25th August, 2020

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


  Сведения об ответе

dump

00:22, 15th August, 2020

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);
}


  Сведения об ответе

dumai

08:28, 22nd August, 2020

Незаконное сочетание модификаторов: статических и абстрактных

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

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

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


  Сведения об ответе

park

00:26, 1st August, 2020

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


  Сведения об ответе

dumai

18:57, 18th August, 2020

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

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

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


  Сведения об ответе

KOMP

12:23, 20th August, 2020

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

Итак, теперь вы видите, как невероятно полезны интерфейсы.

Они используются только для создания экземпляров объектов. Только не на статических классах.

Если бы вы сделали pay статическим, то при циклическом просмотре IPayable в accountsToPay не было бы никакого способа выяснить, должен ли он вызывать pay на BusinessAcount или CustomerAccount.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться