В чем разница между классом как окончательным и конструктором класса как частным

В чем именно разница между окончательным классом и наличием конструктора класса как частного.

Я знаю, что оба не могут быть подклассами (поправьте меня, если я ошибаюсь). Есть ли у них разница?


person Deva    schedule 07.09.2011    source источник


Ответы (6)


Окончательный класс не может быть расширен. Это предотвращает это

final class FinalClass {

}

// and later

class ExtendedClass extends FinalClass { // ERROR

}

Это полезно для таких вещей, как String — вы бы не хотели, чтобы кто-то мог перезаписать логику String, одного из наиболее часто используемых объектов, и иметь возможность, о, я не знаю, добавить сеть и отправить все строки обратно вы используете. Это возможно сделать, если вы можете расширить String.

Частный конструктор нельзя вызывать вне класса.

class PrivateCons {

    private PrivateCons() {

    }
}

// later
PrivateCons pc = new PrivateCons(); // ERROR

Часто это работает так: (java.lang.Math — хороший пример)

class FuncLib {
    private FuncLib() { } // prevent instantiation
    public static void someFunc(...) { }
    public static int anotherFunc(...) { }
}

Или это в конечном итоге работает так // Integer делает это на самом деле

class VerySpecial {

    private static Map<String,VerySpecial> cache;

    public static VerySpecial generate(String data) {
        VerySpecial result = cache.get(data);
        if(result == null) {
            result = new VerySpecial(data);
            cache.put(data,result);
        }
        return result;
    }

    private String data;

    private VerySpecial() { }

    private VerySpecial(String data) { this.data = data}

}

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

person corsiKa    schedule 07.09.2011
comment
можете ли вы расширить класс, все конструкторы которого являются закрытыми? - person MozenRath; 07.09.2011
comment
Если все ваши конструкторы закрыты, вы не сможете расширить класс - person Adam Batkin; 07.09.2011
comment
Сможет ли JVM оптимизировать конечный класс лучше, чем класс со всеми частными конструкторами? (Не то, чтобы мы должны заботиться об оптимизации, если нет реальной, измеримой проблемы, но из интереса...). - person Russell; 07.09.2011
comment
@glowCoder Вы хотите сказать, что для конечных классов мы можем создать экземпляр класса, но для класса с частным конструктором мы не можем создать экземпляр. - person Deva; 07.09.2011
comment
@Russell хорошо, да, это будет лучше оптимизировать, но вы также потеряете много рычагов. Я полагаю, вы всегда можете сделать его не окончательным, если вам нужно его расширить, поскольку это не нарушит какой-либо API (как если бы вы сделали его окончательным после выпуска). - person corsiKa; 07.09.2011
comment
@Adam Строго говоря, вы можете создавать внутренние классы, которые расширяют внешний класс, но да, помимо этого вы не можете расширять класс. - person Arnout Engelen; 07.09.2011
comment
Так что я до 3 отрицательных голосов по этому поводу. Я чувствовал, что решил все проблемы, которые были подняты, как в механике, так и в том, как они обычно используются. Есть ли что-нибудь еще, что можно сделать, чтобы улучшить его? Я был бы рад решить другие вопросы, оставленные в комментариях. :-) - person corsiKa; 07.09.2011

Создание экземпляра

  • Вы не можете создать экземпляр класса с помощью частного конструктора. Но вы можете использовать его как служебный класс со статическими методами.
  • Конечный класс может быть создан, но не расширен, очевидно, вы не можете расширить класс с помощью частного конструктора, так как неявный вызов super() завершится ошибкой.

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

person Farmor    schedule 07.09.2011
comment
Вы можете создать экземпляр класса с помощью частного конструктора. Это необходимо, например, для шаблона MyObject.newInstance(), где newInstance вызывает приватный конструктор. (Это необходимо, когда вы не можете использовать обычный конструктор, потому что он приведет к утечке ссылки this.) - person toto2; 07.09.2011
comment
newInstance() вызовет исключение IllegalAccessException, если вы не использовали конструктор с setAccessible(true). - person Peter Lawrey; 07.09.2011
comment
@Питер Извини. Я просто имел в виду самодельный newInstance, ничего с рефлексией. Это просто статический метод, который возвращает новую сборку экземпляра из частного конструктора. - person toto2; 07.09.2011
comment
@toto2, вы можете использовать Constructor.newInstance() (после смены доступа), но не MyClass.class.newInstance() - person Peter Lawrey; 07.09.2011

Если вы не хотите, чтобы ваш класс был подклассом, используйте final. Если вы не хотите, чтобы другие классы создавали экземпляр вашего класса, а хотите контролировать, как создается и поддерживается объект, вы используете частный конструктор.

person Bobby Fisher    schedule 07.09.2011

Наличие только частных конструкторов сильнее, чем наличие конечного класса.

Подробно: наличие только частных конструкторов в классе A сильно влияет на создание объекта. Обычно вы используете фабричный метод. Вы по-прежнему можете создавать экземпляры A без фабричного метода, используя приемы, такие как clone() или рефлексивный вызов закрытого конструктора. Но подклассы невозможны, потому что конструктор подкласса должен иметь возможность вызывать super(). Это было бы возможно только внутри вложенного класса внутри A.

Часто имеет смысл иметь только частные конструкторы, например. для управления экземплярами с помощью фабричных методов, например. для синглтонов (см. Эффективный Java, пункт 3). Но даже в этом случае я не вижу причин не писать «окончательный класс», хотя бы для документации, чтобы читатели сразу поняли, что создание подклассов не разрешено.

person DaveFar    schedule 07.09.2011

Доступ к private членам можно получить через внутренние классы.

public class Outer {
  private Outer() {
    System.out.println("Outer()");
  }

  static class Inner extends Outer {
    {
      System.out.println("Inner()");
    }
  }

  public static void main(String... args) {
    new Inner();
  }
}

отпечатки

Outer()
Inner()

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

person Peter Lawrey    schedule 07.09.2011

Окончательный класс/метод никогда не может быть унаследован/переопределен и вызовет ошибку компиляции, где класс с частным конструктором также вызовет компиляцию, которая «Для вашего класса нет конструктора по умолчанию», и как только вы добавите не окончательный конструктор и вызовите это из вашего дочернего класса, ошибки не будет.

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

public class Singleton{    
private static final Singleton instance = new Singleton();

//private constructor to avoid client applications to use constructor
private Singleton(){}

public static Singleton getInstance(){
    return instance;
}}

И, например, класс String в java является конечным классом.

person srishti singh    schedule 03.06.2017