Почему я не могу определить статический метод в интерфейсе Java?

Вот пример:

public interface IXMLizable<T>
{
  static T newInstanceFromXML(Element e);
  Element toXMLElement();
}

Конечно, это не сработает. Но почему нет?

Одной из возможных проблем будет то, что происходит, когда вы звоните:

IXMLizable.newInstanceFromXML(e);

В этом случае я думаю, что он должен просто вызвать пустой метод (то есть {}). Все подклассы будут вынуждены реализовать статический метод, поэтому все они будут в порядке при вызове статического метода. Так почему же это невозможно?

РЕДАКТИРОВАТЬ: Я думаю, что я ищу ответ, который глубже, чем "потому что это так, как Java".

Есть ли конкретная технологическая причина, по которой статические методы нельзя перезаписать? То есть, почему разработчики Java решили сделать методы экземпляров переопределенными, а не статическими?

РЕДАКТИРОВАТЬ: проблема с моим дизайном в том, что я пытаюсь использовать интерфейсы для обеспечения соблюдения правил кодирования.

То есть цель интерфейса двояка:

  1. Я хочу, чтобы интерфейс IXMLizable позволял мне преобразовывать классы, которые его реализуют, в элементы XML (используя полиморфизм, работает нормально).

  2. Если кто-то хочет создать новый экземпляр класса, который реализует интерфейс IXMLizable, он всегда будет знать, что будет статический конструктор newInstanceFromXML(Element e).

Есть ли другой способ обеспечить это, кроме простого добавления комментария в интерфейс?

РЕДАКТИРОВАТЬ: Начиная с Java 8, статические методы теперь разрешены в интерфейсах.

24 ответа

Решение

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

В Java 8 интерфейсы могут иметь статические методы. Они также могут иметь конкретные методы экземпляра, но не поля экземпляра.

Здесь действительно два вопроса:

  1. Почему в старые добрые времена интерфейсы не могли содержать статические методы?
  2. Почему статические методы не могут быть переопределены?

Статические методы в интерфейсах

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

Наконец, Java 8 представила статические методы интерфейса, а также перезаписываемые методы экземпляров с реализацией по умолчанию. Они все еще не могут иметь поля экземпляра, хотя. Эти функции являются частью поддержки лямбда-выражений, и вы можете прочитать больше о них в Части H JSR 335.

Переопределение статических методов

Ответ на второй вопрос немного сложнее.

Статические методы разрешимы во время компиляции. Динамическая диспетчеризация имеет смысл для методов экземпляра, где компилятор не может определить конкретный тип объекта и, таким образом, не может разрешить вызываемый метод. Но для вызова статического метода требуется класс, и поскольку этот класс известен статически - во время компиляции - динамическая диспетчеризация не требуется.

Небольшое представление о том, как работают экземпляры, необходимо, чтобы понять, что здесь происходит. Я уверен, что фактическая реализация совершенно иная, но позвольте мне объяснить мое представление о методе диспетчеризации, который модели точно наблюдал поведение.

Представьте, что у каждого класса есть хеш-таблица, которая отображает сигнатуры методов (имена и типы параметров) с реальным фрагментом кода для реализации метода. Когда виртуальная машина пытается вызвать метод в экземпляре, она запрашивает у объекта свой класс и ищет запрошенную подпись в таблице класса. Если тело метода найдено, оно вызывается. В противном случае родительский класс класса получается, и поиск там повторяется. Это продолжается до тех пор, пока метод не будет найден или не останется родительских классов, что приведет к NoSuchMethodError,

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

Теперь предположим, что мы пропускаем экземпляр объекта и просто начинаем с подкласса. Разрешение может продолжаться, как указано выше, давая вам своего рода "переопределенный" статический метод. Однако все это разрешение может произойти во время компиляции, поскольку компилятор запускается из известного класса, а не ждет времени выполнения, чтобы запросить объект неопределенного типа для своего класса. Нет смысла "переопределять" статический метод, поскольку всегда можно указать класс, содержащий нужную версию.


Конструктор "Интерфейс"

Вот немного больше материала, чтобы обратиться к недавнему редактированию вопроса.

Похоже, вы хотите эффективно назначить конструктор-подобный метод для каждой реализации IXMLizable, Забудьте о попытке реализовать это с помощью интерфейса на минуту и ​​представьте, что у вас есть некоторые классы, отвечающие этому требованию. Как бы вы использовали это?

class Foo implements IXMLizable<Foo> {
  public static Foo newInstanceFromXML(Element e) { ... }
}

Foo obj = Foo.newInstanceFromXML(e);

Поскольку вы должны явно назвать конкретный тип Foo при "создании" нового объекта компилятор может убедиться, что у него действительно есть необходимый фабричный метод. А если нет, ну и что? Если я могу реализовать IXMLizable в котором отсутствует "конструктор", и я создаю экземпляр и передаю его в ваш код, это IXMLizable со всем необходимым интерфейсом.

Конструкция является частью реализации, а не интерфейса. Любой код, который успешно работает с интерфейсом, не заботится о конструкторе. Любой код, который заботится о конструкторе, должен в любом случае знать конкретный тип, и интерфейс можно игнорировать.

Об этом уже спрашивали и отвечали, вот

Чтобы дублировать мой ответ:

Нет смысла объявлять статический метод в интерфейсе. Они не могут быть выполнены обычным вызовом MyInterface.staticMethod(). Если вы вызываете их, указывая класс реализации MyImplementor.staticMethod(), то вы должны знать фактический класс, поэтому не имеет значения, содержит ли его интерфейс или нет.

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

MyInterface var = new MyImplementingClass();
var.staticMethod();

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

Причина, по которой вы не можете выполнить "result=MyInterface.staticMethod()", состоит в том, что ему придется выполнить версию метода, определенного в MyInterface. Но не может быть версии, определенной в MyInterface, потому что это интерфейс. У него нет кода по определению.

Хотя вы можете сказать, что это "потому что Java делает это таким образом", на самом деле решение является логическим следствием других проектных решений, также принятых по очень веской причине.

С появлением Java 8 теперь возможно писать стандартные и статические методы в интерфейсе. docs.oracle/staticMethod

Например:

public interface Arithmetic {

    public int add(int a, int b);

    public static int multiply(int a, int b) {
        return a * b;
    }
}
public class ArithmaticImplementation implements Arithmetic {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) {
        int result = Arithmetic.multiply(2, 3);
        System.out.println(result);
    }
}

Результат: 6

СОВЕТ: Вызов метода статического интерфейса не требует реализации каким-либо классом. Конечно, это происходит потому, что те же правила для статических методов в суперклассах применяются к статическим методам на интерфейсах.

Обычно это делается с использованием шаблона Factory

public interface IXMLizableFactory<T extends IXMLizable> {
  public T newInstanceFromXML(Element e);
}

public interface IXMLizable {
  public Element toXMLElement();
}

Потому что статические методы не могут быть переопределены в подклассах, и, следовательно, они не могут быть абстрактными. И все методы в интерфейсе де-факто являются абстрактными.

Почему я не могу определить статический метод в интерфейсе Java?

На самом деле вы можете в Java 8.

Согласно документу Java:

Статический метод - это метод, связанный с классом, в котором он определен, а не с каким-либо объектом. Каждый экземпляр класса разделяет свои статические методы

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

Пример метода по умолчанию:

list.sort(ordering);

вместо

Collections.sort(list, ordering);

Пример статического метода (из самого документа):

public interface TimeClient {
    // ...
    static public ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +
                "; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

    default public ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }    
}

Интерфейсы связаны с полиморфизмом, который по своей природе связан с экземплярами объектов, а не с классами. Поэтому static не имеет смысла в контексте интерфейса.

Во-первых, все языковые решения - это решения, принимаемые создателями языка. В мире разработки программного обеспечения или определения языка или написания компилятора / интерпретатора нет ничего, что говорило бы о том, что статический метод не может быть частью интерфейса. Я создал пару языков и написал для них компиляторы - все это просто садится и определяет значимую семантику. Я бы сказал, что семантика статического метода в интерфейсе удивительно ясна - даже если компилятор должен отложить разрешение метода до времени выполнения.

Во-вторых, то, что мы используем статические методы, означает, что есть веская причина иметь шаблон интерфейса, который включает статические методы - я не могу говорить ни за кого из вас, но я использую статические методы на регулярной основе.

Наиболее вероятный правильный ответ заключается в том, что в то время, когда был определен язык, не было ощущения необходимости в статических методах в интерфейсах. За прошедшие годы Java значительно выросла, и этот вопрос, по-видимому, вызвал некоторый интерес. То, что он рассматривался для Java 7, указывает на то, что он поднялся до уровня интереса, который может привести к изменению языка. Я, например, буду счастлив, когда мне больше не придется создавать экземпляр объекта просто для того, чтобы я мог вызвать свой нестатический метод получения, чтобы получить доступ к статической переменной в экземпляре подкласса...

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

Но вы можете поместить классы, содержащие статические методы, в интерфейсы. Вы можете попробовать это!

public interface Test {
    static class Inner {
        public static Object get() {
            return 0;
        }
    }
}
  • Msgstr "Есть ли особая причина, по которой статические методы не могут быть переопределены".

Позвольте мне перефразировать этот вопрос для вас, заполнив определения.

  • "Есть ли особая причина, по которой методы, разрешенные во время компиляции, не могут быть решены во время выполнения".

Или, если говорить более полно, если я хочу вызвать метод без экземпляра, но зная класс, как я могу разрешить его на основе экземпляра, которого у меня нет.

Комментирование EDIT: As of Java 8, static methods are now allowed in interfaces.

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

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

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

cmd = createCmd(Person.getCreateCmdId());
Person p = cmd.execute();

и загрузить человека по идентификатору вы бы сделали

cmd = createCmd(Person.getGetCmdId());
cmd.set(ID, id);
Person p = cmd.execute();

Это довольно удобно, однако у него есть свои проблемы; Примечательно, что в интерфейсе нельзя применять статические методы. Перезаписываемый статический метод в интерфейсе был бы именно тем, что нам нужно, если бы только он мог как-то работать.

EJB решают эту проблему, имея домашний интерфейс; каждый объект знает, как найти свой Дом, а Дом содержит "статические" методы. Таким образом, "статические" методы могут быть переопределены по мере необходимости, и вы не загромождаете нормальный (он называется "удаленный") интерфейс методами, которые не применяются к экземпляру вашего компонента. Просто установите в обычном интерфейсе метод getHome(). Возврат экземпляра объекта Home (который может быть одноэлементным, я полагаю), и вызывающая сторона может выполнять операции, которые влияют на все объекты Person.

Why can't I define a static method in a Java interface?

Все методы в интерфейсе явно абстрактны, и поэтому вы не можете определить их как статические, потому что статические методы не могут быть абстрактными.

Что ж, без обобщений статические интерфейсы бесполезны, потому что все вызовы статических методов разрешаются во время компиляции. Таким образом, нет никакой реальной пользы для них.

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

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

Таким образом, наиболее близким приближением к статическому методу в интерфейсе будет нестатический метод, который игнорирует "this", то есть не обращается к каким-либо нестатическим элементам экземпляра. На низкоуровневой абстракции каждый нестатический метод (после поиска в любой vtable) на самом деле является просто функцией с областью действия класса, которая принимает "this" в качестве неявного формального параметра. Посмотрите на одноэлементный объект Scala и совместимость с Java в качестве доказательства этой концепции. И, таким образом, каждый статический метод является функцией с областью действия класса, которая не принимает параметр "this". Таким образом, обычно статический метод может вызываться статически, но, как было указано ранее, интерфейс не имеет реализации (является абстрактным).

Таким образом, чтобы получить наиболее близкое приближение к статическому методу в интерфейсе, используйте нестатический метод, затем не обращайтесь ни к одному из нестатических элементов экземпляра. Не было бы никакого возможного выигрыша в производительности каким-либо другим способом, потому что нет никакого способа статически связать (во время компиляции) ISomething.member(), Единственное преимущество статического метода в интерфейсе, которое я вижу, состоит в том, что он не будет вводить (то есть игнорировать) неявное "this" и, таким образом, запрещать доступ к любому из нестатических элементов экземпляра. Это неявно заявило бы, что функция, которая не имеет доступа к "this", является иммутированной и даже не только для чтения по отношению к содержащему ее классу. Но объявление "статического" в интерфейсе ISomething будет также путать людей, которые пытались получить к нему доступ ISomething.member() что приведет к ошибке компилятора. Я полагаю, если бы ошибка компилятора была достаточно объяснительной, это было бы лучше, чем пытаться научить людей использовать нестатический метод для достижения того, чего они хотят (по-видимому, в основном фабричные методы), как мы делаем здесь (и повторялось для 3 Вопросы и ответы на этом сайте), так что это, очевидно, проблема, которая не является интуитивно понятной для многих людей. Я должен был подумать об этом некоторое время, чтобы получить правильное понимание.

Чтобы получить изменяемое статическое поле в интерфейсе, используйте нестатические методы получения и установки в интерфейсе, чтобы получить доступ к тому статическому полю, которое находится в подклассе. Sidenote, по-видимому неизменяемая статика может быть объявлена ​​в интерфейсе Java с static final,

Хотя я понимаю, что Java 8 решает эту проблему, я решил присоединиться к сценарию, над которым я сейчас работаю (заблокирован с помощью Java 7), в котором было бы полезно указать статические методы в интерфейсе.

У меня есть несколько определений перечисления, в которых я определил поля "id" и "displayName", а также вспомогательные методы, оценивающие значения по разным причинам. Реализация интерфейса позволяет мне гарантировать, что методы getter находятся на месте, но не статические вспомогательные методы. Будучи перечислением, на самом деле нет чистого способа разгрузить вспомогательные методы в унаследованный абстрактный класс или что-то подобное, поэтому методы должны быть определены в самом перечислении. Кроме того, поскольку это enum, вы никогда не сможете фактически передать его как экземплярный объект и трактовать его как тип интерфейса, но мне нравится возможность наличия статических вспомогательных методов через интерфейс. это поддерживается в Java 8.

Вот код, иллюстрирующий мою точку зрения.

Определение интерфейса:

public interface IGenericEnum <T extends Enum<T>> {
    String getId();
    String getDisplayName();
    //If I was using Java 8 static helper methods would go here
}

Пример одного определения перечисления:

public enum ExecutionModeType implements IGenericEnum<ExecutionModeType> {
    STANDARD ("Standard", "Standard Mode"),
    DEBUG ("Debug", "Debug Mode");

    String id;
    String displayName;

    //Getter methods
    public String getId() {
        return id;
    }

    public String getDisplayName() {
        return displayName;
    }

    //Constructor
    private ExecutionModeType(String id, String displayName) {
        this.id = id;
        this.displayName = displayName;
    }

    //Helper methods - not enforced by Interface
    public static boolean isValidId(String id) {
        return GenericEnumUtility.isValidId(ExecutionModeType.class, id);
    }

    public static String printIdOptions(String delimiter){
        return GenericEnumUtility.printIdOptions(ExecutionModeType.class, delimiter);
    }

    public static String[] getIdArray(){
        return GenericEnumUtility.getIdArray(ExecutionModeType.class);
    }

    public static ExecutionModeType getById(String id) throws NoSuchObjectException {
        return GenericEnumUtility.getById(ExecutionModeType.class, id);
    }
}

Общее определение утилиты enum:

public class GenericEnumUtility {
    public static <T extends Enum<T> & IGenericEnum<T>> boolean isValidId(Class<T> enumType, String id) {       
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(enumOption.getId().equals(id)) {
                return true;
            }
        }

        return false;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String printIdOptions(Class<T> enumType, String delimiter){
        String ret = "";
        delimiter = delimiter == null ? " " : delimiter;

        int i = 0;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(i == 0) {
                ret = enumOption.getId();
            } else {
                ret += delimiter + enumOption.getId();
            }           
            i++;
        }

        return ret;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String[] getIdArray(Class<T> enumType){
        List<String> idValues = new ArrayList<String>();

        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            idValues.add(enumOption.getId());
        }

        return idValues.toArray(new String[idValues.size()]);
    }

    @SuppressWarnings("unchecked")
    public static <T extends Enum<T> & IGenericEnum<T>> T getById(Class<T> enumType, String id) throws NoSuchObjectException {
        id = id == null ? "" : id;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(id.equals(enumOption.getId())) {
                return (T)enumOption;
            }
        }

        throw new NoSuchObjectException(String.format("ERROR: \"%s\" is not a valid ID. Valid IDs are: %s.", id, printIdOptions(enumType, " , ")));
    }
}

Давайте предположим, что статические методы были разрешены в интерфейсах: * Они заставили бы все реализующие классы объявить этот метод. * Интерфейсы обычно используются через объекты, поэтому единственными эффективными методами для них являются нестатические. * Любой класс, который знает конкретный интерфейс, может вызывать его статические методы. Следовательно, статический метод реализующего класса будет вызван снизу, но класс invoker не знает, какой именно. Как это узнать? У него нет экземпляров, чтобы догадаться об этом!

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

Если мы хотим, чтобы это было распространено на статические методы, у нас должна быть возможность предварительно определить реализующий класс, а затем передать ссылку на вызывающий класс. Это может использовать класс через статические методы в интерфейсе. Но в чем разница между этой ссылкой и объектом? Нам просто нужен объект, представляющий, что это был за класс. Теперь объект представляет старый класс и может реализовывать новый интерфейс, включая старые статические методы - теперь они нестатические.

Для этого служат метаклассы. Вы можете попробовать класс Class of Java. Но проблема в том, что Java недостаточно гибка для этого. Вы не можете объявить метод в объекте класса интерфейса.

Это мета проблема - когда нужно делать задницу

..бла бла

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

Чтобы решить эту проблему: ошибка: отсутствует тело метода или объявлено абстрактное статическое void main(String[] args);

interface I
{
    int x=20;
    void getValue();
    static void main(String[] args){};//Put curly braces 
}
class InterDemo implements I
{
    public void getValue()
    {
    System.out.println(x);
    }
    public static void main(String[] args)
    {
    InterDemo i=new InterDemo();
    i.getValue();   
    }

}

выход: 20

Теперь мы можем использовать статический метод в интерфейсе

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

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

Надеюсь, это поможет!

Предположим, вы могли бы сделать это; рассмотрим этот пример:

interface Iface {
  public static void thisIsTheMethod();
}

class A implements Iface {

  public static void thisIsTheMethod(){
    system.out.print("I'm class A");
  }

}

class B extends Class A {

  public static void thisIsTheMethod(){
    System.out.print("I'm class B");
  } 
}

SomeClass {

  void doStuff(Iface face) {
    IFace.thisIsTheMethod();
    // now what would/could/should happen here.
  }

}

Нечто, что можно реализовать, - это статический интерфейс (вместо статического метода в интерфейсе). Все классы, реализующие данный статический интерфейс, должны реализовывать соответствующие статические методы. Вы можете получить статический интерфейс SI из любого класса, используя

SI si = clazz.getStatic(SI.class); // null if clazz doesn't implement SI
// alternatively if the class is known at compile time
SI si = Someclass.static.SI; // either compiler errror or not null

тогда вы можете позвонить si.method(params), Это было бы полезно (например, для шаблона проектирования фабрики), потому что вы можете получить (или проверить реализацию) реализацию статических методов SI из неизвестного класса времени компиляции! Динамическая диспетчеризация необходима, и вы можете переопределить статические методы (если не финальные) класса, расширив его (при вызове через статический интерфейс). Очевидно, что эти методы могут получить доступ только к статическим переменным своего класса.

Вы не можете определить статические методы в интерфейсе, потому что статические методы принадлежат классу, а не экземпляру класса, и интерфейсы не являются классами. Узнайте больше здесь.

Однако, если вы хотите, вы можете сделать это:

public class A {
  public static void methodX() {
  }
}

public class B extends A {
  public static void methodX() {
  }
}

В этом случае у вас есть два класса с двумя различными статическими методами, которые называются methodX().

Я думаю, что у Java нет статических методов интерфейса, потому что они вам не нужны. Вы можете думать, что делаете, но... Как бы вы их использовали? Если вы хотите назвать их как

MyImplClass.myMethod()

тогда вам не нужно объявлять это в интерфейсе. Если вы хотите назвать их как

myInstance.myMethod()

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

Интерфейсы позволяют вам определять контракт между экземпляром класса, который реализует интерфейс, и вызывающим кодом. И java помогает вам быть уверенным, что этот контракт не нарушен, поэтому вы можете положиться на него и не беспокоиться о том, какой класс реализует этот контракт, достаточно просто "того, кто подписал контракт". В случае статических интерфейсов ваш код

MyImplClass.myMethod()

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

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

Другие вопросы по тегам