Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
895
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4351
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Почему я не могу объявить статические методы в интерфейсе?
Тема говорит больше всего - в чем причина того, что статические методы не могут быть объявлены в интерфейсе?
public interface ITest {
public static String test();
}
Приведенный выше код выдает мне следующую ошибку (по крайней мере, в Eclipse): "недопустимый модификатор для метода интерфейса ITest.test(); разрешены только публичные & абстрактные".
Здесь есть несколько вопросов, которые играют свою роль. Первый - это проблема объявления статического метода без его определения. В этом и заключается разница между
public interface Foo {
public static int bar();
}
и
public interface Foo {
public static int bar() {
...
}
}
Первое невозможно по причинам, которые упоминает Espo : вы не знаете, какой класс реализации является правильным определением.
Java может позволить последнее; и в самом деле, начиная с Java8, это действительно так!
Причина, по которой вы не можете иметь статический метод в интерфейсе, заключается в том, как Java разрешает статические ссылки. Java не будет утруждать себя поиском экземпляра класса при попытке выполнения статического метода. Это происходит потому, что статические методы не зависят от экземпляра и, следовательно, могут быть выполнены прямо из файла класса. Учитывая, что все методы в интерфейсе абстрактны, VM должен был бы искать конкретную реализацию интерфейса, чтобы найти код позади статического метода, чтобы он мог быть выполнен. Это тогда противоречит тому, как работает разрешение статического метода, и внесло бы непоследовательность в язык.
Я отвечу на ваш вопрос примером. Предположим, у нас есть математический класс со статическим методом add. Вы бы назвали этот метод так:
Math.add(2, 3);
Если бы математика была интерфейсом, а не классом, она не могла бы иметь никаких определенных функций. Поэтому говорить что-то вроде Math.add(2, 3) не имеет смысла.
Причина кроется в принципе проектирования, что 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()?
Теперь 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, чтобы сделать их методами по умолчанию и статическими методами соответственно.
Похоже, что статический метод в интерфейсе может быть поддержан в 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..., тогда вы можете избавиться от неоднозначной проблемы.
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);
}
Незаконное сочетание модификаторов: статических и абстрактных
Если член класса объявлен как статический, его можно использовать с именем класса, которое ограничено этим классом, без создания объекта.
Если член класса объявлен как абстрактный, необходимо объявить класс как абстрактный и предоставить реализацию абстрактного члена в его наследуемом классе (подклассе).
Вам нужно предоставить реализацию абстрактному члену класса в подклассе, где вы собираетесь изменить поведение статического метода, также объявленного как абстрактный, который ограничен базовым классом, что не является правильным
Так как статические методы не могут быть унаследованы . Так что нет смысла помещать его в интерфейс. Интерфейс-это в основном контракт, которому должны следовать все его подписчики . Размещение статического метода в интерфейсе заставит подписчиков реализовать его . что теперь становится противоречащим тому факту, что статические методы не могут быть унаследованы .
С Java 8 интерфейсы теперь могут иметь статические методы.
С Java 8 интерфейсы теперь могут иметь статические методы.
Например, компаратор имеет статический метод naturalOrder().
Требование, что интерфейсы не могут иметь реализаций, также было смягчено. Интерфейсы теперь могут объявлять реализации метода "default", которые похожи на обычные реализации с одним исключением: если вы наследуете как реализацию по умолчанию от интерфейса, так и обычную реализацию от суперкласса, реализация суперкласса всегда будет иметь приоритет.
Возможно, вам поможет пример кода, я собираюсь использовать 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.