El siguiente contenido son preguntas y respuestas responsables dadas después del conjunto de preguntas de entrevista de Java original y se revisaron por completo. Hay muchas preguntas duplicadas y preguntas valiosas en las preguntas originales, y muchas respuestas de referencia también son incorrectas. El conjunto de preguntas de entrevista de Java modificado se refiere a la última versión de JDK, elimina contenido inútil como EJB 2.x, y complementa la estructura de datos y las preguntas relacionadas con el algoritmo, las preguntas de programación de entrevistas clásicas, la gran arquitectura técnica del sitio web, el sistema operativo, la base de datos, las pruebas de software, los patrones de diseño, el UML y otro contenido. Al mismo tiempo, se han analizado profundamente muchos puntos de conocimiento, como el diseño del método hashcode, el montón y la generación de recolección de basura, la nueva programación concurrente de Java, NIO.2, etc. Creo que será de beneficio para los programadores de Java que se están preparando para unirse.
Preguntas de entrevista del programador de Java establecido (1-50)
1. Java Conceptos básicos
1. ¿Cuáles son los aspectos de las características orientadas a objetos?
Respuesta: Los aspectos principales de las características orientadas a objetos son:
1) Resumen: La abstracción es el proceso de resumir las características comunes de un tipo de objeto en una clase de objetos, incluida la abstracción de datos y la abstracción del comportamiento. La abstracción solo se centra en qué atributos y comportamientos tiene el objeto, y no presta atención a cuáles son los detalles de estos comportamientos.
2) Herencia: la herencia es el proceso de obtener información de herencia de las clases existentes y crear nuevas clases. La clase que proporciona información hereditaria se llama clase principal (superclase, clase base); La clase que obtiene información hereditaria se llama subclase (clase derivada). La herencia le da al sistema de software cambiante un cierto grado de continuidad, y la herencia también es un medio importante para encapsular factores variables en el programa (si no puede entenderlo, lea la parte sobre el modo puente en el "Java y patrones" del Dr. Yan Hong "o" Patrones de diseño exquisitos ").
3) Encapsulación: generalmente se cree que la encapsulación es unir los datos al método de operación de datos, y el acceso a los datos solo se puede lograr a través de la interfaz definida. La esencia de los objetos orientados es retratar el mundo real como una serie de objetos completamente autónomos y cerrados. El método que escribimos en una clase es encapsular los detalles de implementación; Escribimos una clase es encapsular las operaciones de datos y datos. Se puede decir que el embalaje es ocultar todo lo que se puede ocultar, y solo proporciona la interfaz de programación más simple para el mundo exterior (puede pensar en la diferencia entre una lavadora ordinaria y una lavadora totalmente automática. Es obvio que la lavadora completamente automática está mejor empaquetada y, por lo tanto, más fácil de operar; el teléfono inteligente que usamos ahora también está bien empaquetado bien porque algunos de los botones pueden manejar todo).
4) Polimorfismo: el polimorfismo se refiere a permitir que los objetos de diferentes subtipos respondan de manera diferente al mismo mensaje. En pocas palabras, es llamar al mismo método con la misma referencia de objeto pero hacer cosas diferentes. Los polimorfismos se dividen en polimorfismos en tiempo de compilación y polimorfismos de tiempo de ejecución. Si el método del objeto se considera un servicio proporcionado por el objeto al mundo exterior, entonces el polimorfismo de tiempo de ejecución se puede explicar como: cuando el sistema A accesas los servicios proporcionados por el Sistema B, el Sistema B tiene múltiples formas de proporcionar servicios, pero todo es transparente para el Sistema A (al igual que una Shaver eléctrica es el sistema A, su Sistema de alimentación B es el Sistema B, el Sistema B puede ser alimentado por las baterías o AC o AC, y puede ser Solar Energy A SOLY A SOLD A SOLO MEJOR SISTEMA SISTEMA ES SISTEMA B A SUMITADO SISTEMA SISTEMA CLASE SISTEMA BUSH SISTEMA CUENTA SISTEMA BAYO EN Objetos, pero no sabe cuál es la implementación subyacente del sistema de fuente de alimentación y cómo obtiene energía). La sobrecarga de métodos implementa el polimorfismo de tiempo de compilación (también conocido como preodificación), mientras que el método anular implementa el polimorfismo en tiempo de ejecución (también conocido como posada posterior). El polimorfismo de tiempo de ejecución es lo más esencial de orientarse a objetos. Para implementar el polimorfismo, se deben hacer dos cosas: 1. Reescritura del método (la subclase hereda la clase principal y reescribe métodos existentes o abstractos en la clase principal); 2. Modelado de objetos (refiriéndose al objeto tipo niño con la referencia de tipo principal, de modo que las mismas llamadas de referencia, el mismo método, mostrará diferentes comportamientos de acuerdo con los diferentes objetos de subclase).
2. ¿Cuál es la diferencia entre el acceso a los modificadores públicos, privados, protegidos y no escritos (predeterminados)?
Respuesta: Las diferencias son las siguientes:
El alcance es el mismo que la subclase BUN.
público √ √ √ √ √ √
protegido √ √ √ ×
predeterminado √ √ × ×
Privado √ × × ×
El valor predeterminado es predeterminado cuando los miembros de la clase no escriben la modificación de acceso. Por defecto, es equivalente al público para otras clases en el mismo paquete, y privado para otras clases que no están en el mismo paquete. Proteged es equivalente a las subclases públicas y privadas a las clases que no están en el mismo paquete que no tienen una relación padre-hijo.
3. ¿Es la cadena el tipo de datos más básico?
Respuesta: No. Solo hay 8 tipos de datos básicos en Java: Byte, Short, Int, Long, Float, Double, Char y Boolean; Excepto por el tipo básico (tipo primitivo) y el tipo de enumeración (tipo de enumeración), el resto son tipos de referencia (tipo de referencia).
4. Flotar F = 3.4; ¿Es correcto?
Respuesta: Incorrecto. 3.4 es un número de doble precisión. Asignar doble al tipo de punto flotante (FLOAT) causará pérdida de precisión (fundición descendente, también conocida como estrechamiento), por lo que debe lanzar el flotador F = (Float) 3.4; o escribir flotante f = 3.4f;.
5. Short S1 = 1; S1 = S1 + 1; ¿Hay algo mal? corto S1 = 1; S1 += 1; ¿Hay algo mal?
Respuesta: para breves S1 = 1; S1 = S1 + 1; Dado que 1 es un tipo INT, el resultado de la operación S1+1 también es un tipo INT, y se requiere un tipo de lanzamiento para asignar valor al tipo corto. Y corto S1 = 1; S1 += 1; puede compilarse correctamente porque S1+= 1; es equivalente a S1 = (corto) (S1 + 1); Hay moldes implícitos.
6. ¿Hay un GoTo en Java?
Respuesta: GOTO es una palabra reservada en Java y no se usa en la versión actual de Java. (Una lista de palabras clave Java se da en el apéndice del libro "El lenguaje de programación Java" escrito por James Gosling (el padre de Java) que incluye GoTo y Const, pero estas dos son palabras clave que actualmente no se pueden usar, por lo que algunos lugares lo llaman palabras reservadas. De hecho, las palabras reservadas de palabras deben tener un significado más amplio, ya que los programadores están familiarizados con el lenguaje C conocen que las palabras o las combinaciones de las palabras reservadas que tienen las palabras de las palabras de palabras que se consideran las palabras del sistema. palabras reservadas)
7. ¿Cuál es la diferencia entre int y entero?
Respuesta: Java es un lenguaje de programación casi puro orientado a objetos, pero para la conveniencia de la programación, todavía presenta tipos de datos básicos que no son objetos. Sin embargo, para operar estos tipos de datos básicos como objetos, Java ha introducido la clase de contenedor correspondiente para cada tipo de datos básicos. La clase de embalaje de INT es entero. Desde JDK 1.5, se ha introducido un mecanismo automático de embalaje/desempaquetado, de modo que los dos se pueden convertir entre sí.
Java proporciona tipos de envoltorio para cada tipo primitivo:
Tipos primitivos: booleano, char, byte, corto, int, largo, flotante, doble
Tipos de embalaje: booleano, personaje, byte, corto, entero, largo, flotante, doble
paquete com.lovo; // ¿Por qué preguntar sobre Hovertree.comPublic Class AutounboxingTest {public static void main (string [] args) {integer a = nuevo entero (3); Entero b = 3; // Cuadro automático 3 en el tipo entero int c = 3; System.out.println (a == b); // Falso Las dos referencias no hacen referencia al mismo objeto System.out.println (a == c); // Verdadero A Unboxes automáticamente en el tipo int y luego se compara con C}}Agregado: Recientemente encontré una pregunta de la entrevista, que también está relacionada con el embalaje automático y el desempaquetado, el código es el siguiente:
public class test03 {public static void main (string [] args) {integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; System.out.println (F1 == F2); System.out.println (F3 == F4); }} // Hovertree.comSi no lo entiende, es fácil pensar que ambas salidas son verdaderas o falsas. En primer lugar, es importante tener en cuenta que las cuatro variables F1, F2, F3 y F4 son todos objetos enteros, por lo que la operación == siguiente compara no valores sino referencias. ¿Cuál es la esencia del embalaje? Cuando asignamos un valor int a un objeto entero, llamaremos al valor del método estático de la clase entera. Si observamos el código fuente de valor de valor, sabremos lo que está sucediendo.
public static entero valor de (int i) {if (i> = integerCache.low && i <= integerCache.high) return integerCache.cache [i + (-intregerCache.low)]; devolver nuevo entero (i); } // Hovertree.comIntegerCache es una clase interna de entero, y su código se ve así:
/** * Cache para admitir la semántica de identidad de objetos del autoboxing para los valores entre * -128 y 127 (inclusive) según lo requerido por JLS. * * El caché se inicializa en el primer uso. El tamaño del caché * puede ser controlado por la opción {@code -xx: autoboxcachemax = <size>}. * Durante la inicialización de VM, java.lang.integer.integercache.high propiedad * puede establecerse y guardar en las propiedades del sistema privado en la clase * Sun.misc.vm. * Hovertree.com */ private static class IntegerCache {static final int low = -128; estático final int high; Cache entero final estático []; static {// El valor alto puede configurarse mediante la propiedad int h = 127; String IntegerCacheHighPropValue = Sun.Misc.Vm.GetSavedProperty ("java.lang.integer.integercache.high"); if (integerCacheHighPropValue! = null) {try {int i = parseInt (integerCacheHighPropValue); i = math.max (i, 127); // El tamaño máximo de la matriz es integer.max_value h = math.min (i, integer.max_value -(-low) -1); } Catch (NumberFormateException nfe) {// Si la propiedad no se puede analizar en un int, ignórelo. }} high = h; caché = nuevo entero [(alto - bajo) + 1]; int j = bajo; para (int k = 0; k <cache.length; k ++) caché [k] = nuevo entero (j ++); // El rango [-128, 127] debe ser internalizado (jls7 5.1.7) afirmar integercache.high> = 127; } private integerCache () {}}En pocas palabras, si el valor literal es entre -128 y 127, entonces el nuevo objeto entero no será nuevo, pero el objeto entero en el grupo constante se referirá directamente. Por lo tanto, el resultado de F1 == F2 en la pregunta de la entrevista anterior es verdadero, y el resultado de F3 == F4 es falso. Cuantas más preguntas de la entrevista, más misterio hay, y el entrevistador debe tener habilidades considerables.
8. ¿Cuál es la diferencia entre & y &&?
Respuesta: Hay dos usos del operador: (1) bit a bitwise y (2) lógico y. El operador && es un cortocircuito y operación. La diferencia entre la lógica y los cortocircuitos es muy grande, aunque ambos requieren que los valores booleanos en los extremos izquierdo y derecho del operador sean verdaderos al valor de toda la expresión. && se llama operación de cortocircuito porque si el valor de la expresión a la izquierda de && es falsa, la expresión a la derecha se corta directamente y la operación no se realizará. Muchas veces es posible que necesitemos usar && en lugar de &. Por ejemplo, al verificar que el nombre de usuario no es nulo y no es una cadena vacía, debe escribirse como: UserName! = NULL &&! UserName.Equals (""). El orden de los dos no se puede intercambiar, y el operador & no se puede usar, porque si la primera condición no es verdadera, la comparación igual de la cadena no se puede realizar en absoluto, de lo contrario se generará una NullPointerException. Nota: Lo mismo es verdadero para la diferencia entre lógico o operador (|) y cortocircuito u operador (||).
Agregado: si está familiarizado con JavaScript, es posible que pueda sentir más el poder de la computación de cortocircuito. Si quieres convertirte en un maestro de JavaScript, comience reproduciendo computación de cortocircuito.
9. Explique el uso de áreas de almacenamiento de pila, montón y estática en la memoria.
Respuesta: Por lo general, definimos una variable del tipo de datos básico, una referencia de objeto y el almacenamiento en el sitio de las llamadas a la función usa el espacio de pila en la memoria; y los objetos creados a través de la nueva palabra clave y constructor se colocan en el espacio del montón; Los literales en el programa, como 100, "hola" y constantes escritas directamente se colocan en el área de almacenamiento estático. El espacio de la pila funciona más rápido pero también es muy pequeño. Por lo general, se coloca una gran cantidad de objetos en el espacio de montón, y toda la memoria, incluida la memoria virtual en el disco duro, se puede usar como espacio de montón.
Cadena str = new String ("Hello");
En la declaración anterior, STR se coloca en la pila, el objeto de cadena creado con nuevo se coloca en el montón y el "hola" literal se coloca en el área de almacenamiento estático.
Suplemento: una versión más nueva de Java utiliza una tecnología llamada "Análisis de escape" que puede colocar algunos objetos locales en la pila para mejorar el rendimiento operativo de los objetos.
10. ¿A qué es Math.round (11.5) igual? ¿A qué es Math.round (-11.5) igual?
Respuesta: El valor de retorno de Math.round (11.5) es 12, y el valor de retorno de Math.round (-11.5) es -11. El principio de redondeo es agregar 0.5 al parámetro y luego redondearlo hacia abajo.
11.
Respuesta: En el JDK temprano, en Switch (ExpR), Expr puede ser Byte, Short, Char e Int. A partir de la versión 1.5, Java ha introducido tipos de enumes (enums), y EXPR también puede ser enums, a partir de la versión 1.7 de JDK, y también una cadena (cadena). No está permitido el tipo largo.
12. Use el método más eficiente para calcular 2 veces 8?
Respuesta: 2 << 3 (Mover 3 bits a la izquierda es equivalente a multiplicar por 2 a la potencia de 3, y mover 3 bits a la derecha es equivalente a dividir por 2 al poder de 3).
Suplemento: cuando reescribimos el método hashcode para la clase que escribimos, podemos ver el código que se muestra a continuación. De hecho, no entendemos por qué usamos dicha multiplicación para generar un código hash (código hash), y por qué este número es un número primo y por qué generalmente se selecciona el número 31. Puede Baidu sobre las respuestas a las dos primeras preguntas. Elija 31 porque las operaciones de cambio y sustracción se pueden usar en lugar de multiplicación, logrando así un mejor rendimiento. Hablando de esto, es posible que haya pensado: 31 * num <==> (num << 5) - num, cambiar los 5 bits izquierdos es equivalente a multiplicar por 2 a la 5ta potencia (32) y restarse es equivalente a multiplicar por 31. Todos los VM pueden completar automáticamente esta optimización.
paquete com.loonstudio; Clase pública PhoneNumber {private int AreaCode; prefijo de cadena privada; Cadena privada de lino; @Override public int hashcode () {final int prime = 31; int resultado = 1; Result = Prime * Result + AreaCode; resultado = Prime * resultado + ((Linenumber == NULL)? 0: Linenumber.hashCode ()); resultado = prime * resultado + ((prefix == null)? 0: prefix.hashcode ()); resultado de retorno; } @Override public boolean iguales (objeto obj) {if (this == obj) return true; if (obj == null) return false; if (getClass ()! = obj.getClass ()) return false; PhoneNumber Otro = (PhoneNumber) obj; if (AreaCode! = Other.areAcode) return false; if (linenumber == null) {if (other.linenumber! = null) return false; } else if (! Linenumber.equals (OTRO.LINEENEMBER)) return false; if (prefix == null) {if (otro.prefix! = null) return false; } else if (! prefix.equals (other.prefix)) return false; devolver verdadero; }} // ¿Por qué preguntar sobre Hovertree.com13. ¿Hay un método de longitud () para matrices? ¿Hay un método de longitud () para cadena?
Respuesta: La matriz no tiene un método Longitud (), pero tiene un atributo de longitud. La cadena tiene un método de longitud (). En JavaScript, la obtención de la longitud de la cadena se obtiene a través del atributo de longitud, que se confunde fácilmente con Java.
14. En Java, ¿cómo salir de los bucles anidados múltiples actuales?
Respuesta: Agregue una marca como A antes del bucle más externo, y luego use Break A; Se pueden romper múltiples bucles. (Java admite declaraciones etiquetadas Break y continúa, y sus funciones son un poco similares a las declaraciones de GOTO en C y C ++, pero al igual que evitar GOTO, debe evitar la ruptura etiquetada y continuar porque no hará que su programa sea más elegante, y a menudo incluso tendrá el efecto contrario, por lo que esta sintaxis es realmente mejor)).
15. ¿Se puede anular el constructor?
Respuesta: El constructor no puede ser heredado, por lo que no se puede reescribir, pero se puede sobrecargar.
16. Dos objetos tienen el mismo valor (X.Equals (y) == Verdadero), pero pueden tener diferentes códigos hash. ¿Es esto correcto?
Respuesta: No, si los dos objetos x e y satisfacen x.equals (y) == Verdadero, su código hash debería ser el mismo. Java estipula el método Eqauls y el método hashcode de la siguiente manera: (1) Si dos objetos son los mismos (el método igual devuelve verdadero), entonces sus valores de hashcode deben ser los mismos; (2) Si los hashcodes de los dos objetos son los mismos, no son necesariamente los mismos. Por supuesto, no tiene que hacer lo que se requiere, pero si viola los principios anteriores, encontrará que cuando use contenedores, el mismo objeto puede aparecer en la colección establecida, y la eficiencia de agregar nuevos elementos se reducirá considerablemente (para los sistemas utilizando el almacenamiento de hash, los conflictos frecuentes en los códigos hash causarán una aguda disminución en el rendimiento de acceso).
Suplemento: muchos programas de Java saben sobre iguales y métodos de hashcode, pero muchas personas lo saben. En la obra maestra de Joshua Bloch "Java efectiva" (muchas compañías de software, "Java efectiva", "Java Programming Pensings" y "Refactoring: Mejorar la calidad del código existente" son libros imprescindibles por los programadores de Java. Si no lo ha leído, apúrate y compra uno en Amazon.) Esto es cómo introducir el método iguales: primero de todos, el método de ecuaciones que deben cumplir con los reflexividad (Reflexividad (X. y la simetría (x.equals (y) Devuelve True, y.equals (x) también debe ser que debe devolver verdadero), transitividad (x.equals (y) e y.equals (z) también debe devolver verdadero) y consistencia (cuando la información del objeto referenciada por x e y no se modifica, múltiples llamadas a x.equals (y) deberían obtener el mismo valor de regreso), y para cualquier referencia no anulada de referencia x, x.equals (neco). Los trucos para implementar los métodos iguales de alta calidad incluyen: 1. Use el operador == para verificar "si el parámetro es una referencia a este objeto"; 2. Use la instancia de operador para verificar "si el parámetro es el tipo correcto"; 3. Para los atributos clave en la clase, verifique si los atributos pasados al objeto coinciden; 4. Después de escribir el método igual, pregúntese si satisface la simetría, la transitividad y la consistencia; 5. Siempre reescribe el choque de hash al reescribir iguales; 6. No reemplace el objeto objeto en los parámetros del método igual con otros tipos, y no olvide la anotación @Override al reescribir.
17. ¿Se puede heredar la clase de cadena?
Respuesta: La clase de cadena es una clase final y no se puede heredar.
Suplemento: heredar la cadena es un comportamiento incorrecto en sí mismo. La mejor manera de reutilizar los tipos de cadenas es la asociación (HAS-A) en lugar de la herencia (IS-A).
18. Cuando se pasa un objeto como parámetro a un método, este método puede cambiar las propiedades del objeto y devolver el resultado cambiado. Entonces, ¿es un pase de valor o un pase de referencia aquí?
Respuesta: es transferencia de valor. El lenguaje de programación Java solo pasa parámetros con valores. Cuando una instancia de objeto se pasa a un método como parámetro, el valor del parámetro es una referencia al objeto. Las propiedades de un objeto se pueden cambiar durante el proceso de llamada, pero la referencia al objeto nunca cambiará. En C ++ y C#, el valor de los parámetros aprobados se puede cambiar pasando referencias o transferiendo parámetros.
Suplemento: es realmente inconveniente no aprobar referencias en Java, que no se ha mejorado en Java 8. Es precisamente de esta manera que una gran cantidad de clases de envoltura aparecen en el código escrito en Java (colocando referencias que deben modificarse a través de llamadas de método en una clase de envoltorio, y luego pasar el objeto de envoltorio en un método). Este enfoque solo hará que el código se hinche, especialmente para los desarrolladores que se transforman de C y C ++ a programadores de Java a intolerables.
19. ¿Cuál es la diferencia entre String y StringBuilder y StringBuffer?
Respuesta: La plataforma Java proporciona dos tipos de cadenas: String y StringBuffer/StringBuilder, que puede almacenar y manipular cadenas. Donde la cadena es una cadena de solo lectura, lo que significa que el contenido de la cadena a la que se hace referencia por cadena no se puede cambiar. Los objetos de cadena representados por las clases StringBuffer y StringBuilder se pueden modificar directamente. StringBuilder se introdujo en JDK 1.5. Es exactamente lo mismo que el método de StringBuffer, la diferencia es que se usa en un solo entorno roscado porque todos los aspectos no están modificados por sincronizado, por lo que es un poco más eficiente que StringBuffer.
Suplemento 1: Hay una pregunta de la entrevista: ¿Hay alguna situación en la que usar + para hacer la concatenación de cadenas es mejor que llamar al método Append del objeto StringBuffer/StringBuilder? Si la cadena obtenida después de la conexión ya existe en el área de almacenamiento estático, entonces usar + para la concatenación de cadena es mejor que el método de append de StringBuffer/StringBuilder.
Suplemento 2: La siguiente es también una pregunta de entrevista, pidiendo la salida del programa para ver si puede dar la respuesta correcta.
paquete com.lovo; // ¿Por qué preguntar sobre Hovertree.comPublic Class StringequalTest {public static void main (string [] args) {string a = "programación"; Cadena b = nueva cadena ("Programación"); Cadena c = "programa" + "ming"; System.out.println (a == b); System.out.println (a == c); System.out.println (a.equals (b)); System.out.println (a.equals (c)); System.out.println (a.intern () == B.Intern ()); }}20. La diferencia entre sobrecarga y anulación. ¿Se pueden distinguir los métodos sobrecargados en función del tipo de retorno?
Respuesta: Tanto la sobrecarga de métodos como la reescritura son formas de implementar el polimorfismo. La diferencia es que el primero implementa el polimorfismo en tiempo de compilación, mientras que el segundo implementa el polimorfismo en tiempo de ejecución. La sobrecarga ocurre en una clase. Si un método con el mismo nombre tiene una lista de parámetros diferente (diferentes tipos de parámetros, un número diferente de parámetros, o ambos), se considera una sobrecarga; La reescritura ocurre entre la subclase y la clase principal. La reescritura requiere que el método reescrito de la subclase y la clase principal tengan el mismo tipo de retorno que el método reescrito de la clase principal, que es un mejor acceso que el método reescrito de la clase principal, y no puede declarar más excepciones que el método reescrito de la clase principal (principios de sustitución de Rischer). La sobrecarga no tiene requisitos especiales para los tipos de devolución.
Suplemento: Huawei una vez hizo una pregunta en la pregunta de la entrevista: ¿Por qué no puede distinguir la sobrecarga en función del tipo de retorno y decir su respuesta?
21. Describe el principio y el mecanismo de los archivos de clase de carga JVM?
Respuesta: La carga de clases en el JVM es implementada por un cargador de clase (cargador de clases) y sus subclases. El cargador de clase en Java es un componente importante del sistema de tiempo de ejecución de Java, que es responsable de encontrar y cargar clases en archivos de clase en tiempo de ejecución.
Reponer:
1. Debido a la naturaleza multiplataforma de Java, el programa de origen de Java compilado no es un programa ejecutable, sino uno o más archivos de clase. Cuando un programa Java necesita usar una clase, el JVM asegura que la clase haya sido cargada, conectada (verificada, preparada y analizada) e inicializada. La carga de clase se refiere a la lectura de datos del archivo de clase. Class en la memoria. Por lo general, crear una matriz de bytes para leerlo en el archivo .class, y luego generar un objeto de clase correspondiente a la clase cargada. Después de completar la carga, el objeto de clase todavía está incompleto, por lo que la clase no está disponible en este momento. Cuando se carga la clase, ingresa a la etapa de conexión. Esta etapa incluye tres pasos: verificación, preparación (asignación de memoria para variables estáticas y configuración del valor inicial predeterminado) y análisis (reemplazar las referencias de símbolos con referencias directas). Finalmente, el JVM inicializa la clase, incluyendo: 1. Si la clase tiene una clase principal directa y la clase no se ha inicializado, entonces la clase principal se inicializará primero; 2. Si hay declaraciones de inicialización en la clase, estas declaraciones de inicialización se ejecutarán a su vez.
2. La carga de clase se realiza mediante el cargador de clase, que incluye: cargador de raíz (bootstrap), cargador de extensión (extensión), cargador del sistema (sistema) y cargador de clase definido por el usuario (subclase de java.lang.classloader). A partir de JDK 1.2, el proceso de carga de clase adopta el mecanismo de delegación del padre (PDM). PDM mejor garantiza la seguridad de la plataforma Java. En este mecanismo, la propia bootstrap de la JVM es el cargador de raíz, y otros cargadores tienen y solo tienen un cargador de clase padre. La carga de la clase primero solicita al cargador de clase principal que cargue, y el cargador de clase principal solo será cargado por su cargador de subclase cuando sea impotente. El JVM no proporciona referencias a Bootstrap a los programas Java. Aquí hay algunas instrucciones para varios cargadores de clase:
a) Bootstrap: generalmente se implementa utilizando el código local y es responsable de cargar la biblioteca de clase básica básica de JVM (RT.jar);
b) Extensión: Cargue la biblioteca de clases desde el directorio especificado por la propiedad del sistema java.ext.dirs, y su cargador principal es bootstrap;
c) Sistema: también conocido como cargador de clase de aplicación, su clase principal es la extensión. Es el cargador de clase más utilizado. Registra clases desde el directorio especificado por la variable de entorno classpath o el atributo del sistema java.class.path, y es el cargador principal predeterminado del cargador definido por el usuario.
22. ¿Se puede almacenar un personaje chino en una variable tipo Char? ¿Por qué?
Respuesta: El tipo de char puede almacenar un carácter chino, porque la codificación utilizada en Java es unicode (no se selecciona una codificación específica y los caracteres se usan directamente en el número de conjunto de caracteres, que es el único método unificado). Un tipo de char toma 2 bytes (16 bits), por lo que no es un problema poner un chino.
Suplemento: el uso de Unicode significa que los personajes tienen diferentes manifestaciones dentro y fuera del JVM, y ambos son unicode dentro del JVM. Cuando este personaje se transfiere del JVM al exterior (por ejemplo, almacenado en el sistema de archivos), se requiere la conversión de codificación. Por lo tanto, Java tiene secuencias de bytes y transmisiones de caracteres, así como transmisiones de conversión que se convierten entre transmisiones de caracteres y secuencias de bytes, como InputStreamReader y OuttreStreamReader. Estas dos clases son clases de adaptadores entre las transmisiones de bytes y las transmisiones de caracteres, y realizan la tarea de codificar la conversión; Para los programadores C, para completar dicha conversión de codificación, probablemente confían en las características de la memoria compartida de Union (Union/Community) para lograr.
23. ¿Cuáles son las similitudes y diferencias entre la clase abstracta y la interfaz?
Respuesta: Las clases e interfaces abstractas no pueden ser instanciadas, pero se pueden definir referencias a clases abstractas y tipos de interfaz. Si una clase hereda una clase abstracta o implementa una interfaz, necesita implementar todos los métodos abstractos en ella, de lo contrario, la clase aún debe declararse como una clase abstracta. Las interfaces son más abstractas que las clases abstractas, porque los constructores se pueden definir en clases abstractas, y puede haber métodos abstractos y métodos concretos, mientras que los constructores no pueden definirse en interfaces, y todos los métodos en ellos son métodos abstractos. Los miembros en clases abstractas pueden ser privados, predeterminados, protegidos y públicos, mientras que los miembros en las interfaces son todos públicos. Las variables de los miembros se pueden definir en clases abstractas, mientras que las variables miembros definidas en las interfaces son en realidad constantes. Las clases con métodos abstractos deben declararse como clases abstractas, y las clases abstractas no necesariamente tienen métodos abstractos.
24. ¿Cuál es la diferencia entre las clases anidadas estáticas y las clases internas (clase interna)?
Respuesta: La clase anidada estática es una clase interna declarada como estática, que puede instanciarse sin depender de instancias de clase externas. Las clases internas habituales deben ser instanciadas después de instanciar la clase externa, y la sintaxis se ve bastante extraña, como se muestra a continuación.
paquete com.lovo; / ** * Clase de póker (un mazo de póker) ¿Por qué preguntar sobre Hovertree.com * */ Public Class Poker {private static string [] suites = {"Spade", "Rose", "Grass Flower", "Cube"}; Private static int [] face = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; tarjetas de tarjeta privada []; / *** constructor**/ public poker () {tarjetas = nueva tarjeta [52]; for (int i = 0; i <suites.length; i ++) {for (int j = 0; j <faceS.length; j ++) {tarjetas [i * 13+j] = nueva tarjeta (suites [i], face [j]); }}} / ** * shuffle (aleatorio fuera de orden) * * / public void shuffle () {for (int i = 0, len = cards.length; i <len; i ++) {int index = (int) (math.random () * len); Tarjeta temp = tarjetas [índice]; tarjetas [índice] = tarjetas [i]; Tarjetas [i] = temp; }} / *** Deal de tarjeta* @param index la posición de la oferta** / oferta de tarjeta pública (int index) {tarjetas de retorno [índice]; } / ** * clase de tarjeta (una pieza de póker) * [clase interna] * @author luo hao * * / public class Card {private String Suite; // se adapta a la cara privada int; // Tarjeta pública de puntos (String Suite, int Face) {this.suite = suite; this.face = face; } @Override public string toString () {String facestr = ""; switch (cara) {caso 1: facestr = "a"; romper; Caso 11: facestr = "j"; romper; Caso 12: facestr = "Q"; romper; Caso 13: facestr = "k"; romper; predeterminado: facestr = string.ValueOf (cara); } suite de retorno + facestr; }}} Clase de prueba:
paquete com.lovo; clase PokerTest {public static void main (string [] args) {poker poker = new Poker (); poker.shuffle (); // shuffle poker.card c1 = poker.deal (0); // Sirve la primera tarjeta // para tarjetas de clase interna no estatales // El objeto de tarjeta puede crearse solo a través de su clase de clase externa de póker poker.card c2 = poker.new tarjeta ("corazón rojo", 1); // crear una tarjeta usted mismo System.out.println (C1); // el primer sistema.out.println (C2); // Imprimir: Red Heart A}} // ¿Por qué preguntar sobre Hovertree.com25. ¿Habrá una filtración de memoria en Java? Descríbalo brevemente.
Respuesta: En teoría, Java no tendrá fugas de memoria porque tiene un mecanismo de recolección de basura (GC) (esta también es una razón importante por la cual Java se usa ampliamente en la programación del lado del servidor); Sin embargo, en el desarrollo real, puede haber objetos inútiles pero accesibles, y estos objetos no pueden ser reciclados por GC y se producirán fugas de memoria. Un ejemplo es que los objetos en la sesión de Hibernate (caché de nivel uno) son persistentes, y el recolector de basura no reciclará estos objetos, pero puede haber objetos de basura inútiles en estos objetos. El siguiente ejemplo también muestra la fuga de memoria en Java:
paquete com.lovo; // ¿Por qué preguntar sobre Hovertree.comimport java.util.arrays; import java.util.emptystackexception; clase pública mystack <t> {private t [] elementos; Tamaño privado int = 0; Private static final int init_capacity = 16; public mystack () {Elements = (t []) nuevo objeto [init_capacity]; } public void push (t elem) {EnsureCapacity (); elementos [size ++] = elem; } public t pop () {if (size == 0) tirar nueva vacíaStackException (); Elementos de retorno [-tamaño]; } private void ensureCapacity() { if(elements.length == size) { elements = Arrays.copyOf(elements, 2 * size + 1); }}}上面的代码实现了一个栈(先进后出(FILO))结构,乍看之下似乎没有什么明显的问题,它甚至可以通过你编写的各种单元测试。然而其中的pop方法却存在内存泄露的问题,当我们用pop方法弹出栈中的对象时,该对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,因为栈内部维护着对这些对象的过期引用(obsolete reference)。在支持垃圾回收的语言中,内存泄露是很隐蔽的,这种内存泄露其实就是无意识的对象保持。如果一个对象引用被无意识的保留起来了,那么垃圾回收器不会处理这个对象,也不会处理该对象引用的其他对象,即使这样的对象只有少数几个,也可能会导致很多的对象被排除在垃圾回收之外,从而对性能造成重大影响,极端情况下会引发Disk Paging(物理内存与硬盘的虚拟内存交换数据),甚至造成OutOfMemoryError。
26、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?
答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。
27、静态变量和实例变量的区别?
答:静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。在Java开发中,上下文类和工具类中通常会有大量的静态成员。
28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
答:不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,因此在调用静态方法时可能对象并没有被初始化。
29、如何实现对象克隆?
答:有两种方式:
1.实现Cloneable接口并重写Object类中的clone()方法;
2.实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下。
package com.lovo; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class MyUtil { private MyUtil() { throw new AssertionError(); } public static <T> T clone(T obj) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bout); oos.writeObject(obj); ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bin); return (T) ois.readObject(); // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源} } //何问起hovertree.com下面是测试代码:
package com.lovo; import java.io.Serializable; /** * Human* @author Luo Hao* */ class Person implements Serializable { private static final long serialVersionUID = -9102017020286042305L; private String name; // Name private int age; // Age private Car car; // Car public Person(String name, int age, Car car) { this.name = name; this.age = edad; this.car = car; } public String getName () {nombre de retorno; } public void setName (nombre de cadena) {this.name = name; } public int getAge () {return Age; } public void setAge(int age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", car=" + car + "]"; } } /** * Car class* @author Luo Hao* */ class Car implements Serializable { private static final long serialVersionUID = -5713945027627603702L; private String brand; // Brand private int maxSpeed; // Top speed public Car(String brand, int maxSpeed) { this.brand = brand; this.maxSpeed = maxSpeed; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } @Override public String toString() { return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]"; } } //Why ask about hovertree.comclass CloneTest { public static void main(String[] args) { try { Person p1 = new Person("Hao LUO", 33, new Car("Benz", 300)); Person p2 = MyUtil.clone(p1); // Deep cloning p2.getCar().setBrand("BYD"); // Modify the brand attributes of the cloned Person object p2-associated car object// The original Person object p1-associated car will not be affected in any way// Because when cloning Person object, the car object associated with it is also cloned System.out.println(p1); } catch (Exception e) {E.PrintStackTrace (); }}}注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。
30、GC 是什么?为什么要有GC?
答: GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。
补充:垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:
伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。
与垃圾回收相关的JVM参数:
-Xms / -Xmx --- 堆的初始大小/ 堆的最大大小
-Xmn --- 堆中年轻代的大小
-XX:-DisableExplicitGC --- 让System.gc()不产生任何作用
-XX:+PrintGCDetail --- 打印GC的细节
-XX:+PrintGCDateStamps --- 打印GC操作的时间戳
31、String s=new String(“xyz”);创建了几个字符串对象?
答:两个对象,一个是静态存储区的"xyz",一个是用new创建在堆上的对象。
32、接口是否可继承(extends)接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)?
答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承具体类,但前提是具体类必须有明确的构造函数。
33、一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。
34、Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?
答:可以继承其他类或实现其他接口,在Swing编程中常用此方式来实现事件监听和回调。
35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?
答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
36、Java 中的final关键字有哪些用法?
答: (1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。
37、指出下面程序的运行结果:
class A{ static{ System.out.print("1"); } public A(){ System.out.print("2"); } } class B extends A{ static{ System.out.print("a"); } public B(){ System.out.print("b"); } } //Why ask about hovertree.compublic class Hello{ public static void main(String[] args){ A ab = new B(); ab = new B(); }}答:执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。
38、数据类型之间的转换:
1)如何将字符串转换为基本数据类型?
2)如何将基本数据类型转换为字符串?
respuesta:
1)调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;
2)一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf(…)方法返回相应字符串
39、如何实现字符串的反转及替换?
答:方法很多,可以自己写实现也可以使用String或StringBuffer / StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:
public static String reverse(String originStr) { if(originStr == null || originStr.length() <= 1) return originStr; return reverse(originStr.substring(1)) + originStr.charAt(0); } //何问起hovertree.com40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?
答:代码如下所示:
String s1 = "你好";String s2 = newString(s1.getBytes("GB2312"), "ISO-8859-1");41、日期和时间:
1)如何取得年月日、小时分钟秒?
2)如何取得从1970年1月1日0时0分0秒到现在的毫秒数?
3)如何取得某月的最后一天?
4)如何格式化日期?
答:操作方法如下所示:
1)创建java.util.Calendar 实例,调用其get()方法传入不同的参数即可获得参数所对应的值
2)以下方法均可获得该毫秒数:
Calendar.getInstance().getTimeInMillis(); System.currentTimeMillis(); //何问起hovertree.com
3)示例代码如下:
Calendar time = Calendar.getInstance(); time.getActualMaximum(Calendar.DAY_OF_MONTH); //何问起hovertree.com
4)利用java.text.DataFormat 的子类(如SimpleDateFormat类)中的format(Date)方法可将日期格式化。
42、打印昨天的当前时刻。
respuesta:
public class YesterdayCurrent { public static void main(String[] args){ Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -1); System.out.println(cal.getTime()); } } //何问起hovertree.com43、比较一下Java 和JavaSciprt。
答: JavaScript 与Java是两个公司开发的不同的两个产品。Java 是原Sun 公司推出的面向对象的程序设计语言,特别适合于互联网应用程序开发;而JavaScript是Netscape公司的产品,为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言,它的前身是LiveScript;而Java 的前身是Oak语言。
下面对两种语言间的异同作如下比较:
1)基于对象和面向对象:Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言。因而它本身提供了非常丰富的内部对象供设计人员使用;
2)解释和编译:Java 的源代码在执行之前,必须经过编译;JavaScript 是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行;
3)强类型变量和类型弱变量:Java采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript中变量声明,采用其弱类型。即变量在使用前不需作声明,而是解释器在运行时检查其数据类型;
4)代码格式不一样。
补充:上面列出的四点是原来所谓的标准答案中给出的。其实Java和JavaScript最重要的区别是一个是静态语言,一个是动态语言。目前的编程语言的发展趋势是函数式语言和动态语言。在Java中类(class)是一等公民,而JavaScript中函数(function)是一等公民。对于这种问题,在面试时还是用自己的语言回答会更加靠谱。
44、什么时候用assert?
答: assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后, assertion检查通常是关闭的。在实现中,断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式计算为false,那么系统会报告一个AssertionError。
断言用于调试目的:
assert(a > 0); // throws an AssertionError if a <= 0
断言可以有两种形式:
assert Expression1;
assert Expression1 : Expression2 ;
Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的字符串消息。
断言在默认情况下是禁用的,要在编译时启用断言,需使用source 1.4 标记:
javac -source 1.4 Test.java
要在运行时启用断言,可使用-enableassertions 或者-ea 标记。
要在运行时选择禁用断言,可使用-da 或者-disableassertions 标记。
要在系统类中启用断言,可使用-esa 或者-dsa 标记。还可以在包的基础上启用或者禁用断言。可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。
45、Error 和Exception 有什么区别?
答: Error 表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;Exception 表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。
Supplement: During the interview with Motorola in 2005, I asked a question like "If a process reports a stack overflow run-time error, what's the most possible cause?", giving four options a. lack of memory; b. write on an invalid memory space; do. recursive function calling; d. array index out of boundary. Java programs may also encounter StackOverflowError when running. This is an error that cannot be recovered, so I can only re-modify the code. The answer to this interview question is c. If you write recursion that cannot converge quickly, it is very likely to cause a stack overflow error, as shown below:
package com.lovo; public class StackOverflowErrorTest { public static void main(String[] args) { main(null); } } //何问起hovertree.com因此,用递归编写程序时一定要牢记两点:1. 递归公式;2. 收敛条件(什么时候就不再递归而是回溯了)。
46、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?
答:会执行,在方法返回调用者前执行。Java允许在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,这会对程序造成很大的困扰,C#中就从语法上规定不能做这样的事。
47、Java 语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?
答: Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java 的异常处理是通过5 个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throw)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理;try用来指定一块预防所有“异常”的程序;catch 子句紧跟在try块后面,用来指定你想要捕捉的“异常”的类型;throw 语句用来明确地抛出一个“异常”;throws用来标明一个成员函数可能抛出的各种“异常”;finally 为确保一段代码不管发生什么“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try 语句,“异常”的框架就放到栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种“异常”进行处理,栈就会展开,直到遇到有处理这种“异常”的try 语句。
48、运行时异常与受检异常有何异同?
答:异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。异常和继承一样,是面向对象程序设计中经常被滥用的东西,神作《Effective Java》中对异常的使用给出了以下指导原则:
不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常)
对可以恢复的情况使用受检异常,对编程错误使用运行时异常避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生)
优先使用标准的异常每个方法抛出的异常都要有文档保持异常的原子性不要在catch中忽略掉捕获到的异常
49、列出一些你常见的运行时异常?
respuesta:
ArithmeticException(算术异常)
ClassCastException (类转换异常)
IllegalArgumentException (非法参数异常)
IndexOutOfBoundsException (下表越界异常)
NullPointerException (空指针异常)
SecurityException (安全异常)
50、final, finally, finalize 的区别?
答: final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final 的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final 的方法也同样只能使用,不能在子类中被重写。finally:通常放在try…catch的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。finalize:Object类中定义的方法,Java中允许使用finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize() 方法可以整理系统资源或者执行其他清理工作。
Lo anterior es todo el contenido de este artículo. I hope it will be helpful to everyone in the Java interview, and I hope everyone will support Wulin.com more.