propósito
- Colección especial de algunos temas interesantes.
- Estas preguntas serán fáciles de leer y erróneas.
- Actualización continua, cada diez preguntas como un artículo
Tabla de contenido
- 1. Sobre el operador ternario
- 2. Acerca de la final efectiva
- 3. Acerca del estancamiento por inanición
- 4. Intercambia los valores de a y b
- 5. Ataque de sincronización
- 6. Cual es mi atributo
- 7. Calcule el valor de 1 + 2 +… + n
Serie de artículos
- Interview Companion Part 1: Humble Java Basics / Trap Questions, puede leerlo de inmediato y corregirlo
- Interview Companion 2: preguntas interesantes de la entrevista lógica BAT para compartir
[1] Acerca del operador ternario
- ¿Cuál debería ser la salida del siguiente resultado de operación?
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = null;
Integer d = a > b ? a + b : c;
System.out.println(d);
}
- Que esperas:
null
- Realmente:
Exception in thread "main" java.lang.NullPointerException
at DesignPattern.single.dfghj.main(dfghj.java:16)
Process finished with exit code 1
-
la razón
- La línea 16 del error es esta oración: Entero d = a> b? A + b: c;
- En primer lugar, lo dejamos claro: el operador condicional es asociativo por la derecha, es decir, agrupa los cálculos de derecha a izquierda. Por ejemplo, a? B: c? D: e se ejecutará como a? B: (c? D: e).
- Cuando se convierten el tipo básico y el tipo de empaquetado, hay un proceso de empaquetado y desempaquetado automático, que llamará a .xxxxValue (), como .booleanValue (), .intValue (), .StringValue ().
- El ":" del operador ternario se mantendrá automáticamente igual en los lados izquierdo y derecho. Si los tipos son inconsistentes, se producirá el proceso de desembalaje.
- Si los tipos en los dos lados son inconsistentes, como en el título: el lado izquierdo se calcula como int3 en lugar de Integer3, y el lado derecho también se descomprimirá, entonces el propio nulo se suspenderá nuevamente usando .xxxxValue (), y ocurrirá NPE.
-
Solución: mantenga ambos lados de ":" consistentes,
- O modificar a + b: Integer d = a> b? Integer.valueOf (a + b): c;
- O modificar c: Entero d = a> b? A + b: nulo;
-
Blog de referencia: problema de puntero nulo del operador ternario
【2】 Acerca de la final efectiva
- ¿Cuál debería ser la salida del siguiente resultado de operación?
public class ljtest{
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread name:" + Thread.currentThread().getName() + ",i:" + i);
}
});
}
}
}
- Que esperas:
thread name:Thread-0,i:0
thread name:Thread-1,i:1
thread name:Thread-2,i:2
thread name:Thread-4,i:4
thread name:Thread-6,i:6
thread name:Thread-8,i:8
thread name:Thread-9,i:9
thread name:Thread-3,i:3
thread name:Thread-5,i:5
thread name:Thread-7,i:7
- Realmente:
编译期都过不了,会在输出语句哪一行的 i 哪里显示红线。
- Análisis de causa
- Porque cuando la clase interna accede a la variable miembro de la clase externa, la variable no se puede cambiar, debe ser estable, final o final efectiva.
- Final significa inmutable, y final efectivo significa casi equivalente a inmutable Si una variable no ha sido asignada varias veces (dos veces) antes de ser utilizada, entonces por defecto es formalmente invariable.
- Solución
- Cambie la variable i a final, o final efectiva, por ejemplo, agregue una oración debajo del ciclo for: int temp = i; (tenga en cuenta que i en la declaración de salida también debe cambiarse a temp)
- Ahora agregue int temp = i;, ¿el resultado será el que espera?
- No, porque el hilo no se inicia en absoluto.
- Solución:
- Método 1: en el bucle for, agregue t.start (); después de cada hilo
- Método 2: Entréguelo al grupo de subprocesos para que lo administre, no es necesario agregar t.start ();
[3] Acerca del estancamiento del hambre
- ¿Cuál debería ser la salida del siguiente resultado de operación?
public class ljtest{
private static ExecutorService executorService = Executors.newSingleThreadExecutor();
static class t1 implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("i am t1");
return "t1===";
}
}
static class t2 implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("i am t2");
Future<String> submit = executorService.submit(new t1());
return "t2===" + submit.get();
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
t2 t = new t2();
Future<String> submit = executorService.submit(t);
System.out.println(submit.get());
System.out.println("la~la~la~");
executorService.shutdown();
}
}
- Que esperas:
i am t2
i am t1
t2===t1===
la~la~la~
- En realidad: solo esto
i am t2
- Análisis de causa
- El grupo de subprocesos que usamos es Executors.newSingleThreadExecutor (); es un grupo de subprocesos con solo un subproceso.
- Cuando ponemos t2 para ejecución, t2 pone t1 de nuevo. En este momento, t1 está esperando el final de t2, y t2 está esperando el valor de retorno de t1, y hay hambre esperando.
[4] Intercambia los valores de a y b
- Cómo intercambiar los valores de ayb sin usar otras variables
常规写法:
public static void main(String[] args) {
int a = 5;
int b = 6;
a = a + b;
b = a - b;
a = a - b;
System.out.println("a:" + a + "b:" + b);
}
异或写法
public static void main(String[] args) {
int a = 8;
int b = 8;
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("new--->" + "a:" + a + ",b:" + b);
}
- En respuesta a un blog que señaló que la escritura convencional tiene problemas de desbordamiento de memoria, teóricamente los hay, pero se puede optimizar después de jdk1.8, y no hay desbordamiento en el pro-test.
- Algunos blogs señalaron que el método de escritura XOR tiene un error en el XOR de dos números idénticos, pero no hay un pro-test.
- El método de escritura XOR puede ser relativo al método de escritura convencional, lo que reducirá el número de cálculos.
[5] Ataque de tiempo
- Escribe un código que juzgue la igualdad de cadenas.
常规写法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
- El párrafo anterior se selecciona del método de igualdad de JDK, juzgue primero aproximadamente
- Si la dirección de referencia es la misma
- ¿Es el tipo de cadena?
- Es la longitud consistente
- Compare si cada personaje es el mismo uno por uno
- Está bien escribirlo así, pero no es perfecto. Esto causará problemas de seguridad y expondrá una vulnerabilidad llamada ataque de tiempo (por favor, use el ataque de tiempo de Baidu).
- De acuerdo con el siguiente método de escritura, se sacrificará la eficiencia para evitar ataques de tiempo.
防计时攻击写法
public boolean equals(String s1, String s2) {
if (s1 == null || s2 == null) {
return false;
}
if (s1 == s2) {
return true;
}
if (s1.length() != s2.length()) {
return false;
}
int res = 0;
for (int i = 0; i < s1.length(); i++) {
res |= s1.charAt(i) ^ s2.charAt(i);
}
return res == 0;
}
[6] Cuál es mi atributo
- ¿Cuál debería ser la salida del siguiente resultado de operación?
public class ljtest {
public final int value = 4;//5.注释掉本行
public void dop(){
int value = 6;//4.注释掉本行
Runnable r = new Runnable() {
public final int value = 9;//3.注释掉本行
@Override
public void run() {
int value = 10;//2.注释掉本行
System.out.println(this.value);//1.去掉this
}
};
r.run();
}
public static void main(String[] args) {
ljtest f = new ljtest();
f.dop();
}
}
- Salida
9
-
Mire los comentarios del código y considere los siguientes escenarios: ¿Cuáles son los resultados?
- // 1. Eliminar esto
- // 2. Comenta esta línea
- // 3. Comenta esta línea
- // 4. Comenta esta línea
- // 5. Comenta esta línea
-
Resultado de salida
- 1. Salida: 10
- 2. Resultado: 9
- 3. Salida: 6
- 4. Resultado: 4
- 5. Salida: error de compilación
-
En conclusión:
- Distinguir los atributos y valores de las clases internas.
[7] Calcule el valor de 1 + 2 +… + n
- Descripción del título: Seek 1 + 2 + 3 +… + n, y se requiere que las palabras clave y las sentencias de juicio condicional como multiplicación y división, for, while, if, else, switch, case no se pueden usar (A? B: C).
- Ideas y código para la resolución de problemas:
public class Solution {
private static int[] res = {
0};
public int Sum_Solution(int n) {
/* 1、循环的写法
int sum = 0;
for(int i = 1;i <= n; i++){
sum += i;
}
return sum; */
/* 2、数学规律
return (1 + n) * n / 2; */
/* 3、递归
return n == 0 ? 0 : n + Sum_Solution(n-1); */
// 4、递归-满足题意
try{
return res[n];
}catch(Exception e) {
return n + Sum_Solution(n-1);
}
}
}