Skip to content

Instantly share code, notes, and snippets.

@icoloma
Created June 30, 2010 16:11
Show Gist options
  • Save icoloma/458876 to your computer and use it in GitHub Desktop.
Save icoloma/458876 to your computer and use it in GitHub Desktop.
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