По сути, я считаю, что разработчики Java допустили ошибку при разработке языка, и уже слишком поздно, чтобы исправить это из-за проблем совместимости. Да, это может привести к очень вводящему в заблуждение коду. Да, вам следует избегать этого. Да, вы должны убедиться, что ваша IDE настроена на то, чтобы рассматривать ее как ошибку, IMO. Если вы когда-нибудь разрабатываете язык самостоятельно, помните об этом, как пример того, чего следует избегать:)
Просто чтобы ответить на точку зрения DJClayworth, вот что разрешено в C #:
public class Foo
{
public static void Bar()
{
}
}
public class Abc
{
public void Test()
{
// Static methods in the same class and base classes
// (and outer classes) are available, with no
// qualification
Def();
// Static methods in other classes are available via
// the class name
Foo.Bar();
Abc abc = new Abc();
// This would *not* be legal. It being legal has no benefit,
// and just allows misleading code
// abc.Def();
}
public static void Def()
{
}
}
Почему я думаю, что это вводит в заблуждение? Потому что, если я посмотрю на код someVariable.SomeMethod()
, я ожидаю, что он использует значение someVariable
. Если SomeMethod()
является статическим методом, это ожидание недопустимо; код обманывает меня. Как это может быть хорошая вещь?
Как ни странно, Java не позволяет использовать потенциально неинициализированную переменную для вызова статического метода, несмотря на тот факт, что единственная информация, которую он собирается использовать, - это объявленный тип переменной. Это непоследовательный и бесполезный беспорядок. Зачем это разрешать?
РЕДАКТИРОВАТЬ: Это редактирование является ответом на ответ Клейтона, который утверждает, что он разрешает наследование для статических методов. Это не так. Статические методы просто не полиморфны. Вот короткая, но полная программа, демонстрирующая, что:
class Base
{
static void foo()
{
System.out.println("Base.foo()");
}
}
class Derived extends Base
{
static void foo()
{
System.out.println("Derived.foo()");
}
}
public class Test
{
public static void main(String[] args)
{
Base b = new Derived();
b.foo(); // Prints "Base.foo()"
b = null;
b.foo(); // Still prints "Base.foo()"
}
}
Как видите, значение времени выполнения b
полностью игнорируется.