27 votes

Pourquoi ne puis-je pas "importer statiquement" une méthode "égale" en Java?

J'aime l'utilisation de cette méthode ici:

org.apache.commons.lang.ObjectUtils.equals(Object object1, Object object2)

Le seul inconvénient (par rapport à Google de Goyave, par exemple), c'est que je ne peut pas statique de l'importation de la méthode. I. e. c'est inutile:

import static org.apache.commons.lang.ObjectUtils.equals;

... que mon Eclipse compilateur ne sera pas correctement lien de cette méthode lors de l'écriture

equals(obj1, obj2);

L'erreur est:

La méthode equals(Object) dans le type de l'Objet n'est pas applicable pour les arguments (..., ...)

Pourquoi est-ce? Est mon statiquement importés méthode n'est pas applicable s'il y a une méthode avec le même nom (mais pas la même signature) dans l'un des super-types? Est-ce formellement spécifié dans le JLS? Ou certains Eclipse compilateur problème?

Mise à JOUR

Cela ne fonctionne pas, soit:

import static org.apache.commons.lang.ObjectUtils.defaultIfNull;

public class Test {
  void test() {
    defaultIfNull(null, null);
    // ^^ compilation error here
  }

  void defaultIfNull() {
  }
}

javac message d'erreur:

Test.java:5: defaultIfNull() in Test cannot be applied to (<nulltype>,<nulltype>)
defaultIfNull(null, null);
    ^
1 error

14voto

La collision est en fait avec Object.equals() . Toutes les classes sont héritées de Object et ont donc la méthode Object.equals() qui conduit à cette collision.

Vous importez par nom, pas par signature. En fait, vous ne pouvez pas importer une méthode statique nommée equals . Ou plutôt, vous pouvez l'importer, mais pas l'utiliser. Je suis d'accord pour dire que cela devrait fonctionner.

(J'ai fait de mes commentaires ma propre réponse.)

14voto

Dhirendra Points 1380

Conformément à la Spécification du Langage Java

  1. Si un seul-statique-déclaration d'importation les importations d'un membre dont le simple le nom est n, et l'unité de compilation contient également un type unique d'importation déclaration que les importations d'un type dont le simple nom est n, au moment de la compilation erreur se produit. (Cette erreur se produit même si les deux déclarations reportez-vous à le même type, sur le motif qu'il est source de confusion pour l'utilisation de deux différents des mécanismes pour assurer la redondance de l'importation du même type.)
  2. Si un seul-statique-déclaration d'importation les importations d'un membre dont le simple le nom est n, et l'unité de compilation déclare, en outre, un haut niveau de type dont le simple nom est n, une erreur de compilation se produit.

Donc dans votre cas son point 2 ci-dessus mentionnés est la raison pour laquelle vous faites erreur de compilation. donc, même si la méthode signatures sont différentes si les noms sont même sa une erreur de compilation.

statique d'importation JSR et JLS

5voto

Bringer128 Points 3590

J'ai fait quelques tests. Première chose que j'ai remarqué, c'est que vous avez seulement besoin d'une statique instruction import pour plusieurs méthodes de même nom.

public class EqualsClass {
  public static boolean equals(Object o1, Object o2) {
    return o1 == null ? o2 == null : o1.equals(o2);
  }

  public static boolean equals(Object o1, Object o2, Object o3) {
    return equals(o1, o2) && equals(o2, o3);
  }
}

import static mypackage.EqualsClass.equals;

public class TestClass {
  public static void main() {
    Object o1 = new Object();
    Object o2 = new Object();

    equals(o1, o2); // Compiles - static context

    Object o3 = new Object();

    equals(o1, o2, o3); // No extra static import required
  }

Ensuite, j'ai remarqué que cela ne fonctionne pas dans une instance de contexte:

  public void someInstanceMethod() {
    Object o1 = new Object();
    Object o2 = new Object();

    equals(o1, o2); // Does not compile - instance context

    Object o3 = new Object();

    equals(o1, o2, o3); // As expected does not compile
  }

}

Mais alors, si j'ai supprimé la statique d'importer la classe statique méthode:

public static boolean equals(Object o1, Object o2) {
  return EqualsClass.equals(o1, o2); // Compiles
}

public void someInstanceMethod() {
  equals(new Object(), new Object()); // Compiles!!
  equals(new Object(), new Object(), new Object()); // Doesn't compile!
}

Le fait qu'il fonctionne dans un contexte statique rend une quantité raisonnable de sens pour moi. Toutefois, il apparaît qu'il y a une différence significative entre la résolution d'une manière statique importés méthode et défini une méthode statique de la classe.

Résumé:

  • Les méthodes ayant le même nom qu'une méthode d'instance ne sont pas accessibles lorsqu'statiquement importée à partir d'une instance de contexte.
  • Les méthodes statiques de la même classe avec le même nom peut être accessible à partir d'une instance de contexte.
  • Statique d'importation vous permet d'accéder à toutes les méthodes statiques avec le même nom que la classe, malgré la signature (paramètres et valeur de retour).

Je serais intéressé de voir la partie de la JLS ou un compilateur spec qui spécifie la résolution de la statique des importations par le compilateur et la façon dont ils sont tabassé par des méthodes locales.

4voto

irreputable Points 25577

J'ai également passé au peigne fin JLS3 et ne pouvait pas trouver une réponse définitive.

par 15.12.1, nous devons d'abord déterminer la classe unique où l' equals méthode est déclarée/a hérité. Ici, nous avons deux candidats des classes, et la spec ne semble pas avoir une règle pour résoudre le conflit.

Nous pouvons enquêter sur un comparable problème. Un type simple nom peut faire référence à la fois à un type importé, ou hérité d'un type (un type de membre de la super-classe). Javac choisit la seconde. C'est probablement en raison de la procédure en 6.5.2, qui donne des importations de la priorité la plus faible.

Si le principe est le même, l'importation d' ObjectUtils.equals doit céder à hérité Object.equals. Puis par 15.12.2.1, il n'y a pas d' equals méthode de Object c'est potentiellement applicable à l'expression equals(obj1, obj2)

Personnellement, je préfère que l'importation a la préséance sur l'héritage, car l'importation est plus proche. Il stabilise aussi la signification d'un nom. Dans le schéma actuel, supposons Object n'ont pas de equals méthode, l'expression equals(obj1, obj2) désigne ObjectUtils.equals; maintenant, supposons Object ajoute l' equals "la méthode, totalement innocent déplacer, du coup le sous-classe ne compile pas. Pire scénario: le nouveau equals méthode a une signature compatible; la sous-classe encore compile, mais le sens de l'expression silencieusement changements.

2voto

Stefan Points 511

Ce n'est pas vraiment une réponse (juste plus de questions dans un sens). C'est la preuve que le compilateur n'importer les méthodes avec signature.

package test;

public class Foo 
{
    public static void equal(Object o1)
    {
        System.out.println("Foo.equal Object");
    }   

    public static void equal(Integer o1)
    {
        System.out.println("Foo.equal Integer");
    }   
}

package test;

public class Bar 
{
    public static void equal(Number o1)
    {
        System.out.println("Bar.equal Number");
    }   
}

import static test.Foo.equal;
import static test.Bar.equal;

public static void main(String args[]) throws Exception
{
    equal((Object)null);
    equal((Number)null);
    equal((Integer)null);
}

Output: 
Foo.equal Object
Bar.equal Number
Foo.equal Integer

Cela peut également être lié. Une méthode dans un intérieur de classe 'caché' une méthode statique à l'extérieur de la classe avec une signature différente.

http://ideone.com/pWUf1

On dirait que le compilateur a différents endroits où chercher des méthodes, et il vérifie un par un, mais seulement des recherches par nom, conduisant à un arrêt prématuré de la recherche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X