Paquete y permiso de acceso de Java Tutorial básico Parte 2
Objetivos de aprendizaje para esta sección
- Domina los 4 derechos de acceso en Java;
- Domine las convenciones de nomenclatura del lenguaje Java;
- Domine la estructura de definición del patrón de diseño singleton y el patrón de diseño de casos múltiples;
1️⃣ Permisos de control de acceso
Para la encapsulación, de hecho, solo lo expliqué en detalle antes private
, pero si desea explicar la encapsulación por completo, debe combinar los 4 tipos de derechos de acceso. Las definiciones de estos 4 tipos de derechos de acceso se muestran en la siguiente tabla.
alcance | privado | por defecto | protegido | público |
---|---|---|---|---|
en la misma categoría | √ | √ | √ | √ |
diferentes clases en el mismo paquete | √ | √ | ||
Subclases de diferentes paquetes. | √ | √ | ||
No subclases de paquetes diferentes | √ |
La tabla anterior se puede entender simplemente como: private
solo se puede acceder en esta clase; default
solo se puede acceder en el mismo paquete; protected
se puede acceder en subclases de diferentes paquetes; public
se puede acceder para todas las clases.
En el artículo anterior , ya hemos aprendido acerca de private
, y, por lo que esta sección default
explica principalmente .public
protected
// 范例 1: 定义 com.xiaoshan.demoa.A 类
package com.xiaoshan.demoa;
public class A{
protected String info="Hello";//使用 protected权限定义
}
// 范例 2: 定义 com.xiaoshan.demob.B 类,此类继承A 类
package com.xiaoshan.demob;
import com.xiaoshan.demoa.A;
public class B extends A{
// B是A 不同包的子类
public void print(){
//直接访问父类中的protected属性
System.out.println("A 类的 info = "+ super.info);
}
}
Dado que B
la clase es A
una subclase de , B
se puede acceder directamente protected
al atributo de permiso de la clase principal en la clase .
// 范例 3: 代码测试
package com.xiaoshan.test;
import com.xiaoshan.demob.B;
public class Test {
public static void main(String args[]){
new B().print();
}
}
Resultado de la ejecución del programa:
A 类的 info = Hello
Este programa importa directamente la clase B y luego crea una instancia del objeto para llamar print()
al método y print()
usa " super.info
" en el método para acceder directamente protected
al atributo de permiso en la clase principal.
Y si desea usar directamente la clase principal para acceder a los atributos en com.xiaoshan.test
el paquete , porque no están en el mismo paquete y no hay una relación de herencia, no serán accesibles.Test
A
// 范例 4: 错误的访问
package com.xiaoshan.test;
import com.xiaoshan.demoa.A;
public class Test {
public static void main(String args[]){
A a = new A();
System.out.println(a.info); //错误:无法访问
}
}
Este programa preguntará directamente al usuario al compilar, info
es protected
un permiso, por lo que no se puede acceder directamente.
De hecho, entre los 4 tipos de permisos otorgados, 3 tipos de permisos ( private
, default
, protected
) son todas descripciones de encapsulación, es decir, la encapsulación orientada a objetos ahora se explica completamente. En términos de desarrollo y uso reales, los permisos rara vez se usan , por lo que solo hay dos conceptos de permisos y encapsulación default
que se usan realmente private
.protected
Para los derechos de acceso, los principiantes deben comprender los siguientes dos principios básicos de uso.
- El atributo declara el permiso de uso principal
private
; - Las declaraciones de métodos utilizan principalmente
public
permisos.
2️⃣ Convención de nomenclatura
La característica principal de la convención de nomenclatura es garantizar que el nombre de la clase o el nombre del método en el programa esté claramente marcado, pero para Java, hay algunas convenciones de nomenclatura fijas que deben seguirse.
- Nombre de la clase: la primera letra de cada palabra se escribe en mayúscula, por ejemplo:
TestDemo
; - Nombre de la variable: la primera letra de la primera palabra está en minúscula y la primera letra de cada palabra posterior está en mayúscula, por ejemplo:
studentName
; - Nombre del método: la primera letra de la primera palabra está en minúsculas y la primera letra de cada palabra posterior está en mayúsculas, por ejemplo:
printInfo()
; - Nombres constantes: escriba en mayúscula cada letra, por ejemplo:
FLAG
; - Nombre del paquete: todas las letras en minúsculas, por ejemplo:
com.xiaoshanjava.util
.
Cabe señalar que todos los desarrolladores deben seguir las cinco convenciones de nomenclatura dadas anteriormente, y que los diferentes equipos de desarrollo también pueden tener sus propias convenciones de nomenclatura.Estas convenciones de nomenclatura deben seguirse cuidadosamente en el proceso de desarrollo de software en el futuro.
3️⃣ Patrón de diseño Singleton (Singleton)
La mayoría de las definiciones de atributos se utilizan para private
declarar, pero el constructor también se puede private
declarar, y el constructor en este momento está privatizado. ¿Y qué problemas surgirán después de la privatización del constructor, y qué efecto tendrá? Hagamos un análisis simple.
Primero, antes de explicar el funcionamiento del constructor privado, observemos el siguiente programa.
// 范例 5: 构造方法非私有化
class Singleton {
//定义一个类,此类默认提供无参构造方法
public void print(){
System.out.println("Hello World.");
}
}
public class TestDemo{
public static void main(String args[])(
Singleton inst = null; //声明对象
inst = new Singleton(; //实例化对象
inst.print(); //调用方法
}
}
Resultado de la ejecución del programa:
Hello World.
En este programa, Singleton
hay un método de construcción en la clase (porque si un método de construcción no está definido explícitamente en una clase, se generará automáticamente un método de construcción sin parámetros y sin hacer nada), por lo que primero puede instanciar directamente el objeto y luego llamar al método provisto en la clase print()
. Cambiemos el método de construcción, es decir, usemos private
encapsulación.
// 范例 5: 私有化构造方法
class Singleton{
//定义一个类
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
}
public class TestDemo {
public static void main(String args[]){
Singleton inst = null; //声明对象
inst = hew Singletono: //错误:The constructor Singleton() is not visible
inst.print(); //调用方法
}
}
Cuando este programa instancia el objeto de la clase, el programa tiene un error de compilación, porque el constructor está privatizado y no se puede llamar externamente, es decir, el objeto de la clase Singleton
no se puede instanciar externamente .Singleton
Ahora, en el caso de garantizar que Singleton
el método de construcción en la clase no se modifique ni se agregue, y que el método no se modifique, ¿cómo puede el exterior de la clase llamar al método instanciando el objeto?print()
print()
Pensamiento 1: private
Las operaciones definidas con permisos de acceso solo pueden ser accedidas por esta clase y no pueden ser llamadas externamente. Ahora que el método de construcción está privatizado, prueba que el método de construcción de esta clase solo puede ser llamado por esta clase, es decir, solo los objetos instanciados de esta clase pueden generarse en esta clase.
// 范例 6: 第一步思考
class Singleton {
//定义一个类
Singleton instance = new Singleton(); //在内部实例化本类对象
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
}
Pensamiento 2: Para los atributos ordinarios en una clase, por defecto, deben llamarse después de que haya objetos instanciados en esta clase, pero este programa no puede generar objetos instanciados fuera de la clase, por lo que debemos encontrar una manera de permitir que los atributos en la clase sean llamados cuando no hay un objeto instanciado Singleton
de Singleton
la clase instance
. Singleton
Por lo tanto, se puede hacer static
usando , static
los rasgos de propiedad definidos se llaman directamente por el nombre de la clase y se pueden llamar cuando no se instancia ningún objeto.
// 范例 7: 第二步思考
class Singleton {
//定义一个类
static Singleton instance = new Singleton(); //可以由类名称直接访问
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
}
public class TestDemo {
public static void main(String args[]){
Singleton inst = null; //声明对象
inst = Singleton.instance; //利用“类.static属性”方式取得实例化对象
inst.print(); //调用方法
}
}
Resultado de la ejecución del programa:
Hello World.
Pensamiento 3: todos los atributos de la clase deben encapsularse, por lo que instance
el atributo del ejemplo anterior también debe encapsularse, y para obtener el atributo después de la encapsulación, debe escribir getter
un método, pero en este momento getter
el método también debe ser llamado directamente por el nombre de la clase, definido como static
tipo.
// 范例 8: 第三步思考
class Singleton {
//定义一个类
private static Singleton instance = new Singleton();
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
public static Singleton getInstance(){
//取得本类对象
return instance;
}
}
public class TestDemo(
public static void main(String args[]){
Singleton inst = null; //声明对象
inst = Singleton.getInstance(); //利用“类.static方法()”取得实例化对象
inst.print(); //调用方法
}
}
Resultado de la ejecución del programa:
Hello World.
Pensamiento 4: ¿Cuál es el propósito de hacer esto? instance
El atributo en el programa pertenece a static
la definición, lo que significa que Singleton
no importa cuántas declaraciones de objetos haya, todos los objetos de la clase compartirán la misma instance
referencia de atributo, así que dado que son iguales, ¿cuál es el punto?
Si desea controlar la cantidad de objetos instanciados en una clase, lo primero que debe bloquear es el constructor en la clase (utilícelo para private
definir el constructor), porque el constructor debe usarse al instanciar cualquier objeto nuevo. Si el constructor está bloqueado, naturalmente será imposible generar nuevos objetos instanciados.
Si desea llamar a las operaciones definidas en la clase, obviamente necesita un objeto instanciado. En este momento, puede usar el método dentro de la clase static
para definir un objeto público y static
devolver un objeto único cada vez que pasa por el método, de modo que no importa cuántas veces haya llamadas externas, una clase solo puede generar un objeto único al final. Este diseño pertenece al patrón de diseño singleton ( ) Singleton
.
Sin embargo, todavía hay un problema con este programa, es decir, también se puede usar el siguiente código.
// 范例 9: 程序出现的问题
class Singleton {
//定义一个类
private static Singleton instance = new Singleton();
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
public static Singleton getInstance(){
// 取得本类对象
instance = new Singleton(); //重新实例化对象
return instance;
}
}
No hay nada malo con la sintaxis de la operación en este programa, y no hay necesidad de considerar si tiene sentido, y el código actual lo permite, y al hacerlo descubrirá que todos los esfuerzos anteriores para representar el único objeto instanciado se han desperdiciado. Por lo tanto, debemos encontrar una manera de abolir esta práctica, por lo que debemos instance
agregar una final
palabra clave al definir .
// 范例 10: 一个完整的单例模式的程序
class Singleton {
//定义一个类
private final static Singleton instance = new Singleton();
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
public static Singleton getInstance(){
//取得本类对象
return instance;
}
}
public class TestDemo{
public static void main(String args[]){
Singleton inst = null; //声明对象
inst = Singleton.getInstance(); //利用“类.static方法()”取得实例化对象
inst.print(); //调用方法
}
}
Resultado de la ejecución del programa:
Hello World.
Al usar Singleton
la clase, sin importar cómo opere el código, siempre habrá un solo Singleton
objeto instanciado de la clase, y dicho código se denomina patrón de diseño singleton ( Singleton
) en el patrón de diseño.
4️⃣ Patrón de diseño de múltiples instancias
El patrón de diseño singleton deja solo un objeto instanciado de una clase, mientras que el patrón de diseño de instancias múltiples define varios objetos.
Por ejemplo: defina una clase de operación que represente el día de la semana, y los objetos de esta clase solo pueden tener 7 objetos instanciados ( ) 星期一 ~星期日
; defina una clase que represente género, y solo tenga 2 objetos instanciados ( 男、女
); defina una clase de operación que represente el color base, y solo tenga 3 objetos instanciados ( 红、绿、蓝
).
En estos casos, dicha clase no debería permitir a los usuarios crear objetos instanciados sin restricciones, y solo debería usarse un número limitado, que pertenece al diseño de múltiples instancias. Ya sea un diseño de instancia única o un diseño de múltiples instancias, existe un núcleo inquebrantable, es decir, la privatización del método de construcción.
// 范例 11: 定义一个表示性别的类
package com.xiaoshan.demo;
class Sex{
private String title;
private static final Sex MALE = new Sex("男");
private static final Sex FEMALE = new Sex("女");
private Sex(String title){
//构造私有化
this.title = title;
}
public String toString(){
return this.title;
}
public static Sex getInstance(int ch){
//返回实例化对象
switch (ch){
case 1:
return MALE;
case 2:
return FEMALE;
default:
return;
}
}
}
public class TestDemo {
public static void main(String args[]){
Sex sex = Sex.getInstance(2);
System.out.println(sex);
}
}
Resultado de la ejecución del programa:
女
Este programa primero define una clase de programa de múltiples instancias que describe el género y encapsula su método de construcción, y luego usa el getInstance()
método para devolver un Sex
objeto de clase instanciado después de recibir el número especificado.
El código del Ejemplo 11 obtiene un Sex
objeto de una clase usando números. Algunos amigos pueden sentir que el concepto expresado por este método no es claro. Para obtener el tipo de objeto más claramente, se puede introducir una interfaz para explicarlo.
// 范例 12: 利用接口标记对象内容
interface Choose {
public int MAN = 1; //描述数字
public int WOMAN = 2; //描述数字
}
public class TestDemo {
public static void main(String args[]){
//利用接口标记内容取得对象
Sex sex = Sex.getInstance(Choose.MAM);
System.out.println(sex);
}
}
Si este programa quiere obtener el Sex
objeto de clase especificado, puede usar las constantes globales definidas en la interfaz (de hecho, Sex
algunas constantes globales también se pueden definir en la clase) para juzgar. Este enfoque es una práctica estándar, pero es un poco complicado, por lo que será más fácil usar cadenas para juzgar directamente.
Antes de JDK 1.7, switch
solo puede admitir el juicio de int
o tipo, solo porque si se trata de números o caracteres puramente, el significado no está claro, por lo que se agrega el soporte de.char
String
// 范例 13: 对取得Sex 类对象进行修改
package com.xiaoshan.demo;
class Sex{
private String title;
private static final Sex MALE = new Sex("男");
private static final Sex FEMALE = new Sex("女");
private Sex(String title){
//构造私有化
this.title = title;
}
public String toString(){
return this.title;
}
public static Sex getInstance(String ch){
switch (ch){
//利用字符串判断
case "man":
return MALE;
case "woman":
return FEMALE;
default:
return null;
}
}
}
public class TestDemo {
public static void main(String args[]){
Sex sex = Sex.getInstance("man");
System.out.println(sex);
}
}
Resultado de la ejecución del programa:
男
Este programa usa directamente String
como switch
condición de juicio, de modo que al obtener el objeto instanciado, la cadena de caracteres se puede usar para describir el nombre del objeto, lo cual es más conveniente que usar números directamente.