Вызов статического метода

Можно ли вызвать статический метод без упоминания имени класса в Java?

Ответы

Ответ 1

Да, вы можете. Проверьте статический импорт. Вы должны указать имя класса в инструкции import, но после этого вам не нужно to.e.g. из связанной статьи:

import static java.lang.Math.abs;
import static java.lang.Math.max;

int xDist = abs(destination.getX() - x);
int yDist = abs(destination.getY() - y);
return max(xDist, yDist);

Представлен в Java 5.

Ответ 2

Да, вы можете вызвать метод static без упоминания имени класса. Там import static (см. JLS 7.5.4 для точного механизма), но даже без него, если имя может быть разрешено (см. JLS 15.12.1 для точного механизма) без полной квалификации класса, он будет работать.

Следующий код компилирует и печатает "Hello world!", как ожидалось.

import static java.lang.System.out;

public class Test {
   static String greeting() {
      return "Hello world!";
   }
   public static void main(String[] args) {
      out.println(greeting());
   }
}

out в инструкции println фактически является полем доступа к static класса java.lang.System, а не static, но тем не менее он имеет доступ к элементу static. greeting() - это вызов метода static, и имя класса можно опустить, поскольку его ссылка может быть разрешена без полной квалификации имени.


Теперь позвольте спросить, хорошая ли это идея. Если вы не вызываете метод static из своего класса, не рекомендуется вообще опускать имя класса!!!

Сначала сфокусируйтесь на static import. Цитата из guide:

Итак, когда вы должны использовать статический импорт? Очень экономно! Используйте его только тогда, когда в противном случае у вас возникнет соблазн объявить локальные копии констант или злоупотреблять наследованием (Constant Interface Antipattern). Другими словами, используйте его, когда вам требуется частый доступ к статическим членам из одного или двух классов. Если вы злоупотребляете функцией статического импорта, это может сделать вашу программу нечитаемой и недостижимой, загрязняя ее пространство имен всеми членами static, которые вы импортируете. Читатели вашего кода (включая вас, через несколько месяцев после того, как вы его написали) не будут знать, из какого класса приходит статический член. Импорт всех статических элементов из класса может быть особенно вреден для удобочитаемости; если вам нужен только один или два члена, импортируйте их отдельно. При правильном использовании статический импорт может сделать вашу программу более читаемой, удалив шаблон повторения имен классов.

В следующем примере дело усиливается:

class Base {
    void task1() {
        System.out.println("Base.task1");
    }
    static void task2() {
        System.out.println("Base.task2");
    }
}

class Child extends Base {
    void task1() {
        System.out.println("Child.task1");          
    }
    static void task2() {
        System.out.println("Child.task2");
    }       
}

//....
Base sweetChildOMine = new Child();
sweetChildOMine.task1(); // prints "Child.task1"
sweetChildOMine.task2(); // prints "Base.task2"

Какой сюрприз! Вы думаете, что, поскольку sweetChildOMine имеет ссылку на экземпляр Child, sweetChildOMine.task2() должен печатать "Child.task2", потому что он переопределяется классом Child, правильно?

НЕПРАВИЛЬНО! A static метод нельзя переопределить! Он может быть скрыт только подклассом! На самом деле, если вы попытались сделать правильную вещь и добавили аннотацию @Override к task2, она не скомпилировалась бы!

От JLS 15.12.4.4 Найдите способ для вызова:

Если режим вызова static, целевая ссылка не требуется, и переопределение недопустимо. Метод m класса T является вызываемым.

На самом деле эта проблема рассматривается в Java Puzzlers Пазл 48: все, что я получаю, статично. Вывод, приведенный в конце головоломки, таков:

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

Лучше всего следовать всем этим рекомендациям, поэтому:

  • Если вы вызываете метод static в своем классе, не квалифицируйте
  • В противном случае, с именем класса
    • Если вы делаете это много в одном классе, рассмотрите static import этого конкретного метода
      • Попробуйте static import всех членов с *
    • Никогда не квалифицируйте с помощью выражения
  • Не скрывайте метод static; вы не можете @Override его, это вызовет только путаницу

См. также:

Ответ 3

Да, добавив Brian Agnew, вы также можете вызвать статические методы через экземпляр этого типа класса.

Ответ 4

Да.

class CallStaticMethodTest { 
   public static void staticMethodOne() {
       System.out.println("Static method one");
   }

   // Invoke from a non-static method
   public void instanceMethodOne() {
        staticMethodOne();// Calling static method without mentioning the class name 
   }

   // Invoke from another static method:
   public static void staticMethodTwo() {
       staticMethodOne();
  }
}  

Ответ 5

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

открытый класс TestStatic {

static void hello()
{
   System.out.println("Hello World");
}
static void hello2()
{
   hello();
   System.out.println("Welcome to java");
}
public static void main(String[] args)
{
   hello2();
}

}