Por que não posso declarar métodos estáticos em uma interface?

150

O tópico diz o máximo - qual é a razão do fato de que métodos estáticos não podem ser declarados em uma interface?

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

O código acima me fornece o seguinte erro (no Eclipse, pelo menos): "Modificador ilegal para o método de interface ITest.test (); somente público e resumo são permitidos".

Henrik Paul
fonte
2
Inaceite a resposta de Espo, pois ela é falha. Uma interface possui um arquivo de classe que pode conter a implementação de um método estático (se o designer Java permitir isso), portanto, não há problema em resolver a implementação do método estático. Funciona exatamente como em outras classes estáticas.
Mnementh 26/09/08
eu meio que concordo com a resposta dada por "erickson" stackoverflow.com/questions/512877/…
Maverick
9
Isso estará disponível no Java 8 btw.
M0skit0
1
@Vadorequest GIYF mas enfim, verifique aqui
m0skit0
2
Links de documentação oficial: Java SE tutorial & Java Language Specification 9.2
LoganMzz

Respostas:

85

Existem alguns problemas em jogo aqui. O primeiro é a questão de declarar um método estático sem defini-lo. Essa é a diferença entre

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

e

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

O primeiro é impossível pelos motivos mencionados pela Espo : você não sabe qual classe de implementação é a definição correta.

Java poderia permitir o último; e, de fato, a partir do Java 8, ele faz!

James A. Rosen
fonte
2
Sim - é idealógico, não técnico. A razão pela qual eu gostaria é. é possível ter um método estático de "implementação" em uma interface que faça referência apenas a outros métodos de "interface" na interface que podem ser facilmente reutilizados pela implementação de classes. Mas pode-se declarar uma classe estática em uma interface para que essas coisas residam lá, como MyInterface.Impl.doIt (MyInterface i, Object [] args) {...}
peterk
9
Desde o Java 8, você pode definir staticmétodos em um interface. Os métodos devem ser public.
Olivier Grégoire
4
@ OlivierGrégoire ... e eles não são herdados, o que é fundamental.
William F. Jameson
1
Boa resposta, embora ROFLMAO xD "aproximadamente equivalente" eu teria colocado mais como "um pouco parecido".
Timo
44

A razão pela qual você não pode ter um método estático em uma interface está na maneira como o Java resolve as referências estáticas. Java não se incomodará em procurar uma instância de uma classe ao tentar executar um método estático. Isso ocorre porque os métodos estáticos não dependem da instância e, portanto, podem ser executados diretamente do arquivo de classe. Dado que todos os métodos em uma interface são abstratos, a VM precisaria procurar uma implementação específica da interface para encontrar o código por trás do método estático para que ele pudesse ser executado. Isso então contradiz como a resolução estática do método funciona e introduziria uma inconsistência na linguagem.

Espo
fonte
3
Esta explicação não explica o problema. Toda interface possui seu próprio arquivo de classe; pode conter o método estático. Portanto, nenhuma pesquisa para uma implementação específica seria necessária.
Mnementh 26/09/08
Nem todo tipo de interface em Java está dentro de seu próprio arquivo, nem deve estar de acordo com o JLS. Além disso, o JLS não estipula que as classes devem ser sempre armazenadas em um sistema de arquivos, pelo contrário.
Vlad Gudim
4
@Totophil: As interfaces não devem estar em um único arquivo java, mas terão um arquivo de classe próprio após a compilação. Foi o que eu escrevi.
Mnementh
18

Eu responderei sua pergunta com um exemplo. Suponha que tenhamos uma classe Math com um método estático add. Você chamaria esse método da seguinte maneira:

Math.add(2, 3);

Se o Math fosse uma interface em vez de uma classe, ele não poderia ter nenhuma função definida. Como tal, dizer algo como Math.add (2, 3) não faz sentido.

Kyle Cronin
fonte
11

A razão reside no princípio de design, que java não permite herança múltipla. O problema com herança múltipla pode ser ilustrado pelo seguinte exemplo:

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

Agora, o que acontece se você chamar Cx ()? O Ax () ou o Bx () serão executados? Todo idioma com herança múltipla precisa resolver esse problema.

As interfaces permitem em Java algum tipo de herança múltipla restrita. Para evitar o problema acima, eles não têm permissão para ter métodos. Se olharmos para o mesmo problema com interfaces e métodos estáticos:

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

Mesmo problema aqui, o que acontece se você chamar Cx ()?

Mnementh
fonte
Alguma razão para o voto negativo? Um comentário explicativo seria bom.
Mnementh
Eu não sou o downvoter, mas isso não é válido para métodos não estáticos também?
Nawfal #
OK, aqui estão duas possibilidades diferentes. Um método pode ser implementado ou declarado apenas. Eu entendi que o método estático tem que ser implementado. Nesse sentido, encontro o problema apresentado na minha resposta. Se você não fizer isso, encontrará o problema que Espo descreveu - e que eu não entendi porque presumi que o método estático seria implementado. Você também não pode declarar um método abstrato estático por esse motivo, experimente, o compilador irá reclamar.
Mnementh
Ok, esqueça a parte da implementação. a questão é por que não podemos declarar. sim, o compilador irá reclamar e por que essa é a questão. ao que eu acho que você não respondeu.
Nawfal #
1
Como é que a situação não ser pior do que ter de interface Acontêm int x(int z);ea interface Bcontêm string x(int x);? Qual é o significado da x(3)interface C?
Supercat 01/02
7

Métodos estáticos não são métodos de instância. Não há contexto de instância; portanto, implementá-lo a partir da interface faz pouco sentido.

Ryan Farley
fonte
5

Agora, o Java8 nos permite definir até métodos estáticos na interface.

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

Nota: Os métodos na Interface ainda são abstratos públicos por padrão, se não usarmos explicitamente as palavras-chave default / static para torná-las Métodos padrão e Métodos estáticos resp.

Anandaraja_Srinivasan
fonte
4

Há uma resposta muito agradável e concisa para sua pergunta aqui . (Pareceu-me uma maneira bem direta de explicar que quero vinculá-lo daqui.)

Zarkonnen
fonte
Esta não é uma resposta para a pergunta, na melhor das hipóteses, deve ser um comentário.
CubeJockey
3

Parece que o método estático na interface pode ser suportado no Java 8 , bem, minha solução é apenas defini-los na classe interna.

interface Foo {
    // ...
    class fn {
        public static void func1(...) {
            // ...
        }
    }
}

A mesma técnica também pode ser usada nas anotações:

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

A classe interna sempre deve ser acessada na forma de, em Interface.fn...vez de Class.fn..., então, você pode se livrar de um problema ambíguo.

Xiè Jìléi
fonte
2

Uma interface é usada para o polimorfismo, que se aplica a objetos, não a tipos. Portanto (como já observado), não faz sentido ter um membro de interface estática.

Rob Cooper
fonte
Em alguns contextos reflexivos, quase parece fazer sentido
Cruncher
1

Java 8 Mudou o mundo, você pode ter métodos estáticos na interface, mas obriga a fornecer implementação para isso.

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
fonte
0

Combinação ilegal de modificadores: estático e abstrato

Se um membro de uma classe é declarado como estático, ele pode ser usado com seu nome de classe que é confinado a essa classe, sem criar um objeto.

Se um membro de uma classe for declarado como abstrato, você precisará declarar a classe como abstrata e fornecer a implementação do membro abstrato em sua classe herdada (Subclasse).

Você precisa fornecer uma implementação para o membro abstrato de uma classe na subclasse em que irá alterar o comportamento do método estático, também declarado como abstrato, que está confinado à classe base, o que não está correto

Sankar
fonte
Como isso responde à pergunta? O OP perguntou sobre a interface enquanto você escrevia sobre a aula.
Lucky
0

Como métodos estáticos não podem ser herdados. Portanto, não adianta colocá-lo na interface. Interface é basicamente um contrato que todos os seus assinantes precisam seguir. A colocação de um método estático na interface forçará os assinantes a implementá-lo. o que agora se torna contraditório com o fato de que métodos estáticos não podem ser herdados.

ip_x
fonte
métodos estáticos são sempre herdados, mas não podem ser substituídos.
Akki 27/02
0

Com o Java 8 , as interfaces agora podem ter métodos estáticos.

Por exemplo, o Comparator possui um método estático naturalOrder ().

O requisito de que as interfaces não possam ter implementações também foi relaxado. As interfaces agora podem declarar implementações de método "padrão", que são como implementações normais, com uma exceção: se você herdar uma implementação padrão de uma interface e uma implementação normal de uma superclasse, a implementação da superclasse sempre terá prioridade.

Ishara
fonte
AMD! Temos um programador sério (e eu, comentarista) respondendo (e eu, comentando) uma pergunta de 10 anos.
Mohamed Anees A 21/02/19
Eu não percebi a data :) #
224 Ishara Is
Haha! Sem problemas!
Mohamed Anees A 22/02/19
-2

Talvez um exemplo de código ajude, eu vou usar o C #, mas você deve acompanhar.

Vamos fingir que temos uma interface chamada IPayable

public interface IPayable
{
    public Pay(double amount);
}

Agora, temos duas classes concretas que implementam essa interface:

public class BusinessAccount : IPayable
{
    public void Pay(double amount)
    {
        //Logic
    }
}

public class CustomerAccount : IPayable
{
    public void Pay(double amount)
    {
        //Logic
    }
}

Agora, vamos fingir que temos uma coleção de várias contas. Para isso, usaremos uma lista genérica do tipo IPayable

List<IPayable> accountsToPay = new List<IPayable>();
accountsToPay.add(new CustomerAccount());
accountsToPay.add(new BusinessAccount());

Agora, queremos pagar R $ 50,00 a todas essas contas:

foreach (IPayable account in accountsToPay)
{
    account.Pay(50.00);
}

Então agora você vê como as interfaces são incrivelmente úteis.

Eles são usados ​​apenas em objetos instanciados. Não em classes estáticas.

Se você tivesse feito o pagamento estático, ao percorrer o IPayable em accountsToPay, não haveria maneira de descobrir se ele deveria pagar pelo BusinessAcount ou CustomerAccount.

FlySwat
fonte
Só porque métodos estáticos não fazem sentido neste exemplo, não significa que eles não façam sentido em QUALQUER exemplo. No seu exemplo, se a interface IPayable tivesse o método estático "IncrementPayables" que acompanhava quantas contas a pagar foram adicionadas, esse seria um caso de uso real. Obviamente, sempre se pode usar uma classe abstrata, mas não foi isso que você abordou. Seu exemplo em si não prejudica os métodos estáticos nas interfaces.
achou