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

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


person user315459    schedule 13.04.2010    source источник
comment
Хочешь объяснить немного больше о том, что ты имеешь в виду? Я могу навскидку придумать как минимум три совершенно разных интерпретации...   -  person Donal Fellows    schedule 13.04.2010


Ответы (5)


Да, ты можешь. Ознакомьтесь с статическим импортом. Вы должны указать имя класса в операторе 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.

person Brian Agnew    schedule 13.04.2010

Да, вы можете вызвать метод static без упоминания имени класса. Вот import static (см. JLS 7.5.4 для точного механизма), но и без него, если имя может быть разрешено (см. 15.12" rel="nofollow noreferrer">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. Цитата из руководства:

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

Из JLS 15.12.4.4 Найдите метод для вызова< /а>:

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

На самом деле эта проблема описана в Java Puzzlers Puzzle 48: All I Get Является статическим. Вывод, данный в конце головоломки, таков:

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

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

  • Если вы вызываете метод static в его собственном классе, не уточняйте
  • Otherwise, qualify with the class name
    • If you're doing this a lot within one class, consider static import of that specific method
      • Try not to static import all members with *
    • Никогда не уточняйте выражением
  • Не прячьте метод static; вы не можете @Override этого, это только вызовет путаницу

Смотрите также:

person polygenelubricants    schedule 13.04.2010

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

person GuruKulki    schedule 13.04.2010
comment
Хм? ...without mentioning the class name - person wheaties; 13.04.2010
comment
Я не согласен, что это не очень хорошая идея. Есть определенные типы команд, которые действительно должны быть статическими. При использовании этих команд, если вы хотите разрешить различные реализации, передача экземпляра класса, реализующего метод, является единственным разумным способом. Конечно, было бы значительно удобнее, если бы в Java была возможность передавать тип класса и (легко) вызывать один из его статических методов. - person RHSeeger; 13.04.2010
comment
Я согласен, что это не очень хорошая идея, но просто хотел сказать, что это тоже возможно. - person GuruKulki; 13.04.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();
}

}

person Abimbola    schedule 13.04.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();
  }
}  
person OscarRyz    schedule 13.04.2010