Правильно делать приватные методы Java статическими или нет? Плюсы и минусы каждого варианта?
1,00
р.
р.
В английской версии видел этот вопрос, но в русской версии не нашел. Часто некоторые программисты используют private static методы, чтобы показать что этот приватный метод не использует никаких переменных и методов класса, другие наоборот против этого подхода так считают его не правильным использованием ООП (речь только о приватных методах класса, не использующих никаких переменных класса и других не статических методов). То есть, что правильнее по вашему использовать так public class MyClass { private static void func1() { // со статик ... } } или так public class MyClass { private void func1() { // без статик ... } } ? Я говорил о тех методах, которые не используют (и не могут использовать) поля напрямую, например метод boolean isValid(T str), который вызывается в других методах класса для множества различных объектов, и которые нужны исключительно только для этого класса и выносить их в отдельный Utils класс нет смысла. Как пример такого метода это hugeCapacity в ArrayList из Oracle JDK 8: private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError() return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE } P.S. Любые цитаты и ссылки на известных Java авторов очень помогут решить вопрос (скажем, я знаю, что в ArrayList из Oracle JDK, где авторы довольно известные Josh Bloch и Neal Gafter, используется private static методы). Может вы знаете другие подтверждения той или иной точки зрения? То есть идеальный ответ, это ответ с цитатами на книги / статьи известных Java авторов или тех кто занимался теорией ООП или проектирования.
Ответ Руководствуйтесь смыслом, и только им. Строение ваших классов должно отображать не техническую возможность сделать так или иначе (иногда экземплярные методы можно объявить статическими), а отношения между объектами в доменной области. Это и правда база всего ООП (а где ж ещё следовать ООП, если не в Джаве?). Я не могу привести цитату из умной книги по этому поводу. Но сама идея делать сигнатуру метода зависимой не от его смысла, а от подробностей его конкретной имплементации кажется мне грубым хаком. Даже если это внутренний, приватный метод. Если в публичных методах, предназначенных другим, мы пишем правильно, то почему в методах, предназначенных для себя, писать неправильно? Для отступления от правильного дизайна нужны веские причины. У ArrayList такие причины есть: он используется в миллионах проектов, и среди них есть критические по времени куски, и там выигрыш пары тактов играет серьёзную роль. Но для большинства классов, которые мы пишем, количество вызовов в наших программах не исчисляются десятками тысяч в секунду, и отступление от правильного дизайна вряд ли оправдано.
Если метод относится к конкретному объекту, то объявляйте его экземплярным методов вне зависимости от того, обращается он к нестатическим полям и this или нет. Если метод общий для всего класса, и не имеет смысла в контексте отдельного экземпляра, объявляйте его статическим. Если метод вовсе не относится к классу, вынесите его во вспомогательный класс.
Пример: оружие рыцаря — меч. Да, у всех рыцарей одинаковое оружие. Тем не менее, метод, выдающий оружие — это очевидно экземплярный метод. Далее, рыцари не пользуются кинжалами. Поэтому геттер кинжала у рыцаря возвращает null. Это тоже экземплярный метод. class Knight : Warrior { private Weapon createMainWeapon() { return new Sword() } private Dagger getDagger() { return null } } Далее, количество рыцарей. Соответственно оно не имеет смысла в контексте одного рыцаря, значит, является статическим методом. class Knight : Warrior { static int numberOfKnights public Knight() { numberOfKnights++ } public static int getNumber() { return numberOfKnights } } Ну и наконец, метод, который выясняет, в порядке ли амуниция перед битвой, вообще не относится к сфере деятельности рыцаря. Пусть этим займётся оруженосец! class Squire { Knight master public prepareForBattle() { ... } }