Вызов статического метода - PullRequest
16 голосов
/ 13 апреля 2010

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

Ответы [ 5 ]

34 голосов
/ 13 апреля 2010

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

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.

20 голосов
/ 13 апреля 2010

Да, вы можете вызвать метод 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.Цитата из руководства :

Так когда же следует использовать статический импорт? Очень экономно! Используйте его только тогда, когда у вас возникнет искушение объявить локальные копии констант или злоупотребить наследованием (Антипаттерн Constant Interface).Другими словами, используйте его, когда вам требуется частый доступ к статическим членам одного или двух классов. Если вы чрезмерно используете функцию статического импорта, она может сделать вашу программу нечитаемой и не поддерживаемой , загрязняя ее пространство имен всеми 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, верно?

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

From JLS 15.12.4.4 Метод Locate для вызова :

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

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

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

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

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

См. также:

0 голосов
/ 13 апреля 2010

Да.

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();
  }
}  
0 голосов
/ 13 апреля 2010

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

открытый класс 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();
}

}

0 голосов
/ 13 апреля 2010

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

...