![]() |
Una broma de diciembre de 2012, cuando se decía que el calendario maya predecía el fin del mundo. El programa comprueba la fecha sin parar y lanza una excepción en el momento señalado. Como se ve, la excepción nunca llegó.
Evita los problemas de instalación
Nunca instales una versión nueva de Eclipse sobre una versión antigua. Renombra la instalación antigua para quitarla del camino y descomprime la versión nueva en un directorio limpio.
Recupera tu workspace dañado
Un workspace dañado es una causa común de problemas entre muchos desarrolladores. Si tu instalación de
eclipse comienza a tener errores o un comportamiento inestable, puede que sea tiempo de darle un nuevo comienzo. Ejecuta
eclipse con la opción -clean y todo los datos en cache y de ejecución serán eliminados. Esto a menudo ayuda a resolver algunos problemas con plug-ins y mejora la estabilidad en general.
Incrementa el espacio de memoria
Cuando se agregan nuevos plugins al nucleo de funcionalidad de
eclipse o cuando se necesita usar plug-ins de terceros, los requerimientos de memoria de eclipse se incrementan. La memoria default configurada para eclipse deja de ser suficiente para muchos proyectos de tipo empresarial y eso causa una respuesta lenta por parte del IDE. Si comienzas a tener errores de falta de memoria o respuesta lenta, quizá debas incrementar los valores por default establecidos en el archivo eclipse.ini en el directorio de instalación. En particular, si llegas a tener un error del tipo «PermGem» (permanent generation), debes incluir esta línea al final del archivo y reiniciar eclipse
XX:MaxPermSize=256m
Usa la menor cantidad de memoria menor que puedas pero que sea suficiente para ejecutar bien tus proyectos.
Edicion Side by side
Puedes editar un mismo archivo desde dos puntos diferentes usando el comando Window>New Editor. Es mas cómodo y mejora la productividad.
Deja que mejore tu código automáticamente
Configura Eclipse para que formatee el código automáticamente y organice los «imports» cada vez que salvas. Usa la opción en Window>Preferences>Java Editor>Save Actions para habilirtar estas opciones. Esta ventana de dialogo te permitirá configurar acciones como la de remover «casts» incesarios o agregar notaciones faltantes. Configura tu eclipse para optimizar la compilación, formateo y estilo de código.
Utiliza los teclas de aceso directo
Esto mas productivo y conveniente usar las teclas de acceso directo para ejecutar algunas tareas en eclipse en lugar de buscar las opciones que hacen lo mismo en los menús de navegación. Por ejemplo al buscar las referencias de una variable, método o una clase pueden ser mas fácilmente encontradas mediante el acceso directo Ctrl+Shif+g. Busca alguna ficha tácnica con todos los accesos directos de la IDE, son muy comunes y fáciles de encontrar.
via: javacodegeeks.com
Un objeto es inmutable cuando su estado no puede cambiar después de crearlo. String, Integer y LocalDate lo son. Parece una limitación, pero es lo que permite compartirlos entre hilos sin miedo o usarlos como claves de un mapa. Vemos qué significa en la práctica y cómo hacer los tuyos.
También te puede interesar
No, y por eso los métodos que parecen modificarlo en realidad devuelven otro objeto:
String s = "hola"; String t = s.toUpperCase(); IO.println(s + " / " + t);
salidahola / HOLA
s sigue siendo hola. toUpperCase no tocó la cadena: creó una nueva. Lo mismo hacen replace, trim o plusDays de LocalDate. Si llamas al método y no guardas lo que devuelve, no ha pasado nada.
final List<String> lista = new ArrayList<>();
lista.add("se puede");
IO.println("final pero mutable: " + lista);
List<String> fija = List.of("a", "b");
try {
fija.add("c");
} catch (UnsupportedOperationException e) {
IO.println("List.of: " + e.getClass().getSimpleName());
}
var original = new ArrayList<>(List.of("x"));
var vista = Collections.unmodifiableList(original);
var copia = List.copyOf(original);
original.add("y");
IO.println("vista: " + vista + " copia: " + copia);java Inmutable.javahola / HOLA final pero mutable: [se puede] List.of: UnsupportedOperationException vista: [x, y] copia: [x]
Tres cosas distintas que se confunden a menudo:
| ¿Qué impide? | ¿Inmutable? | |
|---|---|---|
final List | Que la variable apunte a otra lista. La lista en sí se puede cambiar. | No |
Collections.unmodifiableList(x) | Que la cambies a través de la vista. Si alguien cambia x, la vista lo refleja (sale [x, y]). | No |
List.of(…) / List.copyOf(x) | Cualquier cambio. copyOf hace una copia propia y no le afecta lo que pase después con x. | Sí |
Desde Java 16, con un record: todos sus campos son final, no tiene métodos que los cambien, y además trae equals, hashCode y toString. Para «modificarlo» se devuelve uno nuevo:
record Punto(int x, int y) {
Punto mover(int dx, int dy) { return new Punto(x + dx, y + dy); }
}
void main() {
var p = new Punto(1, 2);
var q = p.mover(3, 0);
IO.println(p + " -> " + q);
var claves = new java.util.HashMap<Punto, String>();
claves.put(new Punto(0, 0), "origen");
IO.println(claves.get(new Punto(0, 0)));
}java Punto.javaPunto[x=1, y=2] -> Punto[x=4, y=2] origen
Si el record tiene campos que a su vez son mutables, como una lista, hay que copiarlos en el constructor con List.copyOf. Si no, quien te la pasó puede seguir cambiándola. Lo vemos con un ejemplo en las buenas prácticas de Java, en el punto 3.
De las ventajas que se suelen enumerar, esta es la que más se nota. Un HashMap coloca cada clave según su hashCode en el momento de guardarla. Si la clave cambia después, queda en un sitio que ya no le corresponde:
var mapa = new HashMap<Punto, String>(); var p = new Punto(0, 0); mapa.put(p, "origen"); p.x = 5;
java MapaMutable.java — con un Punto mutableget(new Punto(0,0)): null get(new Punto(5,0)): null tamaño: 1, containsKey(p): false
La entrada sigue en el mapa (el tamaño es 1), pero no se puede encontrar ni con la clave vieja ni con la nueva, ni siquiera con el mismo objeto p. Con el record de arriba esto no puede pasar, y por eso new Punto(0, 0) encuentra «origen» sin problema.
| Ventaja | Por qué |
|---|---|
| Se comparten entre hilos sin sincronizar | Nadie puede cambiarlos, así que ningún hilo lee un estado a medias |
| No hace falta copiarlos | Se pueden devolver y pasar sin copias defensivas |
| Siempre están en un estado válido | Se comprueban una vez, en el constructor, y ya no cambian |
| Son fáciles de probar y de razonar | El mismo objeto da siempre los mismos resultados |
El coste es crear un objeto nuevo en cada «cambio». Para objetos pequeños es despreciable; si vas a hacer miles de cambios seguidos sobre algo grande, como un texto que se va construyendo, para eso existen las versiones mutables, como StringBuilder.
Entrada publicada en 2012 y revisada en octubre de 2026. Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio; las salidas están copiadas de esa ejecución.
| Primera lección para novatos de Java |
La primera lección para quien empieza con Java: no tiene nada que ver con JavaScript, salvo el nombre y parte de la sintaxis. Si quieres aprender Java desde cero, tienes nuestro curso de Java.
Leer un valor de un XML con indexOf y substring, o fabricar el documento sumando cadenas, parece más rápido que usar un analizador. Funciona con el primer ejemplo que pruebas y falla con el tercero. Lo comprobamos con seis casos, todos XML válidos.
También te puede interesar
Esta es la versión que suele aparecer, con el error que trae casi siempre:
String extraer(String xml) {
int inicio = xml.indexOf("<nombre>");
int fin = xml.indexOf("</nombre>");
return xml.substring(inicio, fin);
}Devuelve <nombre>Ana: indexOf da la posición donde empieza la etiqueta, y hay que saltársela. Corregido eso, la probamos con seis documentos que cualquier analizador lee sin problema:
String[] casos = {
"<persona><nombre>Ana</nombre></persona>",
"<persona><nombre>Gómez & Hijos</nombre></persona>",
"<persona><nombre><![CDATA[<b>Ana</b>]]></nombre></persona>",
"<persona><nombre >Ana</nombre></persona>",
"<persona>\n <!-- <nombre>viejo</nombre> -->\n <nombre>Ana</nombre>\n</persona>",
"<p:persona xmlns:p=\"urn:x\"><p:nombre>Ana</p:nombre></p:persona>",
};java AMano.javaoriginal: [<nombre>Ana] [Ana] [Gómez & Hijos] [<![CDATA[<b>Ana</b>]]>] [a><nombre >Ana] [viejo] excepción: Range [7, -1) out of bounds for length 63
| Caso | Resultado a mano | Qué pasó |
|---|---|---|
| Simple | Ana | Bien |
| Con una entidad | Gómez & Hijos | No traduce & a & |
| Con CDATA | <![CDATA[…]]> | Devuelve el envoltorio en vez del contenido |
| Con un espacio en la etiqueta | a><nombre >Ana | <nombre > es válido, pero indexOf no lo encuentra y devuelve basura |
| Con un comentario delante | viejo | Lee el nombre que estaba comentado |
| Con espacio de nombres | excepción | <p:nombre> no coincide y el programa se cae |
Cinco de seis mal, y lo peor es que solo uno avisa. Los demás devuelven un valor equivocado sin ningún error.
El JDK trae uno, así que no hace falta añadir ninguna dependencia:
String nombre(String xml) throws Exception {
var f = DocumentBuilderFactory.newInstance();
f.setNamespaceAware(true);
var doc = f.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
var nodos = doc.getElementsByTagNameNS("*", "nombre");
return nodos.getLength() == 0 ? null : nodos.item(0).getTextContent();
}java ConParser.java[Ana] [Gómez & Hijos] [<b>Ana</b>] [Ana] [Ana] [Ana]
Los seis bien. El analizador traduce las entidades, abre el CDATA, ignora los comentarios y entiende los espacios de nombres (por eso se activa setNamespaceAware y se busca con "*").
Construir el documento concatenando tiene el problema contrario: hay caracteres que en XML tienen significado y deben escaparse.
String aMano(String nombre, String atributo) {
return "<root>"
+ "<nombre atr=\"" + atributo + "\">"
+ nombre
+ "</nombre>"
+ "</root>";
}Con nombre = "Gómez & Hijos <S.A.>" y un atributo con comillas, el resultado ni siquiera es XML:
salida<root><nombre atr="dijo "hola"">Gómez & Hijos <S.A.></nombre></root> [Fatal Error] :1:26: Element type "nombre" must be followed by either attribute specifications, ">" or "/>". al leerlo: Element type "nombre" must be followed by either attribute specifications, ">" or "/>".
La línea [Fatal Error] la escribe el analizador por su cuenta en la salida de errores, antes de lanzar la excepción. Este es el error que verá quien reciba el archivo.
var doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
var root = doc.createElement("root");
var n = doc.createElement("nombre");
n.setAttribute("atr", atributo);
n.setTextContent(nombre);
root.appendChild(n);
doc.appendChild(root);
var t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
var out = new StringWriter();
t.transform(new DOMSource(doc), new StreamResult(out));salida<root> <nombre atr="dijo "hola"">Gómez & Hijos <S.A.></nombre> </root> de vuelta: [Gómez & Hijos <S.A.>] atr=[dijo "hola"]
El &, los < > y las comillas se escapan solos. Al volver a leerlo se recupera exactamente lo que se escribió, y eso es lo que hay que exigir a cualquier forma de generar XML.
Entrada publicada en 2011 y revisada en octubre de 2026. Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio; las salidas están copiadas de esa ejecución.
Unos cuantos hechos acerca de Chuck Norris, que quizá te convenga saber para tu examen de certificación SCJP.
![]() |
| Chuck Norris y Java |