Created
June 30, 2010 16:11
-
-
Save icoloma/458876 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.junit.Assert.assertEquals; | |
import static org.junit.Assert.assertFalse; | |
import static org.junit.Assert.assertTrue; | |
import java.math.BigDecimal; | |
import java.math.RoundingMode; | |
import java.util.HashSet; | |
import java.util.Set; | |
import org.junit.Test; | |
/** | |
* Respuestas al Quiz Java del 15 de Junio. | |
* http://www.javahispano.org/contenidos/es/dos_plazas_gratis_para_el_javaspecialist_master_course_en_madrid/ | |
* @author icoloma | |
*/ | |
public class QuizTest { | |
/* | |
# Pregunta 1 | |
Dado el siguiente fragmento de código | |
public static void main(String... args) { | |
BigDecimal b = new BigDecimal("1.3333333333"); | |
b.setScale(2, RoundingMode.DOWN); | |
System.out.println(b); | |
} | |
¿Qué salida obtendremos en la consola? | |
* Ninguna, se producirá una IllegalArgumentException porque BigDecimal no permite la redución de escala | |
* Imprimirá 1.33 siempre Imprimirá 1,33 si el sistema operativo está configurado en Español | |
* Imprimirá 1.3333333333 porque falta un b= | |
* Imprimirá 1.3333333333 porque System.out.println() imprime la representación interna de BigDecimal | |
*/ | |
/** | |
* Respuesta: | |
* Imprimirá 1.3333333333 porque falta un b= | |
* | |
* Explicación: | |
* BigDecimal.scale indica el número de decimales a mostrar, pero BigDecimal es immutable. | |
* setScale() no hace nada sobre la instancia sino que devuelve una nueva instancia con | |
* el scale aplicado. | |
*/ | |
@Test | |
public void test1() { | |
// versión incorrecta | |
BigDecimal b = new BigDecimal("1.3333333333"); | |
b.setScale(2, RoundingMode.DOWN); | |
assertEquals("1.3333333333", b.toString()); | |
// versión correcta | |
b = b.setScale(2, RoundingMode.DOWN); | |
assertEquals("1.33", b.toString()); | |
} | |
/* | |
# Pregunta 2 | |
Dado el siguiente fragmento de código | |
public static void main(String... args) { | |
String a = new StringBuilder("a").append("a").toString(); | |
String b = a.intern(); | |
String c = "aa"; | |
} | |
¿Cuál de las siguientes expresiones es true? | |
* a == b && b == c | |
* a == c && a == b | |
* b == c && a != b | |
* a != b && b != c | |
* Ninguna, debería utilizarse equals() | |
*/ | |
/** | |
* Respuesta: | |
* b == c && a != b | |
* | |
* Explicación: | |
* En Java cualquier repetición de instancias de String referenciadas desde código | |
* usan la misma instancia, en este caso "aa". Esto se hace empleando internamente un | |
* pool de Strings, al que se pueden añadir cadenas invocando intern(). | |
*/ | |
@Test | |
public void test2() { | |
String a = new StringBuilder("a").append("a").toString(); | |
String b = a.intern(); | |
String c = "aa"; | |
// la misma cadena se reutiliza en Java | |
assertTrue(c == "aa"); | |
assertTrue(b == "aa"); | |
assertFalse(a == "aa"); | |
// las respuestas del test | |
assertFalse(a == b && b == c); | |
assertFalse(a == c && a == b); | |
assertTrue(b == c && a != b); | |
assertFalse(a != b && b != c); | |
} | |
/* | |
#Pregunta 3 | |
Dada la siguiente clase | |
public class A { | |
private int id; | |
private String name; | |
@Override | |
public int hashCode() { | |
return id + name.hashCode(); | |
} | |
@Override | |
public boolean equals(Object other) { | |
if (other == null || !(other instanceof A)) { | |
return false; | |
} | |
A a = (A) other; | |
return a.id == this.id && (this.name == null ? a.name == null : this.name.equals(a.name)); | |
} | |
public int getId() { | |
return id; | |
} | |
public void setId(int id) { | |
this.id = id; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
} | |
Si se crean varias instancias de A y se almacenan en un Set<A>, ¿en qué casos se puede garantizar que el Set no contiene instancias repetidas? | |
* Sólo si los valores de id y name no cambian, dada la implementación de equals() y hashCode() | |
* Sólo si la instancia es la misma, porque Set utiliza internamente el comparador == | |
* No se puede garantizar que no haya instancias repetidas, por la implementación de A | |
* No se puede garantizar que no haya instancias repetidas, porque A debería implementar Comparable | |
*/ | |
/** | |
* Respuesta: | |
* No se puede garantizar con esta implementación de A. | |
* (UPDATE: por errata en esta pregunta, se acepta igualmente la respuesta | |
* "Sólo si los valores de id y name no cambian" como válida) | |
* | |
* Explicación: | |
* hashCode() y equals() deben ser inmutables, está definido en el javadoc de ambos | |
* métodos. En este caso ambas implementaciones dependen de dos valores que no se | |
* garantiza que sean inmutables (id típicamente lo es, pero name no). En un Set | |
* esto tiene la consecuencia de que no se puede localizar una instancia si su hashcode | |
* cambia una vez ha sido introducido en el Set. | |
* | |
* Set hace uso de equals y hashCode. El único uso que hace de la comparación por | |
* igualdad (==) se debe a que es la implementación por defecto de equals. | |
* | |
* Comparable es un requisito de SortedSet, pero no de Set. | |
*/ | |
@Test | |
public void test3() { | |
class A { | |
private int id; | |
private String name; | |
@Override | |
public int hashCode() { | |
return id + name.hashCode(); | |
} | |
@Override | |
public boolean equals(Object other) { | |
if (other == null || !(other instanceof A)) { | |
return false; | |
} | |
A a = (A) other; | |
return a.id == this.id && (this.name == null? a.name == null : this.name.equals(a.name)); | |
} | |
public int getId() { | |
return id; | |
} | |
public void setId(int id) { | |
this.id = id; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
} | |
A a = new A(); | |
a.setId(1); | |
a.setName("foo"); | |
Set<A> set = new HashSet<A>(); | |
set.add(a); | |
assertTrue(set.contains(a)); | |
a.setName("bar"); | |
assertFalse(set.contains(a)); | |
} | |
/* | |
#Pregunta 4 | |
Dado el siguiente fragmento de código | |
public static void main(String... args) { | |
System.out.println(new StringBuffer('H').append("ello ").append("World").toString()); | |
System.out.println('H' + "ello " + "World"); | |
System.out.println("Hello World"); | |
} | |
¿Qué afirmación es cierta? | |
* La primera expresión es menos eficiente que la segunda, dado que la segunda utiliza internamente StringBuilder | |
* Las tres expresiones producen la misma salida por consola | |
* La segunda y la tercera expresión tienen el mismo rendimiento | |
*/ | |
/** | |
* Respuesta: | |
* La segunda y la tercera expresión tienen el mismo rendimiento. | |
* | |
* Explicación: | |
* La primera línea no es correcta. new StringBuffer('H') equivale a hacer | |
* new StringBuffer(12), dado que el caracter es interpretado como un entero en este contexto. | |
* Normalmente la concatenación de cadenas de caracteres se realiza en Java usando | |
* un StringBuilder de manera interna, aunque cuando es posible se resuelve en tiempo | |
* de compilación. Es decir, 'H' + "ello " + "World" es equivalente a escribir "Hello World" | |
* en una sola cadena. Optimizaciones similares se hacen con cálculos como 2 * 24 * 60 * 60L. | |
*/ | |
@Test | |
public void test4() { | |
assertEquals("ello World", new StringBuffer('H').append("ello ").append("World").toString()); | |
// bytecode producido: | |
// 28 getstatic java.lang.System.out : java.io.PrintStream [78] | |
// 31 ldc <String "Hello World"> [102] | |
// 33 invokevirtual java.io.PrintStream.println(java.lang.String) : void [97] | |
System.out.println('H' + "ello " + "World"); | |
// bytecode producido: | |
// 36 getstatic java.lang.System.out : java.io.PrintStream [78] | |
// 39 ldc <String "Hello World"> [102] | |
// 41 invokevirtual java.io.PrintStream.println(java.lang.String) : void [97] | |
System.out.println("Hello World"); | |
// curiosidad adicional: hace uso del pool de Strings del test 2 | |
assertTrue('H' + "ello " + "World" == "Hello World"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment