Haz clic si te gusta el proyecto. Sus contribuciones son bienvenidas de todo corazón.
subprocesos múltiples
Colecciones
Conectividad de base de datos Java (JDBC)
Programas Java
Métodos de cadena de Java
Páginas del servidor de Yakarta (JSP)
servlets
Preguntas de opción múltiple de Java
Patrón de diseño de Java
Hibernar
Conceptos básicos del marco de primavera
Introducción
Arquitectura Java
Tipos de datos Java
Métodos Java
Programación funcional Java
Expresiones Java Lambda
clases de java
Constructores de Java
Matriz Java
Cadenas de Java
Reflexión de Java
Secuencias de Java
Expresiones regulares de Java
Manejo de archivos Java
Excepciones de Java
Herencia de Java
Anulación del método Java
Polimorfismo de Java
Abstracción de Java
Interfaces Java
Encapsulación de Java
Genéricos de Java
Misceláneas
Métodos de interfaz por defecto;
expresiones lambda;
Interfaces funcionales;
Referencias a métodos y constructores;
Anotaciones repetibles
Anotaciones sobre tipos de datos;
Reflexión para los parámetros del método;
Stream API para trabajar con colecciones;
Clasificación paralela de matrices;
Nueva API para trabajar con fechas y horas;
Nuevo motor JavaScript Nashorn;
Se agregaron varias clases nuevas para operación segura para subprocesos;
Se agregó una nueva API para Calendar
y Locale
;
Se agregó soporte para Unicode 6.2.0;
Se agregó una clase estándar para trabajar con Base64;
Se agregó soporte para aritmética sin signo;
Constructor mejorado java.lang.String(byte[], *)
y rendimiento del método java.lang.String.getBytes()
;
Una nueva implementación AccessController.doPrivileged
que le permite establecer un subconjunto de privilegios sin tener que verificar todos los * demás niveles de acceso;
Los algoritmos basados en contraseñas se han vuelto más sólidos;
Se agregó soporte para la indicación de nombre de servidor (NSI) SSL/TLS en el servidor JSSE;
Almacén de claves mejorado (KeyStore);
Se agregó el algoritmo SHA-224;
Puente JDBC eliminado - ODBC;
Se elimina PermGen, se cambia el método para almacenar metadatos de clases;
Capacidad para crear perfiles para la plataforma Java SE, que incluyen no toda la plataforma, sino una parte de ella;
Herramientas
Se agregó la utilidad jjs
para usar JavaScript Nashorn;
El comando java
puede ejecutar aplicaciones JavaFX;
Se agregó la utilidad jdeps
para analizar archivos .class.
↥ volver arriba
Nashorn es un motor JavaScript desarrollado en Java por Oracle. Diseñado para brindar la capacidad de incrustar código JavaScript en aplicaciones Java. En comparación con Rhino, que cuenta con el respaldo de la Fundación Mozilla, Nashorn proporciona un rendimiento de 2 a 10 veces mejor, ya que compila código y transfiere código de bytes a la máquina virtual Java directamente en la memoria. Nashorn puede compilar código JavaScript y generar clases Java que se cargan con un cargador especial. También es posible llamar al código Java directamente desde JavaScript.
↥ volver arriba
jjs
: esta es una utilidad de línea de comandos que le permite ejecutar programas JavaScript directamente en la consola.
↥ volver arriba
En Java, hay tres formas diferentes de leer la entrada del usuario en el entorno de línea de comandos (consola).
1. Uso de la clase de lector almacenado en búfer:
Este método se utiliza envolviendo System.in (flujo de entrada estándar) en un InputStreamReader que está envuelto en un BufferedReader, podemos leer la entrada del usuario en la línea de comando.
/** * Clase de lector almacenado en búfer */import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Test { public static void main(String[] args) throws IOException { // Enter datos usando BufferReader Lector BufferedReader = nuevo BufferedReader (nuevo InputStreamReader (System.in)); // Leer datos usando readLine String name = lector.readLine(); // Imprimiendo la línea de lectura System.out.println(name); } }
2. Usando la clase de escáner:
El objetivo principal de la clase Scanner es analizar cadenas y tipos primitivos usando expresiones regulares; sin embargo, también se puede usar para leer la entrada del usuario en la línea de comando.
/** * Clase de escáner */import java.util.Scanner;class GetInputFromUser { public static void main(String args[]) { // Uso del escáner para obtener información del escáner del usuario in = new Scanner(System.in); Cadena s = in.nextLine(); System.out.println("Ingresaste la cadena " + s); int a = in.siguienteInt(); System.out.println("Ingresaste un número entero " + a); flotador b = in.nextFloat(); System.out.println("Ingresaste float " + b); } }
3. Usando la clase de consola:
Se ha convertido en una forma preferida de leer las entradas del usuario desde la línea de comandos. Además, se puede utilizar para leer entradas similares a contraseñas sin repetir los caracteres ingresados por el usuario; También se puede utilizar la sintaxis de cadena de formato (como System.out.printf()).
/** * Clase de consola */public class Sample { public static void main(String[] args) { // Uso de la consola para ingresar datos del usuario String name = System.console().readLine(); System.out.println(nombre); } }
↥ volver arriba
El comando javap muestra información sobre los campos, constructores y métodos presentes en un archivo de clase. El comando javap (también conocido como Java Disassembler) desensambla uno o más archivos de clase.
/** * Desensamblador de Java */class Simple { public static void main(String args[]) { System.out.println("Hola mundo"); } }
cmd> javap Clase simple
Producción
Compilado de la clase ".java" Simple { Simple(); principal vacío estático público (java.lang.String []); }
↥ volver arriba
System.out::println
? La expresión especificada ilustra cómo pasar una referencia a un método estático de una clase println()
System.out
.
↥ volver arriba
Las transmisiones pueden ser secuenciales y paralelas. Las operaciones en flujos secuenciales se realizan en un subproceso del procesador, en flujos paralelos, utilizando varios subprocesos del procesador. Las transmisiones paralelas utilizan la transmisión compartida ForkJoinPool
a través del método estático ForkJoinPool.commonPool()
. En este caso, si el entorno no es multinúcleo, la transmisión se ejecutará de forma secuencial. De hecho, el uso de flujos paralelos se reduce al hecho de que los datos en los flujos se dividirán en partes, cada parte se procesa en un núcleo de procesador separado y, al final, estas partes se conectan y las operaciones finales se realizan en a ellos.
También puede utilizar el método de interfaz parallelStream()
para crear una secuencia paralela a partir de la colección Collection
.
Para hacer que una secuencia secuencial regular sea paralela, debe llamar al método Stream
en el objeto parallel()
. El método isParallel()
le permite saber si la transmisión es paralela.
Utilizando los métodos parallel()
y sequential()
es posible determinar qué operaciones pueden ser paralelas y cuáles sólo secuenciales. También puedes hacer un flujo paralelo a partir de cualquier flujo secuencial y viceversa:
recopilación .arroyo () .peek (...) // la operación es secuencial .paralelo () .map (...) // la operación se puede realizar en paralelo, .secuencial () .reduce (...) // la operación vuelve a ser secuencial
Como regla general, los elementos se transfieren a la secuencia en el mismo orden en que se definen en la fuente de datos. Cuando se trabaja con flujos paralelos, el sistema conserva la secuencia de elementos. Una excepción es un método forEach()
que puede generar elementos en orden aleatorio. Y para mantener el orden es necesario aplicar el método forEachOrdered()
.
Criterios que pueden afectar el rendimiento en flujos paralelos:
Tamaño de los datos: cuantos más datos, más difícil será separarlos primero y luego combinarlos.
El número de núcleos del procesador. En teoría, cuantos más núcleos tenga una computadora, más rápido funcionará el programa. Si la máquina tiene un núcleo, no tiene sentido utilizar hilos paralelos.
Cuanto más simple sea la estructura de datos con la que trabaja el flujo, más rápidas serán las operaciones. Por ejemplo, los datos de ArrayList
son fáciles de usar, ya que la estructura de esta colección asume una secuencia de datos no relacionados. Pero una colección de tipos LinkedList
no es la mejor opción, ya que en una lista secuencial todos los elementos están conectados con anterior/siguiente. Y esos datos son difíciles de paralelizar.
Las operaciones con tipos primitivos serán más rápidas que con objetos de clase.
Se recomienda encarecidamente que no utilice flujos paralelos para operaciones largas (por ejemplo, conexiones de red), ya que todos los flujos paralelos funcionan con un ForkJoinPool
, operaciones tan largas pueden detener todos los flujos paralelos en la JVM debido a la falta de subprocesos disponibles. en la piscina, etc. e. los flujos paralelos deben usarse sólo para operaciones cortas donde el conteo dura milisegundos, pero no para aquellas donde el conteo puede durar segundos y minutos;
Guardar el orden en flujos paralelos aumenta los costos de ejecución, y si el orden no es importante, es posible deshabilitar su almacenamiento y así aumentar la productividad usando una operación intermedia unordered()
:
colección.parallelStream () .ordenado () .desordenado () .collect (Coleccionistas. toList());
↥ volver arriba
Java Virtual Machine (JVM) es una especificación que proporciona un entorno de ejecución en el que se puede ejecutar el código de bytes de Java (archivos .class). La JVM es la plataforma. La JVM actúa como una máquina o procesador "virtual". La independencia de plataforma de Java consiste principalmente en su Máquina Virtual Java (JVM). JVM hace esto posible porque conoce la longitud específica de las instrucciones y otras particularidades de la plataforma (Sistema Operativo).
La JVM no es independiente de la plataforma. La máquina virtual Java (JVM) proporciona el entorno para ejecutar el archivo Java (archivo .Class). Entonces, al final, depende del kernel y el kernel difiere de un sistema operativo (sistema operativo) a otro. La JVM se utiliza para traducir el código de bytes al lenguaje de máquina para una computadora en particular y también para ejecutar las instrucciones correspondientes en lenguaje de máquina.
↥ volver arriba
El compilador Just-In-Time (JIT) es un componente del entorno de ejecución que mejora el rendimiento de las aplicaciones Java al compilar códigos de bytes en código de máquina nativo en tiempo de ejecución.
Los programas Java constan de clases que contienen códigos de bytes neutrales para la plataforma que pueden ser interpretados por una JVM en muchas arquitecturas informáticas diferentes. En tiempo de ejecución, la JVM carga los archivos de clase, determina la semántica de cada código de bytes individual y realiza el cálculo apropiado. El uso adicional de procesador y memoria durante la interpretación significa que una aplicación Java funciona más lentamente que una aplicación nativa. El compilador JIT ayuda a mejorar el rendimiento de los programas Java al compilar códigos de bytes en código de máquina nativo en tiempo de ejecución. El compilador JIT está habilitado de forma predeterminada. Cuando se ha compilado un método, la JVM llama directamente al código compilado de ese método en lugar de interpretarlo.
↥ volver arriba
Java ClassLoader es parte del Java Runtime Environment que carga dinámicamente clases Java en la máquina virtual Java. El compilador javac compila el código Java en un archivo de clase y la JVM ejecuta el programa Java ejecutando códigos de bytes escritos en el archivo de clase. ClassLoader es responsable de cargar archivos de clase desde el sistema de archivos, la red o cualquier otra fuente.
Tipos de cargador de clases:
1. Cargador de clases Bootstrap :
Carga archivos de clase JDK estándar desde rt.jar y otras clases principales. Carga archivos de clase desde jre/lib/rt.jar. Por ejemplo, clase de paquete java.lang.
2. Cargador de clases de extensiones :
Carga clases desde las extensiones JDK directamente, generalmente el directorio JAVA_HOME/lib/ext
o cualquier otro directorio como java.ext.dirs.
3. Cargador de clases del sistema :
Carga clases específicas de la aplicación desde la variable de entorno CLASSPATH. Se puede configurar al invocar el programa usando las opciones de línea de comando -cp o classpath.
↥ volver arriba
1. JDK :
Java Development Kit es el componente central del entorno Java y proporciona todas las herramientas, ejecutables y binarios necesarios para compilar, depurar y ejecutar un programa Java.
2. JVM :
JVM es responsable de convertir el código de bytes al código específico de la máquina. JVM también depende de la plataforma y proporciona funciones básicas de Java como administración de memoria, recolección de basura, seguridad, etc. JVM es personalizable y podemos usar opciones de Java para personalizarla, por ejemplo, asignando memoria mínima y máxima a JVM. JVM se llama virtual porque proporciona una interfaz que no depende del sistema operativo subyacente ni del hardware de la máquina.
2.JRE :
Java Runtime Environment proporciona una plataforma para ejecutar programas Java. JRE consta de binarios JVM y Java y otras clases para ejecutar cualquier programa con éxito.
↥ volver arriba
1. Espacio de almacenamiento dinámico de Java:
El tiempo de ejecución de Java utiliza el espacio de almacenamiento dinámico de Java para asignar memoria a objetos y clases JRE . Siempre que creamos un objeto, siempre se crea en el espacio del montón.
La recolección de basura se ejecuta en la memoria del montón para liberar la memoria utilizada por los objetos que no tienen ninguna referencia. Cualquier objeto creado en el espacio del montón tiene acceso global y se puede hacer referencia a él desde cualquier parte de la aplicación.
2. Memoria de pila de Java:
La pila en Java es una sección de memoria que contiene métodos , variables locales y variables de referencia . Las variables locales se crean en la pila.
Siempre se hace referencia a la memoria de pila en orden LIFO (Último en entrar, primero en salir). Cada vez que se invoca un método, se crea un nuevo bloque en la memoria de la pila para que el método contenga valores primitivos locales y referencias a otros objetos del método.
Tan pronto como finaliza el método, el bloque deja de usarse y queda disponible para el siguiente método. El tamaño de la memoria de pila es mucho menor en comparación con la memoria de montón.
Diferencia:
Parámetro | Memoria de pila | Espacio de montón |
---|---|---|
Solicitud | La pila se usa en partes, una a la vez durante la ejecución de un hilo. | Toda la aplicación utiliza espacio Heap durante el tiempo de ejecución. |
Tamaño | La pila tiene límites de tamaño según el sistema operativo y suele ser más pequeña que la pila | No hay límite de tamaño en el montón |
Almacenamiento | Almacena solo variables primitivas y referencias a objetos creados en Heap Space | Todos los objetos recién creados se almacenan aquí. |
Orden | Se accede mediante el sistema de asignación de memoria LIFO (Último en entrar, primero en salir). | Se accede a esta memoria a través de complejas técnicas de gestión de memoria que incluyen la generación joven, la generación antigua o permanente y la generación permanente. |
Vida | La memoria de pila solo existe mientras se ejecuta el método actual | El espacio del montón existe mientras se ejecuta la aplicación. |
Eficiencia | Comparativamente mucho más rápido de asignar en comparación con el montón | Más lento de asignar en comparación con la pila |
Asignación/Desasignación | Esta memoria se asigna y desasigna automáticamente cuando se llama y se devuelve un método, respectivamente. | El espacio de almacenamiento dinámico se asigna cuando Gargabe Collector crea y desasigna nuevos objetos cuando ya no se hace referencia a ellos. |
↥ volver arriba
JVM es un programa que toma el código de bytes de Java y lo convierte (línea por línea) en código comprensible para la máquina. JVM realiza algunos tipos particulares de operaciones:
Carga de codigo
Verificación de código
Ejecutando el código
Proporciona un entorno de tiempo de ejecución a los usuarios.
Tipos de áreas de memoria asignadas por la JVM:
1. Classloader : Classloader es un subsistema de JVM que se utiliza para cargar archivos de clases.
2. Área de clase (método) : El área de clase (método) almacena estructuras por clase, como el grupo de constantes de tiempo de ejecución, datos de métodos y campos, y el código de los métodos.
3. Montón : es el área de datos en tiempo de ejecución donde se asignan los objetos.
4. Pila : Java Stack almacena marcos. Contiene variables locales y resultados parciales, y desempeña un papel en la invocación y el retorno de métodos. Cada hilo tiene una pila JVM privada, creada al mismo tiempo que el hilo.
5. Registro del contador de programas : Registro de PC (contador de programas). Contiene la dirección de la instrucción de la máquina virtual Java que se está ejecutando actualmente.
6. Pila de métodos nativos : contiene todos los métodos nativos utilizados en la aplicación.
↥ volver arriba
La conversión automática de tipos de datos primitivos a su tipo Wrapper equivalente se conoce como boxeo y la operación opuesta se conoce como unboxing.
Ejemplo: autoboxing
/** * Autoboxing */class BoxingExample { public static void main(String args[]) { int a = 50; Entero a2 = nuevo entero(a); // Boxeo Entero a3 = 5; // Sistema de boxeo.out.println(a2 + " " + a3); } }
Ejemplo: desempaquetar
/** * Unboxing */class UnboxingExample { public static void main(String args[]) { Entero i = new Integer(50); int a = yo; System.out.println(a); } }
↥ volver arriba
1. Transitorio:
El modificador transitorio le dice al subsistema de serialización de objetos Java que excluya el campo al serializar una instancia de la clase. Cuando se deserializa el objeto, el campo se inicializará con el valor predeterminado; es decir, nulo para un tipo de referencia y cero o falso para un tipo primitivo.
Ejemplo:
/** * Transitorio */public transitorio int limit = 55; // no persistirápublic int b; // persistirá
2. Volátil:
El modificador volátil le dice a la JVM que las escrituras en el campo siempre deben vaciarse sincrónicamente en la memoria y que las lecturas del campo siempre deben leerse desde la memoria. Esto significa que se puede acceder y actualizar de forma segura los campos marcados como volátiles en una aplicación multiproceso sin utilizar sincronización nativa o basada en biblioteca estándar.
Ejemplo:
/** * Volátil */public class MyRunnable implements Runnable { privado volátil booleano activo; ejecución pública vacía() { activo = verdadero; mientras (activo) { } } parada nula pública() { activo = falso; } }
↥ volver arriba
Una afirmación permite probar la exactitud de cualquier suposición que se haya hecho en el programa. La afirmación se logra utilizando la declaración de afirmación en Java.
Al ejecutar una afirmación, se cree que es cierta. Si falla, JVM genera un error denominado AssertionError
. Se utiliza principalmente con fines de prueba durante el desarrollo.
La declaración de afirmación se usa con una expresión booleana y se puede escribir de dos maneras diferentes.
// Primera forma de afirmar expresión;// Segunda forma de afirmar expresión1: expresión2;
Ejemplo:
/** * Afirmaciones */public class Ejemplo { public static void main(String[] args) { int age = 14; afirmar edad <= 18: "No puedo votar"; System.out.println("La edad del votante es " + edad); } }
↥ volver arriba
1. Variable final:
Las variables finales no son más que constantes. No podemos cambiar el valor de una variable final una vez inicializada.
Ejemplo:
/** * Variable final */class Demostración { final int MAX_VALUE = 99; void miMétodo() { MAX_VALUE = 101; } public static void main(String args[]) { Demo obj = new Demo(); obj.myMethod(); } }
Producción
Excepción en el hilo "principal" java.lang.Error: problema de compilación no resuelto: El campo final Demo.MAX_VALUE no se puede asignar en principiantesbook.com.Demo.myMethod(Details.java:6)en principiantesbook.com.Demo.main(Details.java:10)
2. Variable final en blanco:
Una variable final que no se inicializa en el momento de la declaración se conoce como variable final en blanco. Debemos inicializar la variable final en blanco en el constructor de la clase, de lo contrario arrojará un error de compilación (Error: variable MAX_VALUE might not have been initialized
).
Ejemplo:
/** * Variable final en blanco */class Demo { // Variable final en blanco final int MAX_VALUE; Demo() { // Debe inicializarse en el constructor MAX_VALUE = 100; } void myMethod() { System.out.println(MAX_VALUE); } public static void main(String args[]) { Demo obj = new Demo(); obj.myMethod(); } }
Producción
100
3. Método final:
No se puede anular un método final. Lo que significa que aunque una subclase puede llamar al método final de la clase principal sin ningún problema, no puede anularlo.
Ejemplo:
/** * Método final */class XYZ { final void demo() { System.out.println("Método de clase XYZ"); } }clase ABC extiende XYZ { void demo() { System.out.println("Método de clase ABC"); } public static void main(String args[]) { ABC obj = new ABC(); obj.demo(); } }
↥ volver arriba
Si un tipo primitivo o una cadena se define como una constante y el valor se conoce en el momento de la compilación, el compilador reemplaza el nombre de la constante en todas partes del código con su valor. Esto se llama constante de tiempo de compilación.
La constante de tiempo de compilación debe ser:
Declarado definitivo
Primitivo o cadena
Inicializado dentro de la declaración
Inicializado con expresión constante
Se reemplazan con valores reales en tiempo de compilación porque el compilador conoce su valor por adelantado y también sabe que no se puede cambiar durante el tiempo de ejecución.
privado final int x = 10;
↥ volver arriba
Los especificadores/modificadores de acceso ayudan a restringir el alcance de una clase, constructor, variable, método o miembro de datos.
Hay cuatro tipos de modificadores de acceso disponibles en Java:
default
: no se requiere palabra clave, cuando una clase, constructor, variable, método o miembro de datos se declara sin ningún especificador de acceso, entonces tiene un alcance de acceso predeterminado, es decir, accesible solo dentro del mismo paquete.
private
: cuando se declara como privado, el alcance del acceso está limitado dentro de la clase adjunta.
protected
: cuando se declara como protegido, el alcance del acceso se limita a incluir clases, subclases del mismo paquete y otros paquetes.
public
: cuando se declara público, accesible en todas partes del programa.
... /* variables miembro de datos */ String firstName="Pradeep"; /* alcance predeterminado */ protected isValid=true; /* ámbito protegido */ cadena privada otp="AB0392"; /* ámbito privado */ public int id = 12334; /* alcance público */ ... ... /* funciones miembro de datos */ String getFirstName(){ return this.firstName; } /* alcance predeterminado */ protected boolean getStatus(){this.isValid;} /* alcance protegido */ private void generateOtp(){ /* alcance privado */ this.otp = this.hashCode() << 16; }; public int getId(){ devolver este.id; } /* alcance público */ ... .../* clases internas */ clase A{} /* alcance predeterminado */ clase protegida B{} /* alcance protegido */ clase privada C{} /* alcance privado */ clase pública D{} /* alcance público */ ...
↥ volver arriba
En Java, todos los métodos no estáticos son por defecto funciones virtuales . Sólo los métodos marcados con la palabra clave final
, que no se pueden anular, junto con private methods
, que no se heredan, no son virtuales.
Ejemplo: función virtual con interfaz
/** * La función applyBrakes() es virtual porque * las funciones en las interfaces están diseñadas para ser anuladas. **/interface Bicicleta { void applyBrakes(); }class ACMEBicycle implements Bicycle { public void applyBrakes() { // Aquí implementamos applyBrakes() System.out.println("Frenos aplicados"); // función } }
↥ volver arriba
Un método nativo es un método Java (ya sea un método de instancia o un método de clase) cuya implementación también está escrita en otro lenguaje de programación como C/C++. Además, un método marcado como nativo no puede tener cuerpo y debe terminar con un punto y coma:
Principal.java:
clase pública Principal { público nativo int intMethod(int i); public static void main(String[] args) { System.loadLibrary("Principal"); System.out.println(new Main().intMethod(2)); } }
Principal.c:
#include <jni.h>#include "Main.h"JNIEXPORT jint JNICALL Java_Main_intMethod( JNIEnv *env, jobject obj, jint i) { return i * i; }
Compilar y ejecutar:
javac Main.javajavah -jni Maingcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux Main.cjava -Djava.library.path=. Principal
Producción
4
↥ volver arriba
Si un método se declara como estático, es miembro de una clase en lugar de pertenecer al objeto de la clase. Se puede llamar sin crear un objeto de la clase. Un método estático también tiene el poder de acceder a datos estáticos de los miembros de la clase.
Hay algunas restricciones impuestas a un método estático.
El método estático no puede utilizar miembros de datos no estáticos ni invocar métodos no estáticos directamente.
this
y super
no se pueden usar en contexto estático.
El método estático solo puede acceder a datos de tipo estático (variable de instancia de tipo estático).
No es necesario crear un objeto de la clase para invocar el método estático.
Un método estático no se puede anular en una subclase
Ejemplo:
/** * Métodos estáticos */class Parent { static void display() { System.out.println("Superclase"); } }El ejemplo de clase pública extiende Padre { void display() // intentando anular display() { System.out.println("Subclase"); } público estático vacío principal (String [] argumentos) { Obj principal = nuevo Ejemplo(); obj.display(); } }
Esto genera un error en tiempo de compilación. El resultado es el siguiente:
Ejemplo.java:10: error: display() en el ejemplo no puede anular display() en Parentvoid display() // intentando anular display() ^el método anulado es un error estático1
↥ volver arriba
¿Cuál es la estructura y las características del uso de una expresión lambda? Una lambda es un conjunto de instrucciones que se pueden separar en una variable separada y luego llamar repetidamente en varios lugares del programa.
La base de la expresión lambda es el operador lambda , que representa la flecha ->
. Este operador divide la expresión lambda en dos partes: el lado izquierdo contiene una lista de parámetros de expresión y el lado derecho representa el cuerpo de la expresión lambda, donde se realizan todas las acciones.
La expresión lambda no se ejecuta por sí sola, sino que forma la implementación del método definido en la interfaz funcional. Es importante que la interfaz funcional contenga un solo método sin implementación.
interfaz Operable { int calcular (int x, int y); }public static void main ( String [] args) { Operación operativa = (x, y) - > x + y; int resultado = operación.calcular (10, 20); System.out.println (resultado); // 30 }
De hecho, las expresiones lambda son de alguna manera una forma abreviada de clases anónimas internas que se usaban anteriormente en Java.
Expresiones lambda de ejecución diferida : se define una vez en un lugar del programa, se llama si es necesario, cualquier número de veces y en cualquier lugar del programa.
Los parámetros de la expresión lambda deben corresponder en tipo a los parámetros del método de interfaz funcional:
operación = (int x, int y) - > x + y;// Al escribir la expresión lambda en sí, no se permite especificar el tipo de parámetro: (x, y) - > x + y;// Si el método no acepta ningún parámetro, entonces se escriben corchetes vacíos, por ejemplo: () - > 30 + 20 ;// Si el método acepta solo un parámetro, entonces se pueden omitir los corchetes: n - > n * n;
No es necesario que las expresiones lambda finales devuelvan ningún valor.
interfaz Imprimible { void print( String s ); } public static void main ( String [] args) { Impresora imprimible = s - > System.out.println(s); impresora.print("Hola mundo"); }// _ Las expresiones lambda del bloque_ están rodeadas por llaves. Las expresiones lambda modulares se pueden usar dentro de bloques anidados, bucles, `diseñar la `` declaración de cambio ' if, crear variables, etc. d . Si bloquea una expresión lambda debe devolver un valor, se aplica explícitamente `declaración de retorno de declaración ': Operación operable = (int x, int y) - > { si (y == 0) {retorno 0; } más {return x/y; } };
Pasar una expresión lambda como parámetro de método
Condición de interfaz { booleano es apropiado (int n); }privada estática int suma (int [] números, condición condición) { int resultado = 0; for ( int i : números) { if (condition.isAppropriate(i)) { resultado + = i; } } devolver resultado; }public static void main ( String [] args) { System.out.println(sum (new int [] { 0, 1, 0, 3, 0, 5, 0, 7, 0, 9 }, (n) - > norte ! = 0 )); }
↥ volver arriba
El acceso a variables de alcance externo desde una expresión lambda es muy similar al acceso desde objetos anónimos.
variables locales inmutables (efectivamente finales, no necesariamente marcadas como finales);
campos de clase
variables estáticas.
No se permite acceder a los métodos predeterminados de la interfaz funcional implementada dentro de la expresión lambda.
↥ volver arriba
Si el método existente en la clase ya hace todo lo necesario, entonces puede usar el mecanismo de referencia del método (referencia del método) para pasar este método directamente. El resultado será exactamente el mismo que en el caso de definir una expresión lambda que llame a este método.
Ejemplo:
interfaz privada Medible { public int length(String string); }public static void main ( String [] args) { Medible a = String::length; System.out.println(a.length("abc")); }
Las referencias a métodos son potencialmente más eficientes que el uso de expresiones lambda. Además, proporcionan al compilador mejor información sobre el tipo, y si puede elegir entre usar una referencia a un método existente y usar una expresión lambda, siempre debe usar una referencia de método.
↥ volver arriba
sobre el método estático;
método por instancia;
al constructor.
↥ volver arriba
La clase interna anidada puede acceder a cualquier variable de instancia privada de la clase externa. Como cualquier otra variable de instancia, podemos tener modificador de acceso privado, protegido, público y predeterminado.
Ejemplo:
/** * Clase interna */clase externa { clase interna { espectáculo público vacío() { System.out.println("En un método de clase anidada"); } } } clase principal { público estático vacío principal (String [] argumentos) { Exterior.Interior en = nuevo Exterior().nuevo Interior(); en.mostrar(); } }
Una subclase es una clase que hereda uno o varios métodos de una superclase.
Ejemplo:
/** * Subclase */class Coche { //...} class HybridCar extiende Car { //...}
↥ volver arriba
1. Carga de clases estáticas:
La creación de objetos e instancias utilizando new
palabra clave se conoce como carga de clases estática. La recuperación de la definición de clase y la creación de instancias del objeto se realiza en tiempo de compilación.
Ejemplo:
/** * Carga de clases estáticas */class TestClass { public static void main(String args[]) { TestClass tc = new TestClass(); } }
2. Carga dinámica de clases:
La carga de clases utiliza el método Class.forName()
. La carga dinámica de clases se realiza cuando el nombre de la clase no se conoce en el momento de la compilación.
Ejemplo:
/** * Carga dinámica de clases */Class.forName (String className);
↥ volver arriba
1. Clase de tiempo de ejecución:
La clase java.lang.Runtime es una subclase de la clase Object y proporciona acceso al sistema de ejecución de Java. La información del tiempo de ejecución, como la disponibilidad de memoria, la invocación del recolector de basura, etc.
Ejemplo:
/** * Clase de tiempo de ejecución */public class RuntimeTest { clase estática Mensaje extiende hilo { public void run() { System.out.println(" Salir"); } } public static void main(String[] args) { prueba { Runtime.getRuntime().addShutdownHook(new Message()); System.out.println("Programa iniciado..."); System.out.println(" Espere 5 segundos..."); Hilo.sleep(5000); System.out.println("Programa finalizado..."); } catch (Excepción e) { e.printStackTrace(); } } }
2. Clase de sistema:
El propósito de la clase System es proporcionar acceso a los recursos del sistema. Contiene accesibilidad a la entrada estándar, salida de StandAr, transmisiones de salida de error, tiempo actual en milis, terminando la aplicación, etc.
↥ De vuelta a la cima
1. Uso de una nueva palabra clave:
Objeto myObject = new MyObject ();
2. Uso de class.forname ():
Myobject object = (myObject) class.forname ("Subin.rnd.myobject"). NewInStance ();
3. Usando clon ():
MyObject othingObject = new myObject (); myObject Object = (myObject) otherObject.clone ();
4. Uso de la deserialización del objeto:
ObjectInputStream Intilam = new ObjectInputStream (anInputStream); myObject Object = (myObject) Insteam.ReadObject ();
↥ De vuelta a la cima
Los objetos inmutables son objetos que no cambian. Un objeto inmutable de Java debe tener todos sus campos que sean campos finales privados internos. No debe implementar ningún setter. Necesita un constructor que tome un valor para cada campo.
Creando un objeto inmutable:
No agregue ningún método de setter
Declarar todos los campos finales y privados
Si un campo es un objeto mutable, cree copias defensivas para los métodos de Getter
Si se debe asignar un objeto mutable al constructor a un campo, cree una copia defensiva de él
No permita que las subclases anulen los métodos.
/** * Objeto inmutable */public class DataContainer {fecha de fecha final privada; public DataContainer () {this.date = new Date (); } Public Date getDate () {return nueva fecha (date.gettime ()); } }
↥ De vuelta a la cima
Clase inmutable significa que una vez que se crea un objeto, no podemos cambiar su contenido. En Java, todas las clases de envoltura (como Integer, Boolean, Byte, Short) y la clase de cadena son inmutables.
Reglas para crear clases inmutables:
La clase debe ser declarada como final
Los miembros de los datos en la clase deben declararse como finales
Un constructor parametrizado
Método Getter para todas las variables en él
No Setters
/** * Clase inmutable */Public Final Clase Employee {Final String PancardNumber; Public Employee (String PancardNumber) {this.pancardNumber = PancardNumber; } public String getPancardNumber () {return pancardNumber; } }
↥ De vuelta a la cima
Bootstrap ClassLoader es repossible para cargar archivos estándar de clases JDK de rt.jar y es padre de todos los cargadores de clases en Java. Hay tres tipos de cargador de clase incorporado en Java:
1. Cargador de clase Bootstrap: Carga las clases internas JDK, generalmente carga RT.jar y otras clases principales, por ejemplo, Java.lang.* Clases de paquetes
2. Cargador de clase de extensiones: carga clases desde el directorio de extensiones JDK, generalmente $ java_home/lib/ext directorio.
3. Cargador de clase del sistema: carga clases de la classpath actual que se puede configurar mientras invoca un programa usando opciones de línea de comandos -cp o -Classpath.
/** * classloader */import java.util.logging.level; import java.util.logging.logger; public classloaderTest {public static void main (string args []) {try {// Impresión de clases de este sistema de clases .out.println ("ClassLoader:" + classloaderTest.class.getClassLoader ()); // Intentando cargar explícitamente esta clase nuevamente usando la clase de carro de extensión class.forname ("Clase de carga explícitamente", true, classloaderTest.class.getClassLoader (). getParent ()); } Catch (ClassNotFoundException ex) {logger.getLogger (classloaderTest.class.getName ()). log (nivel.severe, null, ex); } } }
↥ De vuelta a la cima
Diferentes formas de crear un objeto en Java
Uso de una nueva palabra clave:
clase ObjectCreationExample {String propietario; } public class MainClass {public static void main (string [] args) {// Aquí estamos creando objeto de JBT usando nuevo WordObjectCreationExample OBJ = new ObjectCreationExample (); } }
Usando una nueva instancia (reflexión)
clase createObjectClass {static int j = 10; createObjectClass () {i = j ++; } int i; @OverridePublic String toString () {return "valor de i:" + i; } } class MainClass {public static void main (string [] args) {try {class cls = class.forname ("createObjectClass"); createObjectClass obj = (createObjectClass) cls.newinstance (); createObjectClass obj1 = (createObjectClass) Cls.newinstance (); System.out.println (obj); system.out.println (obj1); } catch (ClassNotFoundException e) {E.PrintStackTrace (); } catch (InstanciationException e) {E.PrintStackTrace (); } catch (ilegalAccessException e) {E.PrintStackTrace (); } } }
Usando clon:
La clase CreateObjectWithClone implementa clonable {@OverrideProtected Object clone () lanza ClonenOtsupportedException {return super.clone (); } int i; static int j = 10; createObjectWithClone () {i = j ++; } @OverridePublic String toString () {return "valor de i:" + i; } } class MainClass {public static void main (string [] args) {createObjectWithClone obj1 = new createObjectWithClone (); system.out.println (obj1); try {createObjectWithClone obj2 = (createObjectWithClone) obj1.clone (); system.out. println (obj2); } Catch (ClonenotsupportedException e) {E.PrintStackTrace (); } } }
Usando classloader
clase createObjectWithClassLoader {static int j = 10; createObjectWithClassLoader () {i = j ++; } int i; @OverridePublic String toString () {return "valor de i:" + i; } } public class MainClass {public static void main (string [] args) {createObjectWithClassLoader obj = null; try {obj = (createObjectWithClassLoader) New MainClass (). getClass () .getClassLoader (). LoadClass ("CreateObjectWithClassLoader"). NewInStance (); // debe usarse el nombre de clase totalmente calificado. } catch (InstanciationException e) {E.PrintStackTrace (); } catch (ilegalAccessException e) {E.PrintStackTrace (); } catch (ClassNotFoundException e) {E.PrintStackTrace (); } System.out.println (obj); } }
↥ De vuelta a la cima
La clase de objeto es la clase principal de todas las clases en Java de forma predeterminada.
Método | Descripción |
---|---|
Clase final pública getClass () | Devuelve el objeto de clase de clase de este objeto. La clase de clase se puede usar para obtener los metadatos de esta clase. |
Public int hashcode () | Devuelve el número de hashcode para este objeto. |
público booleano es igual (obj obj) | compara el objeto dado con este objeto. |
Objeto protegido Clone () arroja clonenotsupportedException | Crea y devuelve la copia exacta (clon) de este objeto. |
Cadena pública ToString () | Devuelve la representación de cadena de este objeto. |
Public Final NUEVE Notify () | Retire un solo hilo, esperando en el monitor de este objeto. |
Público Final Void notifyall () | Retire todos los hilos, esperando en el monitor de este objeto. |
Public Final Void Wait (Tiempo de espera largo) Lanza interruptedException | Hace que el hilo actual espere los milisegundos especificados, hasta que otro hilo notifique (invoca el método notify () o notifyall ()). |
Public Final Void Wait (Long TimeOut, int nanos) lanza interruptedException | Hace que el hilo actual espere los milisegundos y nanosegundos especificados, hasta que otro hilo notifique (invoca el método notify () o notifyall ()). |
Public Final NUEVE Wait () lanza interruptedException | Hace que el hilo actual espere, hasta que otro hilo notifique (invoca el método notify () o notifyall ()). |
El vacío protegido finalize () lanza lanzamiento | el recolector de basura se invoca antes de que el objeto sea recolectado de basura. |
↥ De vuelta a la cima
Un valor opcional Optional
es un contenedor para un objeto que puede o no contener un valor null
. Tal envoltura es un medio conveniente de prevención