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

Project + Properties, Debugging, untick «Включить хостинг Visual Studio». Я не могу понять, что он делает. Как только я поставлю галочку в опции «Включенный неуправляемый отладчик кода», чтобы попытаться заглянуть в эти потоки, они больше не запускаются. Нет подсказки. Но я уверен, что это для нас полезно:)

470
задан Daniel Wallman 20 May 2019 в 12:42
поделиться

13 ответов

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

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

здесь существует действительно два вопроса:

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

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

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

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

Переопределяющие статические методы

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

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

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

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

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

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

<час>

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

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

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

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

Foo obj = Foo.newInstanceFromXML(e);

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

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

494
ответ дан erickson 20 May 2019 в 22:42
поделиться

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

MyImplClass.myMethod()

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

myInstance.myMethod()

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

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

MyImplClass.myMethod()

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

-2
ответ дан Pavel Feldman 20 May 2019 в 22:42
поделиться
  • 1
    Да, мы на самом деле рассмотрели его, но проблемой здесь является каждая машина, имеет больше чем один экземпляр кота (это может быть больше сложно?) и очевидно они работают на различных портах. Таким образом, порт не может быть hardcoded. – Teja Kantamneni 6 October 2010 в 10:09

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

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

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

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

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

0
ответ дан Handerson 20 May 2019 в 22:42
поделиться
  • 1
    @mrrtnn: вздох Он doesn' t нужен тот. Он doesn' t нужен номер порта. Все, в чем он нуждается, является относительным URL сервиса, к которому он хочет получить доступ в то время, когда он должен получить доступ к нему . – Aaron Digulla 26 November 2010 в 22:40

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

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

Hope, которая помогает!

0
ответ дан samoz 20 May 2019 в 22:42
поделиться
  • 1
    Я имею в виду, когда приложение развернется в любом сервере приложений, будет некоторый код начальной загрузки или init параметрические усилители в сервлетах, которые поднимают приложение и рабочий готовый служить запросам. Когда пружинные загрузки приложения MVC, это загружает всю конфигурацию и я должен знать номер порта в этом процессе. Я обновлю вопрос с большим количеством деталей. – Teja Kantamneni 6 October 2010 в 07:58
  • "Там конкретная причина, что статические методы не могут быть переопределены".

Позволяют мне перефразировать тот вопрос для Вашего путем заполнения определений.

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

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

5
ответ дан Darron 20 May 2019 в 22:42
поделиться
  • 1
    Это неправильно - первое поймает все CLS-совместимые исключения, второе также поймает не CLS-совместимые исключения. – Oded 3 August 2010 в 08:20

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

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

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

и загрузить Человека идентификатором Вы сделали бы

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

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

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

2
ответ дан Mr. Shiny and New 安宇 20 May 2019 в 22:42
поделиться
  • 1
    @Justin Ethier, senzacionale: причина, являющаяся, Ваш код может действительно обработать что-то как из ошибки памяти, или хуже? При ловле исключения Вы говорите, что можно обработать случай, который описывает тип исключительной ситуации. – Merlyn Morgan-Graham 3 August 2010 в 08:13

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

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

public interface Test {
    static class Inner {
        public static Object get() {
            return 0;
        }
    }
}
5
ответ дан Adrian Pronk 20 May 2019 в 22:42
поделиться
  • 1
    Его первая форма без параметров. Ваш пример имеет параметр, таким образом, I' m не уверенный, как Ваш пример выстраивается в линию. Первая форма позволяет Вам без параметров ловить исключения типом, где второе позволяет всем исключениям быть пойманными без параметров. – Travis Heseman 3 August 2010 в 09:07

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

6
ответ дан cliff.meyers 20 May 2019 в 22:42
поделиться

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

21
ответ дан Michael Myers 20 May 2019 в 22:42
поделиться
  • 1
    @Rei Miyasaka: O_O! Это потрясает новости мне. Спасибо за подсказку. – Merlyn Morgan-Graham 3 August 2010 в 08:39

Это уже спросили и ответили, здесь

Для дублирования моего ответа:

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

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

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

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

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

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

47
ответ дан Community 20 May 2019 в 22:42
поделиться
  • 1
    Я думал, что первое только поймает организованные исключения, и второе также поймало бы win32 исключения. – Oded 3 August 2010 в 08:09

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

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

2
ответ дан MichaelGG 20 May 2019 в 22:42
поделиться
  • 1
    @Oded: Я могу быть неправым, но я думаю, что win32 исключения происходят из Исключения, в этом случае они были бы пойманы. – Merlyn Morgan-Graham 3 August 2010 в 08:11

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

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.
  }

}
0
ответ дан Michael Myers 20 May 2019 в 22:42
поделиться
  • 1
    - 1 Teja сказала " я знаю, что мы можем найти его, если у нас есть HTTPServletRequest" и Ваш ответ подразумевает входящий запрос. – mschonaker 25 November 2010 в 20:44

Обычно это сделано с помощью Шаблона "фабрика"

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

public interface IXMLizable {
  public Element toXMLElement();
}
37
ответ дан Peter Lawrey 20 May 2019 в 22:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: