Является ли вызов статических методов через объект "плохой формой"? Зачем?
В недавнем вопросе кто-то спросил о статических методах, и в одном из ответов было сказано, что вы обычно вызываете их примерно так:
MyClassName.myStaticMethod();
В комментариях об этом также говорится, что вы также можете вызвать его через объект с:
MyClassName myVar;
myVar.myStaticMethod();
но это считалось дурным тоном.
Теперь мне кажется, что это может сделать мою жизнь проще, поэтому мне не нужно беспокоиться о том, что статично или нет (а).
Есть ли проблема с вызовом статических функций через объект? Очевидно, вы не захотите создавать новый объект, просто чтобы назвать его:
Integer xyzzy;
int plugh = xyzzy.parseInt ("42", 10);
Но если у вас уже есть объект нужного типа, есть ли проблема в его использовании?
(а) Очевидно, я не могу вызвать нестатический метод с:
MyClassName.myNonStaticMethod();
но это не та проблема, о которой я здесь спрашиваю.
4 ответа
Комментарий о плохой форме исходит из Соглашения о кодировании для Java
См. http://www.oracle.com/technetwork/java/codeconventions-137265.html
Причина этого, если вы подумаете об этом, заключается в том, что метод, будучи статичным, не принадлежит ни одному конкретному объекту. Поскольку он принадлежит классу, почему вы хотите поднять конкретный объект до такого особого статуса, который, по-видимому, принадлежит методу?
В вашем конкретном примере вы можете использовать существующее целое число, через которое можно вызвать parseInt
(то есть это разрешено в Java), но это фокусирует внимание читателя на этом конкретном целочисленном объекте. Это может сбивать с толку читателей, и поэтому руководство состоит в том, чтобы избегать этого стиля.
Чтобы облегчить жизнь программиста, переверните его и спросите, что облегчает жизнь читателю? Есть два вида методов: экземплярный и статический. Когда вы видите выражение C.m
и ты знаешь C
это класс, вы знаете m
должен быть статическим методом. Когда ты видишь x.m
(где x
это экземпляр), вы не можете сказать, но это похоже на метод экземпляра, и поэтому большинство всех резервируют этот синтаксис только для методов экземпляра.
На мой взгляд, реальный вариант использования, который делает это настолько нечитаемым, выглядит примерно так. Что печатает код ниже?
//in a main method somewhere
Super instance = new Sub();
instance.method();
//...
public class Super {
public static void method() {
System.out.println("Super");
}
}
public class Sub extends Super {
public static void method() {
System.out.println("Sub");
}
}
Ответ в том, что он печатает "Super", потому что статические методы не являются виртуальными. Даже если instance
это Sub
компилятор может использовать только тип переменной, которая Super
, Однако, вызывая метод через instance
скорее, чем Super
вы тонко намекаете на то, что он будет виртуальным.
На самом деле, разработчик читает instance.method()
пришлось бы посмотреть на объявление метода (его сигнатуру), чтобы узнать, какой метод он на самом деле вызывается. Вы упоминаете
мне кажется, что это может сделать мою жизнь проще, поэтому мне не нужно беспокоиться о том, что статично или нет
Но в вышеприведенном случае контекст на самом деле очень важен!
Я могу с достаточной уверенностью сказать, что разработчики языка допустили ошибку, допустив это в первую очередь. Держись подальше.
Это вопрос общения. Вызов метода для экземпляра подразумевает, что вы действуете с / с этим конкретным экземпляром, а не с / с классом экземпляра.
Это может привести в замешательство, когда у вас есть объект, который наследуется от другого объекта, переопределяя его статический метод. Особенно, если вы ссылаетесь на объект как на класс его предка. Не было бы очевидно, какой метод вы используете.