Czy konstruktorzy zawsze muszą być jawni? [duplikat]

To pytanie ma już odpowiedź tutaj:

Moje pierwsze pytanie brzmi:]}
   class Explain() {
        public Explain() {
      }
   }

Czy konstruktor powinien zawsze deklarować jako publiczny?

Co jeśli stworzę private Konstruktor.

Zawsze widziałem, że konstruktory są w domyśle public. Więc dlaczego private Konstruktor jest przydatna? Albo nie jest to w ogóle przydatne. Ponieważ nikt nigdy nie mógł go nazwać, ani nigdy nie stworzyć obiektu(z powodu konstruktora private)! I to jest moje drugie pytanie.

Author: Dhanuka, 2015-06-23

11 answers

Nie, konstruktory mogą być public, private, protected lub default (Brak modyfikatora dostępu).

Zrobienie czegoś private nie oznacza, że nikt nie ma do niego dostępu. To znaczy, że nikt poza klasą nie ma do niego dostępu. Więc private konstruktor też jest przydatny.

Jednym z zastosowań konstruktora private jest obsługa klas singleton. Klasa singleton to taka, która ogranicza liczbę tworzonych obiektów do jednej. Używając konstruktora private możemy zapewnić, że nie więcej niż jeden obiekt może być stworzony na raz.

Przykład-

public class Database {

    private static Database singleObject;
    private int record;
    private String name;

    private Database(String n) {
        name = n;
        record = 0;
    }

    public static synchronized Database getInstance(String n) {
        if (singleObject == null) {
            singleObject = new Database(n);
        }

        return singleObject;
    }

    public void doSomething() {
        System.out.println("Hello StackOverflow.");
    }

    public String getName() {
        return name;
    }
}

więcej informacji o modyfikatory dostępu.

 69
Author: Dhanuka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:22

Tak, konstruktory mogą mieć dowolny access specifier/access modifier.

Konstruktory prywatne są przydatne do tworzenia klas singleton.

Singleton - klasa singleton jest klasą, w której można utworzyć tylko jeden obiekt w czasie wykonywania (na JVM).

Prostym przykładem klasy singleton jest -

class Ex {
    private static Ex instance;
    int a;
    private Ex() {
        a = 10;
    }
    public static Ex getInstance() {
        if(instance == null) {
            instance = new Ex();
        }
        return instance;
    }
}

Uwaga, dla powyższej klasy, jedynym sposobem uzyskania obiektu (poza tą klasą) jest wywołanie funkcji getInstance (), która utworzyłaby tylko jedną instancja i zwracaj to dalej.

Należy również pamiętać, że nie jest to bezpieczne dla wątków.

 9
Author: Anand S Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 11:02:16

Konstruktory mogą być publiczne, domyślne lub prywatne i wszystko zależy od tego, co chcesz z nimi zrobić.

Na przykład, jeśli definiujesz klasę Singleton, lepiej Ukryj konstruktor (co oznacza uczynienie go prywatnym, aby był dostępny tylko dla klasy, do której należy), aby uniemożliwić innym klasom tworzenie instancji twojej klasy według ich woli.

Możesz chcieć zadeklarować wartość domyślną, powiedzmy, dla celów testowych, aby przypadki testowe w tym samym pakiecie mogły uzyskaj dostęp.

Bardziej szczegółowe informacje można znaleźć tutaj

 7
Author: Alp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 07:11:46

Nie ma reguły, aby konstruktor był publiczny .Ogólnie definiujemy go jako publiczny tylko dlatego, że chcielibyśmy utworzyć instancję z innych klas .

Prywatny konstruktor oznacza: "nie pozwalam nikomu tworzyć mojej instancji poza mną". Więc zwykle robisz to, gdy chcesz mieć wzór Singletona.

Poniżej znajduje się klasa w JDK, która używa prywatnego konstruktora .

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    public static Runtime getRuntime() {
        return currentRuntime;
    }

    // Don't let anyone else instantiate this class
    private Runtime() {
    }
}
 5
Author: Reddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 07:20:00

Nie,konstruktory mogą używać dowolnego modyfikatora dostępu, w tym prywatnego. (Prywatny konstruktor oznacza, że tylko kod wewnątrz samej klasy może utworzyć instancję obiektu tego typu, więc jeśli Klasa prywatnego konstruktora chce zezwolić na wystąpienie klasa, która ma być użyta, musi zapewniać statyczną metodę lub zmienną, która umożliwia dostęp do instancji utworzonej z poziomu klasy.)

Przykład

class Alpha {
   static String s = " ";
   protected Alpha() { s += "alpha "; }
 }
 class SubAlpha extends Alpha {
   private SubAlpha() { s += "sub "; }
 }
 public class SubSubAlpha extends Alpha {
   private SubSubAlpha() { s += "subsub "; }
   public static void main(String[] args) {
     new SubSubAlpha();
     System.out.println(s);
   }
 }

Wyjście powyższego programu będzie

Alpha subsub

 5
Author: Nitesh Soomani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 07:46:39

Konstruktory mogą mieć wszelkiego rodzaju modyfikatory dostępu. Użycie różnych modyfikatorów dostępu na konstruktorach jest różne.

Tworzysz konstruktor public, jeśli chcesz, aby klasa została utworzona z dowolnego miejsca.

Tworzysz konstruktor protected jeśli chcesz, aby klasa była dziedziczona, a jej dziedziczone klasy były instancjonowane.

Tworzysz konstruktor private jeśli chcesz, aby klasa była tworzona z własnych elementów, zwykle jako statyczny blok lub statyczna metoda. Informatyka oznacza to, że przejmujesz kontrolę nad tworzeniem instancji klasy i stosujesz pewną regułę dotyczącą tworzenia instancji. Przykładem użycia prywatnego konstruktora jest singleton design pattern.

 4
Author: A.v,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 07:46:47

Zgadzam się z poprzednimi odpowiedziami, że Singleton jest dobrym przykładem klasy posiadającej prywatny konstruktor. Polecam jednak inną implementację: a thread safe Singleton:

/**
 * Thread safe singleton
 */
public class Singleton {

    private static volatile Singleton instance = null;

    /**
     * Private constructor
     */
    private Singleton() {
    }

    /**
     * Gets the Instance of the Singleton in a thread safe way.
     * @return
     */
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Używanie Singletona w bezpieczny sposób wątku zabezpieczy Cię wiele bólu w kodzie równoległym.

 4
Author: Marc Giombetti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 08:39:51

Konstruktor ma być przynajmniej chroniony lub nawet prywatny podczas tworzenia, na przykład, niestandardowych klas fabrycznych, takich jak:

public final class MyFactory {
  private MyFactory(){} // this one prevents instances of your factory
}

public static void doSomething(){} // access that with MyFactory.doSomething

Zauważ, że jest to tylko jeden przykład pokazujący, kiedy konstruktor nie powinien być publiczny.

 3
Author: Arthur Eirich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 07:19:20

Większość z tych odpowiedzi odnosi się do klasy singleton lub factory. Innym razem, gdy pojawia się prywatny konstruktor, jest (na przykład) w java.lang.Klasa matematyczna , gdzie wszystko jest statyczne i nikt nigdy nie powinien wywoływać konstruktora (łącznie z samą klasą). Posiadając prywatny konstruktor, uniemożliwiasz komukolwiek spoza klasy wywołanie konstruktora. (To nie uniemożliwia komuś wewnątrz klasy wywołania konstruktora, ale potem łamie własną regułę.)

 1
Author: Teepeemm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 16:16:19

Inni zauważyli, że konstruktory mogą mieć modyfikatory dostępu; aspekt jeszcze nie wymieniony jest, że modyfikatory aspektu w konstruktorze kontrolują dwa bardzo różne aspekty budowy, ale nie pozwalają na ich oddzielne sterowanie: {18]}

  1. kto może tworzyć instancje z ClassName i jakich konstruktorów może używać.
  2. kto może tworzyć rozszerzenia z ClassName i jakie konstruktory mogą użyj.

Zarówno Java, jak i. NET wymagają, aby odpowiedzi na te dwa pytania były razem; jeśli klasa nie jest final (lub sealed) i pozwala konstruktorowi na użycie zewnętrznego kodu do tworzenia nowych instancji, to Zewnętrzny kod będzie miał całkowitą swobodę używania tego samego konstruktora do tworzenia typów pochodnych.

W wielu przypadkach może być właściwe, aby klasa miała tylko konstruktory package-private (internal), ale wystawiała publiczne metody zwracające nowe instancje. Taki metoda może być użyta, jeśli projektuje się od podstaw Typ typu String; pakiet zawierający {[5] } może zdefiniować go jako typ abstrakcyjny, ale zawiera konkretne typy pochodne, takie jak AsciiString i UCS16String, które przechowują swoją zawartość odpowiednio jako byte[] i Char[]; metody zwracające String mogą następnie zwrócić jeden z pochodnych w zależności od tego, czy łańcuch zawiera znaki spoza zakresu ASCII. Jeśli ani String, ani żadne typy pochodne nie ujawniają żadnych konstruktorów poza swoim pakietem, a wszystkie typy pochodne w pakiecie zachowują się jak łańcuch znaków, wtedy kod, który otrzymuje referencję typu String, może oczekiwać, że będzie zachowywał się jak łańcuch znaków (np. gwarantując, że wszelkie obserwacje dotyczące jego wartości na zawsze pozostaną prawdziwe). Ujawnienie konstruktorów poza pakietem umożliwiłoby jednak typom pochodnym zachowanie się w dziwny i dziwaczny sposób (np. zmiana ich zawartości po sprawdzeniu i zatwierdzeniu).

Od a perspektywa składniowa, umiejętność mówienia Fnord foo = new Fnord(123); jest trochę ładniejsza niż mówienie Fnord foo = Fnord.Create(123);, ale Klasa Fnord, która wymaga tej ostatniej składni, może zachować znacznie lepszą kontrolę nad procesem tworzenia obiektu.

 1
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 17:19:08

Proste wyjaśnienie jest takie, że jeśli nie ma konstruktora w klasie, kompilator automatycznie tworzy konstruktor domyślny.

Konstruktor nie zawsze jest zadeklarowany jako publiczny, może być również prywatny, chroniony lub domyślny.

Konstruktory prywatne uniemożliwiają klasie pełne i wyraźnie wyrażone / reprezentowane przez jej wywołujące. W takim przypadku przydatne są konstruktory prywatne. A jeśli nie chcemy, aby nasza klasa była podklasowana, możemy użyć konstruktorów prywatnych.

 0
Author: Nimishan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 15:50:15