Java финальный абстрактный класс - PullRequest
37 голосов
/ 08 марта 2012

У меня довольно простой вопрос:

Я хочу иметь класс Java, который предоставляет один публичный статический метод, который что-то делает.Это просто для целей инкапсуляции (чтобы все было важно в пределах одного отдельного класса) ...

Этот класс не должен быть ни создан, ни расширен.Это заставило меня написать:

final abstract class MyClass {
   static void myMethod() {
      ...
   }
   ... // More private methods and fields...
}

(хотя я знал, что это запрещено).

Я также знаю, что могу сделать этот класс только окончательным и переопределить стандартный конструктор, делая егоprivate.

Но мне кажется, что это больше похоже на «Обходной путь», и СЛЕДУЕТ делать это последним абстрактным классом ...

И я ненавижу обходные пути.Так что для моего же интереса: есть ли другой, лучший способ?

Ответы [ 9 ]

50 голосов
/ 08 марта 2012

Вы не можете стать намного проще, чем использовать enum без экземпляров.

public enum MyLib {;

   public static void myHelperMethod() { }
}

Этот класс является окончательным, без явных экземпляров и закрытого конструктора.

Этообнаруживается компилятором, а не как ошибка времени выполнения.(в отличие от исключения)

46 голосов
/ 08 марта 2012

Ссылка: Эффективное Java, издание 2, пункт 4 «Обеспечение неотъемлемости с помощью частного конструктора»

public final class MyClass { //final not required but clearly states intention
    //private default constructor ==> can't be instantiated
    //side effect: class is final because it can't be subclassed:
    //super() can't be called from subclasses
    private MyClass() {
        throw new AssertionError()
    }

    //...
    public static void doSomething() {}
}
6 голосов
/ 08 марта 2012

Нет, вам нужно создать личный пустой конструктор, который выдает исключение в своем теле. Java - это объектно-ориентированный язык, а класс, создание которого никогда не требуется, сам по себе является обходным решением! :)

final class MyLib{
    private MyLib(){
        throw new IllegalStateException( "Do not instantiate this class." );
    }

    // static methods go here

}
4 голосов
/ 08 марта 2012

Нет, абстрактные классы предназначены для расширения. Используйте приватный конструктор, это не обходной путь - это способ сделать это!

2 голосов
/ 21 октября 2014

Объявите конструктор класса private. Это обеспечивает непостоянство и предотвращает создание подклассов.

1 голос
/ 08 марта 2012

Предложения ассилий (все версии Java) и Питера Лоури (> = Java5) являются стандартным способом в этом случае.

Однако я хотел бы обратить ваше внимание на то, что предотвращение расширения статического служебного класса - это очень окончательное решение, которое может преследовать вас позже, когда вы обнаружите, что у вас есть связанные функции в другом проекте, и вы ' на самом деле я хочу расширить его.

Я предлагаю следующее:

public abstract MyClass {

    protected MyClass() {
    }

    abstract void noInstancesPlease();

    void myMethod() {
         ...
    }
    ... // More private methods and fields...

}

Это идет против устоявшейся практики, поскольку позволяет расширять класс при необходимости, по-прежнему предотвращает случайное создание экземпляров (вы даже не можете создать анонимный экземпляр подкласса, не получив очень явной ошибки компилятора).

Всегда писает о том, что служебные классы JDK (например, java.util.Arrays) фактически были сделаны окончательными. Если вы хотите, чтобы у вас был собственный класс Arrays с методами для, скажем, сравнения, вы не можете, вы должны создать отдельный класс. Это распространит функциональность, которая (IMO) принадлежит друг другу, и должна быть доступна через один класс. Это оставляет вас либо с дико распределенными служебными методами, либо вам придется продублировать каждый из методов в вашем собственном классе.

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

0 голосов
/ 28 мая 2016

Это очень простое объяснение на простом английском языке. Создание абстрактного класса не может быть реализовано и может быть только расширено. Окончательный класс не может быть расширен. собираюсь когда-нибудь использовать этот класс, и каково, на самом деле, основание ставить себя в такую ​​ловушку?

0 голосов
/ 23 июня 2015

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

0 голосов
/ 17 апреля 2014

Проверить этот справочный сайт ..

Не возможно. Абстрактный класс без наследования бесполезен и, следовательно, приведет к ошибке времени компиляции.

Спасибо ..

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