Ma première question est -
class Explain() {
public Explain() {
}
}
Le constructeur doit-il toujours être déclaré public?
Et si je crée un constructeur private
.
J'ai toujours vu que les constructeurs sont implicitement public
. Alors pourquoi le constructeur private
est utile? Ou n'est-ce pas utile du tout. Parce que personne ne pourrait jamais l'appeler, ou jamais créer un objet (à cause du constructeur private
)! Et c'est ma deuxième question.
Non, Les constructeurs peuvent être public
, private
, protected
ou default
(pas de modificateur d'accès du tout).
Faire quelque chose private
ne signifie pas que personne ne peut y accéder. Cela signifie simplement que personne en dehors de la classe ne peut y accéder. Le constructeur private
est donc également utile.
L'une des utilisations du constructeur private
est de servir des classes singleton. Une classe singleton est une classe qui limite le nombre de création d'objets à un. En utilisant le constructeur private
, nous pouvons nous assurer qu’aucun objet ne peut être créé à la fois.
Exemple -
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;
}
}
Plus d'informations sur modificateurs d'accès.
Oui, les constructeurs peuvent avoir n'importe quel spécificateur d'accès/modificateur d'accès.
Les constructeurs privés sont utiles pour créer des classes singleton
.
Singleton - Une classe singleton est une classe où un seul objet peut être créé au moment de l'exécution (par JVM).
Un exemple simple d'une classe singleton est -
class Ex {
private static Ex instance;
int a;
private Ex() {
a = 10;
}
public static Ex getInstance() {
if(instance == null) {
instance = new Ex();
}
return instance;
}
}
Notez que pour la classe ci-dessus, la seule façon d'obtenir un objet (en dehors de cette classe) est d'appeler la fonction getInstance (), qui ne créerait qu'une seule instance et continuerait de la renvoyer.
Notez également que ce n'est pas thread-safe.
Les constructeurs peuvent être publics, par défaut ou privés et tout dépend de ce que vous voulez en faire.
Par exemple, si vous définissez une classe Singleton, vous feriez mieux de cacher (ce qui signifie la rendre privée afin qu'elle ne soit disponible que pour la classe où elle appartient) le constructeur pour empêcher les autres classes d'instancier votre classe à leur guise.
Vous pouvez vouloir le déclarer par défaut, disons, à des fins de test afin que les cas de test dans le même package puissent y accéder.
Des informations plus détaillées peuvent être trouvées ici
Il n'y a pas de règle pour que le constructeur soit public. Généralement, nous le définissons public simplement parce que nous aimerions l'instancier également à partir d'autres classes.
Un constructeur privé signifie: "Je ne laisse personne créer mon instance sauf moi". Donc, normalement, vous feriez cela lorsque vous aimez avoir un motif singleton.
Voici la classe dans JDK qui utilise un constructeur privé.
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() {
}
}
Non, les constructeurs peuvent utiliser n'importe quel modificateur d'accès, y compris privé. (Un constructeur privé signifie que seul le code dans la classe elle-même peut instancier un objet de ce type, donc si la classe constructeur privée veut autoriser l'utilisation d'une instance de la classe, la classe doit fournir une méthode statique ou une variable qui permet d'accéder à une instance créée à partir de la classe.)
Exemple
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);
}
}
Les résultats du programme ci-dessus seront
sous-sous-groupe alpha
Les constructeurs peuvent avoir toutes sortes de modificateurs d'accès. L'utilisation de différents modificateurs d'accès sur les constructeurs est différente.
Vous créez un constructeur public
si vous voulez que la classe soit instanciée de n'importe où.
Vous créez un constructeur protected
si vous voulez que la classe soit héritée et ses classes héritées instanciées.
Vous créez un constructeur private
si vous voulez que la classe soit instanciée uniquement à partir de ses propres membres, généralement un bloc statique ou une méthode statique. Cela signifie que vous prenez le contrôle de l'instanciation de la classe et appliquez une règle d'instanciation. Un exemple d'utilisation du constructeur privé est le modèle de conception singleton.
Je suis d'accord avec les réponses précédentes qu'un Singleton est un bon exemple d'une classe ayant un constructeur privé. Je recommanderais cependant une implémentation différente: un Singleton sûr pour les threads:
/**
* 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;
}
}
L'utilisation d'un singleton de manière sécurisée pour les threads vous évitera beaucoup de problèmes avec le code parallèle.
Un constructeur a pour être au moins protégé ou même privé lors de la création, par exemple, de classes d'usine personnalisées, comme:
public final class MyFactory {
private MyFactory(){} // this one prevents instances of your factory
}
public static void doSomething(){} // access that with MyFactory.doSomething
Notez que ce n'est qu'un exemple montrant quand un constructeur ne doit pas être public.
D'autres ont noté que les constructeurs peuvent avoir des modificateurs d'accès; un aspect non encore mentionné est que les modificateurs d'aspect d'un constructeur contrôlent deux aspects très différents de la construction, mais ne permettent pas de les contrôler séparément:
ClassName
et quels constructeurs sont autorisés à utiliser.ClassName
et quels constructeurs sont autorisés à utiliser.Les deux Java et .NET nécessitent que les réponses à ces deux questions vont ensemble; si une classe n'est pas final
(ou sealed
) et autorise un constructeur à utiliser par du code extérieur pour créer de nouvelles instances, le code extérieur aura également la liberté totale d'utiliser ce même constructeur pour créer des types dérivés.
Dans de nombreux cas, il peut être approprié pour une classe de n'avoir que des constructeurs package-private (internal
), mais d'exposer des méthodes publiques qui renvoient de nouvelles instances. Une telle approche pourrait être utilisée si l'on concevait un type comme String
à partir de zéro; un paquet comprenant String
pourrait le définir comme un type abstrait mais inclure des types concrets dérivés comme AsciiString
et UCS16String
qui stockent leur contenu sous la forme byte[]
et Char[]
, Respectivement; les méthodes qui renvoient String
pourraient alors renvoyer l'une des dérivées selon que la chaîne contenait des caractères en dehors de la plage ASCII. Si ni String
ni aucun type dérivé n'expose tous les constructeurs en dehors de son package, et tous les types dérivés dans le package se comporteraient comme une chaîne devraient se comporter, alors le code qui reçoit une référence de type String
pourrait s'attendre à ce qu'il se comporte sainement comme une chaîne (par exemple, garantissant que toute observation sur sa valeur restera à jamais vraie.) L'exposition de constructeurs en dehors du package, cependant, permettrait aux types dérivés de se comporter de manière étrange et bizarre (par exemple en changeant leur contenu après avoir été examiné et validé).
D'un point de vue syntaxique, être capable de dire Fnord foo = new Fnord(123);
est un peu plus agréable que d'avoir à dire Fnord foo = Fnord.Create(123);
, mais une classe Fnord
qui requiert cette dernière syntaxe peut mieux se maintenir contrôle du processus de création d'objet.
La plupart de ces réponses se réfèrent à une classe singleton ou usine. Une autre fois qu'un constructeur privé apparaît est (par exemple) dans la classe Java.lang.Math , où tout est statique et personne ne devrait jamais appeler le constructeur (y compris la classe elle-même). En ayant le constructeur privé, vous empêchez quiconque en dehors de la classe d'appeler le constructeur. (Cela n'empêche pas quelqu'un de la classe d'appeler le constructeur, mais il enfreint sa propre règle.)
L'explication simple est que s'il n'y a pas de constructeur dans une classe, le compilateur crée automatiquement un constructeur par défaut.
Le constructeur n'est pas toujours déclaré public, il peut également être privé, protégé ou par défaut.
Les constructeurs privés empêchent une classe d'être pleinement et clairement exprimée/représentée par ses appelants. Dans ce cas, les constructeurs privés sont utiles. Et si nous n'avons pas besoin que notre classe soit sous-classée, nous pouvons utiliser des constructeurs privés.