JavaRush /Blog Java /Random-ES /Pausa para el café #165. Paquetes en Java. Métodos seguro...

Pausa para el café #165. Paquetes en Java. Métodos seguros para subprocesos para principiantes

Publicado en el grupo Random-ES

paquetes java

Fuente: Usemynotes Esta publicación lo ayudará a comprender mejor los paquetes en Java, comprender su propósito y cómo implementarlos. Pausa para el café #165.  Paquetes en Java.  Métodos seguros para subprocesos para principiantes - 1

¿Qué son los paquetes en Java?

Un paquete en Java es una forma de agrupar un grupo de clases, interfaces y subpaquetes. Los paquetes se utilizan para crear grupos de clases, interfaces, enumeraciones, etc. relacionadas. Los subpaquetes son paquetes que están dentro de otro paquete. No se importan de forma predeterminada, pero puedes importarlos manualmente si es necesario. La especificación de acceso no se proporciona a los miembros individuales de un subpaquete; se tratan como paquetes separados.

Algunos tipos de paquetes en Java:

  • java.lang : viene incluido con Java de forma predeterminada.
  • java.io : contiene clases, métodos y otros elementos relacionados con la entrada/salida.

¿Por qué se necesitan paquetes?

  • Para evitar conflictos de nombres.
  • Proporcionar acceso controlado.
  • Para lograr la encapsulación de datos.

¿Cómo crear un paquete en Java?

Creemos un paquete llamado computadora . Normalmente el nombre del paquete se escribe en letras minúsculas. Esto se hace sólo para evitar conflictos de nombres con nombres de clases. También crearemos una interfaz llamada Pluggable , que estará ubicada en el paquete del ordenador .
package computer;

interface Pluggable {
   public void pluggedIn();
   public void pluggedOut();
}
Ahora crearemos una clase llamada PenDrive que implementará la interfaz anterior.
package computer;

public class PenDrive implements Pluggable {

   int storage = 64;

   public void pluggedIn () {
     System.out.println("Pen Drive is connected");
   }

   public void pluggedOut () {
     System.out.println("Pen Drive is removed");
   }

   public int storage() {
     return storage;
   }

   public static void main(String args[]) {
     PenDrive p = new PenDrive ();
     p.pluggedIn();
     System.out.println("Pen Drive Storage: " + p.storage());
     p.pluggedOut();
   }
}

¿Cómo crear una jerarquía de paquetes en Java?

Al formar una jerarquía, los paquetes en Java se nombran en orden inverso. Esto los hace muy similares a directorios o carpetas. Al igual que en una computadora personal, donde una carpeta puede contener una o más subcarpetas, lo mismo se aplica a los paquetes en Java. Veamos un paquete llamado Asia.India.Kolkata . Todas estas son carpetas existentes, pero si consideramos la geografía, está claro que Calcuta está en la India y la India está en Asia. El objetivo principal de una jerarquía es hacer que las clases sean más fáciles de encontrar.

Tipos de paquetes en Java

Paquetes incorporados

Los paquetes integrados son paquetes que constan de una gran cantidad de clases integradas que forman parte de la API de Java. Estos paquetes incluyen:
  • java.util : este paquete contiene un número finito de clases de utilidad que se utilizan para implementar estructuras de datos como listas vinculadas, conjuntos, etc. También admite operaciones de fecha y hora y mucho más.
  • java.net : contiene clases utilizadas para operaciones de red.

Paquetes definidos por el usuario

Los paquetes definidos por el usuario se denominan paquetes de usuario. El usuario puede crear manualmente un paquete y tener tantas clases como desee.

¿Cómo acceder a un paquete desde otro paquete?

Puede acceder a un paquete desde otro paquete de tres formas sencillas:
  • Usar un asterisco en una declaración de importación
El carácter asterisco ( * ) se utiliza para representar "todas las cosas" en Java. Usándolo podemos importar todo lo que hay dentro de un subpaquete de un paquete. Ejemplo: considere un paquete llamado herramientas . Si queremos importar todo lo que hay dentro de este paquete, entonces necesitamos usar la declaración de importación como:
import tools.*;
  • Usando el paquete de importación.ClassName ;
Mencionar el nombre de la clase en un paquete es una forma eficaz de importar sólo las clases que necesita en su programa, evitando así importar clases innecesarias. Ejemplo: considere un paquete llamado libros . Si solo queremos importar una clase o interfaz específica (veremos la clase Pages ), entonces podemos importar solo eso usando:
import book.Pages;
  • Usando tu nombre completo
Hay una manera de utilizar directamente un paquete Java o sus clases utilizando su nombre completo. De esta manera no tendrá que importar el paquete y podrá usarlo directamente en el programa. Ejemplo:
java.awt.List aSimpleList = new java.awt.List();

Tamaño de lote predeterminado en Java

De forma predeterminada, Java importa el paquete java.lang . Tiene muchas clases que se usan comúnmente en programas Java simples como String , Integer y otros. Una de las clases más importantes es la clase Object , que a su vez también se encuentra en el paquete java.lang . El tamaño de este paquete se basa en sus componentes: 8 interfaces, 37 clases, 3 enumeraciones, 27 excepciones, 23 tipos de errores y 5 tipos de anotaciones.

Métodos Java seguros para subprocesos para principiantes

Fuente: Medio Con este artículo, puede obtener información sobre el funcionamiento de los métodos seguros para subprocesos en Java. Pausa para el café #165.  Paquetes en Java.  Métodos seguros para subprocesos para principiantes - 2Descubrí que muchos desarrolladores Java junior/intermedios no entienden cómo deberían funcionar los métodos seguros para subprocesos en proyectos reales. Y como solemos trabajar en un entorno multiproceso, su correcto uso es muy importante. Un método seguro para subprocesos es un método que se puede llamar desde varios subprocesos simultáneamente sin afectar el estado de los datos de cada uno. Una comprensión insuficiente de este concepto genera errores que son difíciles de encontrar y corregir. Para evitar este tipo de errores, veamos ejemplos.

Ejemplo 1:

public static int countLetters(String input) {
    int counter = 0;

    for (Character c : input.toCharArray()) {
        if (Character.isAlphabetic(c)) {
            counter++;
        }
    }

    return counter;
}
  • El método countLetters es estático, devuelve un valor int y acepta un parámetro de cadena como entrada.
  • Se crea un contador de variables primitivo dentro del método, luego el bucle recorre los caracteres de la cadena de entrada e incrementa el contador de variables cada vez que se encuentra un carácter de letra.
¿Es seguro este método para subprocesos? Muchos desarrolladores dicen que no, porque en este caso tenemos una operación de incremento que no es segura para subprocesos. Vamos a resolverlo. En el modelo de memoria Java tenemos pila y montón. Cada hilo tiene su propia pila y todos los hilos comparten el mismo montón. En este sentido, los datos de la pila siempre son seguros para subprocesos, pero los datos del montón no. La pila almacena primitivas y referencias a objetos. El montón contiene los propios objetos. Esto significa que en este ejemplo de código, cada subproceso almacena su propio contador de variables en la pila y no tiene ningún efecto sobre los datos de otros subprocesos, por lo que el método es seguro para subprocesos . Tenga en cuenta que el valor String de entrada también es un objeto, pero String y los envoltorios primitivos ( Integer , Long , Double , Boolean , etc.) son seguros para subprocesos porque son inmutables.

Ejemplo #2:

public static int countLetters2(String input) {
    List<Character> listCounter = new ArrayList<>();

    for (Character c : input.toCharArray()) {
        if (Character.isAlphabetic(c)) {
            listCounter.add(c);
        }
    }

    return listCounter.size();
}
Este código usó la misma lógica que el primer ejemplo, pero usó un objeto List en lugar de una variable int primitiva . De la parte anterior sabemos que los objetos en Java se almacenan en el montón y List es un objeto. También sabemos que la pila almacena referencias a objetos en el montón. En el ejemplo n.° 2, cada subproceso crea un nuevo objeto ArrayList : y la variable listCounter almacena una referencia a su objeto en el montón, por lo que ningún otro subproceso puede cambiar ese objeto.
List<Character> listCounter = new ArrayList<>();
Esto significa que este método es seguro para subprocesos.

Ejemplo #3:

public class CounterUtil { // singleton

    List<Character> listCounter = new ArrayList<>();

    public int countLetters3(String input) {
        for (Character c : input.toCharArray()) {
            if (Character.isAlphabetic(c)) {
                listCounter.add(c);
            }
        }

        return listCounter.size();
    }
}
En este ejemplo, tenemos una clase Singleton (esto es importante) CounterUtil con una variable global listCounter . Esta variable se crea al mismo tiempo que la instancia singleton. Cuando varios subprocesos llaman al método countChars3 , todos usan la misma variable global listCounter , que almacena una referencia al mismo objeto en el montón, y los subprocesos allí se influirán entre sí. Por lo tanto podemos concluir que este método no es seguro para subprocesos. E incluso si cambiamos List<Character> listCounter a una variable primitiva int contador , tampoco será seguro para subprocesos porque todos los subprocesos usarán la misma variable primitiva.

Último ejemplo:

public static int countLetters4(List<Character> inputList) {
    List<Character> listCounter = new ArrayList<>();

    for (Character c : inputList) {
        if (Character.isAlphabetic(c)) {
            listCounter.add(c);
        }
    }

    return listCounter.size();
}
El método countLetters4 acepta una lista de caracteres en lugar de un parámetro String . Aquí no podemos garantizar que este método sea seguro para subprocesos. ¿Por qué? Porque no podemos estar seguros de cómo los desarrolladores utilizarán este método. Si otro hilo externo cambia los datos en inputList al mismo tiempo que nuestro método counterLetters4 , podría afectar el resultado final.

Conclusión

Solo hemos visto cuatro ejemplos y no cubren todos los aspectos de la seguridad de subprocesos en proyectos Java, pero son un buen punto de partida. La próxima vez que vea un método en su código, pregúntese: "¿Es este método seguro para subprocesos?" Y muy pronto entenderás claramente la respuesta.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION