studio - set border java
¿Los constructores siempre tienen que ser públicos? (11)
Esta pregunta ya tiene una respuesta aquí:
- ¿Cuál es el uso de constructor privado en java [cerrado] 10 respuestas
Mi primera pregunta es -
class Explain() {
public Explain() {
}
}
¿Debería Constructor siempre declarado como público?
¿Qué sucede si creo un constructor private
?
Siempre he visto que los constructores son implícitamente public
. Entonces, ¿por qué private
constructor private
es útil? O no es útil en absoluto. ¡Porque nadie podría llamarlo nunca, o nunca hacer un objeto (debido al constructor private
)! Y esa es mi segunda pregunta.
Estoy de acuerdo con las respuestas anteriores de que un Singleton es un buen ejemplo de una clase que tiene un constructor privado. Sin embargo, recomendaría una implementación diferente: un Singleton seguro para subprocesos:
/**
* 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;
}
}
Usar un singleton en una forma segura de hilo te salvará mucho dolor en código paralelo.
La explicación simple es si no hay un constructor en una clase, el compilador crea automáticamente un constructor predeterminado.
El constructor no siempre se declara como público, también puede ser privado, protegido o predeterminado.
Los constructores privados evitan que una clase sea expresada / representada por sus interlocutores. En ese caso, los constructores privados son útiles. Y si no necesitamos que nuestra clase sea subclasificada, podemos usar constructores privados.
La mayoría de estas respuestas se refieren a una clase singleton o factory. En otro momento aparece un constructor privado (por ejemplo) en la clase java.lang.Math , donde todo es estático y nadie debe llamar al constructor (incluida la clase). Al tener el constructor privado, evitas que nadie fuera de la clase llame al constructor. (Esto no impide que alguien dentro de la clase llame al constructor, pero luego están rompiendo su propia regla).
Los constructores pueden ser públicos, predeterminados o privados y todo depende de lo que quieras hacer con él.
Por ejemplo, si está definiendo una clase Singleton, será mejor que oculte (es decir, que sea privado para que esté disponible solo para la clase donde pertenece) el constructor para evitar que otras clases creen su clase a su voluntad.
Es posible que desee declararlo predeterminado, digamos, para fines de prueba, de modo que los casos de prueba dentro del mismo paquete puedan acceder a él.
Información más detallada se puede encontrar here
Los constructores pueden tener todo tipo de modificadores de acceso. El uso de diferentes modificadores de acceso en los constructores es diferente.
Haces public
un constructor si quieres que la clase sea instanciada desde cualquier lugar.
Haces que un constructor esté protected
si quieres heredar la clase y crear instancias de sus clases heredadas.
Usted hace que un constructor sea private
si desea que la clase sea instanciada solo por sus propios miembros, generalmente un bloque estático o método estático. Significa que tomas el control de crear instancias de la clase y aplicar alguna regla sobre creación de instancias. El ejemplo de uso del constructor privado es el patrón de diseño singleton.
No existe una regla para que el constructor sea público. Generalmente la definimos pública simplemente porque también nos gustaría instanciarla de otras clases.
Constructor privado significa, "no dejo que nadie cree mi instancia excepto yo". Entonces normalmente harías esto cuando quisieras tener un patrón singleton.
La siguiente es la clase en JDK que usa un constructor privado.
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() {
}
}
No, los constructores pueden ser public
, private
, protected
o default
(no tienen ningún modificador de acceso).
Hacer algo private
no significa que nadie pueda acceder a él. Simplemente significa que nadie fuera de la clase puede acceder a él. Así que private
constructor private
es útil.
Uno de los usos del constructor private
es servir clases singleton. Una clase singleton es aquella que limita el número de creación de objetos a uno. Usando constructor private
podemos asegurarnos de que no se puede crear más de un objeto a la vez.
Ejemplo -
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 .");
}
public String getName() {
return name;
}
}
Más información sobre modificadores de acceso.
No, los constructores pueden usar cualquier modificador de acceso, incluido el privado. (Un constructor privado significa que solo el código dentro de la clase puede instanciar un objeto de ese tipo, por lo que si la clase privada del constructor desea permitir el uso de una instancia de la clase, la clase debe proporcionar un método o variable estática que permita el acceso a una instancia creada desde dentro de la clase).
Ejemplo
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);
}
}
La salida del programa anterior será
alpha subsub
Otros han notado que los constructores pueden tener modificadores de acceso; un aspecto aún no mencionado es que los modificadores de aspecto en un constructor controlan dos aspectos muy diferentes de la construcción, pero no permiten que se controlen por separado:
- Quién puede crear instancias de
ClassName
y qué constructores pueden usar. - Quién puede crear extensiones de
ClassName
y qué constructores pueden usar.
Tanto Java como .NET requieren que las respuestas a esas dos preguntas vayan juntas; si una clase no es final
(o sealed
) y permite que un constructor sea utilizado por código externo para crear nuevas instancias, entonces el código externo también tendrá total libertad para usar ese mismo constructor para crear tipos derivados.
En muchos casos, puede ser apropiado para una clase tener solo constructores privados ( internal
) de paquetes, pero exponer los métodos públicos que devuelven instancias nuevas. Tal enfoque podría usarse si uno diseñara un tipo como String
desde cero; un paquete que incluye String
podría definirlo como un tipo abstracto pero incluir tipos derivados concretos como AsciiString
y UCS16String
que almacenan su contenido como un byte[]
y Char[]
, respectivamente; los métodos que devuelven String
podrían devolver una de las derivadas dependiendo de si la cadena contiene caracteres fuera del rango ASCII. Si ni String
ni ningún tipo derivado exponen constructores fuera de su paquete y se espera que todos los tipos derivados dentro del paquete se comporten como una cadena, entonces el código que recibe una referencia de tipo String
podría esperar que se comportara correctamente como una cadena ( por ejemplo, garantizando que cualquier observación sobre su valor se mantendrá para siempre). La exposición de constructores fuera del paquete, sin embargo, haría posible que los tipos derivados se comporten de una manera extraña y extraña (por ejemplo, cambiando sus contenidos después de que hayan sido examinados y validados).
Desde una perspectiva sintáctica, ser capaz de decir Fnord foo = new Fnord(123);
es un poco mejor que tener que decir Fnord foo = Fnord.Create(123);
, pero una clase Fnord
que requiere la última sintaxis puede mantener un mejor control sobre el proceso de creación de objetos.
Sí, los constructores pueden tener cualquier especificador de acceso / modificador de acceso.
Los constructores privados son útiles para crear clases singleton
.
Singleton : una clase singleton es una clase en la que solo se puede crear un único objeto en tiempo de ejecución (por JVM).
Un ejemplo simple de una clase Singleton es -
class Ex {
private static Ex instance;
int a;
private Ex() {
a = 10;
}
public static Ex getInstance() {
if(instance == null) {
instance = new Ex();
}
return instance;
}
}
Tenga en cuenta que, para la clase anterior, la única forma de obtener un objeto (fuera de esta clase) es llamar a la función getInstance (), que solo crearía una única instancia y continuaría devolviéndola.
Además, tenga en cuenta que esto no es seguro para subprocesos.
Un constructor debe estar al menos protegido o incluso privado al crear, por ejemplo, clases de fábrica personalizadas, como:
public final class MyFactory {
private MyFactory(){} // this one prevents instances of your factory
}
public static void doSomething(){} // access that with MyFactory.doSomething
Tenga en cuenta que este es solo un ejemplo que muestra cuando un constructor no debe ser público.