tag:blogger.com,1999:blog-23303244864662015182023-11-15T14:03:08.041+01:00JavaBlogBlog dirigido a l@s que están aprendiendo el lenguaje de programación Java, con explicaciones, minitutoriales y "cómo se hace" que intentan ayudar a l@s novat@s.Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.comBlogger30125tag:blogger.com,1999:blog-2330324486466201518.post-47436347207198788732012-12-15T13:09:00.000+01:002012-12-15T13:09:46.187+01:00La clase BufferStrategy<div style="text-align: justify;">
En una <a href="http://javaparanulos.blogspot.com.es/2012/11/animacion-de-imagenes-en-java.html" target="_blank">entrada anterior</a> te había explicado cómo hacer una pequeña animación en Java. Ahora bien, es posible que te hayas dado cuenta de que no es todo lo perfecta que debiera, si no que se producen pequeños desajustes, o parpadeos, entre las imágenes, o que incluso a veces se pueden ver algo superpuestas.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Esto es así porque el programa está "dibujando" las imágenes a la vez que el sistema está continuamente refrescando la pantalla. Una forma de evitarlo es crear un espacio de almacenamiento donde el programa dibuje la imagen y no a muestre hasta que esté totalmente acabada. Exactamente esto es lo que hace la clase BufferStrategy. Además, se encarga que las imágenes no se muestren más rápido de la velocidad con la que el monitor se refresca, es decir, supongamos que tú tienes un juego en el que aparecen 150 escenas por segundo, pero tu monitor funciona a 75Hz, lo que significa que sólo puede mostrar 75 escenas por segundo, pues la clase BufferStrategy adapta el programa a esta velocidad. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Lo bueno es que tú sólo tienes que implementarla, ella solita se encarga de manejar los recursos del sistema. Se puede utilizar tanto con Canvas como con Windows, y para crearla elige primero el número de lugares de almacenamiento o "buffers" que deseas y luego utiliza el método createBufferStrategy(), por ejempo así:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="color: blue;">ventana.createBufferStrategy(2);</span></div>
<div style="text-align: justify;">
<span style="color: blue;"><br /></span></div>
<div style="text-align: justify;">
donde 2 es el número de buffers que creamos. Para invocarlo usaremos el método getBufferStrategy(). Por supuesto, hay que dibujar la imagen en el buffer y luego mostrarla. Esto se hace de la siguiente manera:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="color: blue;">BufferStrategy buffer = ventana.getBufferStrategy();</span></div>
<div style="text-align: justify;">
<span style="color: blue;">Graphics g = buffer.getDrawGraphics();</span></div>
<div style="text-align: justify;">
<span style="color: blue;">draw (g);</span></div>
<div style="text-align: justify;">
<span style="color: blue;">g.dispose();</span></div>
<div style="text-align: justify;">
<span style="color: blue;">buffer.show();</span></div>
<div style="text-align: justify;">
<span style="color: blue;"><br /></span></div>
<div style="text-align: justify;">
Te dejo a continuación una actualización del código visto en la entrada sobre animación, PantallaCompleta.java, donde ya está implementada la clase BufferStrategy, y ya puestos, se añaden otras mejoras, como el método getCompatibleDisplayModes(), que te ayudará a conseguir el mejor rendimiento posible del sistema que estés utilizando. También te dejo los códigos de AnimaciónTest.java y Animación.java, para que los tengas todos a mano, aunque también los tienes en la <a href="http://javaparanulos.blogspot.com.es/2012/11/animacion-de-imagenes-en-java.html" target="_blank">entrada correspondiente</a>.</div>
<div style="text-align: justify;">
Si aún no sabes crear una pantalla a modo completo, visita esta <a href="http://javaparanulos.blogspot.com.es/2012/11/como-crear-una-pantalla-completa-para.html" target="_blank">otra entrada</a>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
PantallaCompleta.java</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
</div>
<pre class="brush:java">import java.awt.*;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import java.awt.image.BufferedImage;
public class PantallaCompleta{
private GraphicsDevice gd;
public PantallaCompleta(){
//hay que usar los medios del propio sistema
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
gd = env.getDefaultScreenDevice();
}
//devuelve una lista de los modos de visualización compatibles con las características de nuestro sistema
public DisplayMode[] getCompatibleDisplayModes(){
return gd.getDisplayModes();
}
//devuelve el primer modo compatible o nada si no encuentra ninguno
public DisplayMode findFirstCompatibleMode(DisplayMode modes[]){
DisplayMode goodModes[] = gd.getDisplayModes();
for(int i = 0; i < modes.length; i++){
for(int j = 0; j < goodModes.length; j++){
if(displayModesMatch(modes[i], goodModes[j])){
return modes[i];
}
}
}
return null;
}
//devuelve el modo de visualización actual
public DisplayMode getCurrentDisplayMode(){
return gd.getDisplayMode();
}
/**
Determina si dos modos de visualización coinciden, es decir,
si tienen la misma resolución, velocidad de actualización de
pantalla, etc.
*/
public boolean displayModesMatch(DisplayMode mode1, DisplayMode mode2){
if(mode1.getWidth() != mode2.getWidth() || mode1.getHeight() != mode2.getHeight()){
return false;
}
if (mode1.getRefreshRate() !=
DisplayMode.REFRESH_RATE_UNKNOWN &&
mode2.getRefreshRate() !=
DisplayMode.REFRESH_RATE_UNKNOWN &&
mode1.getRefreshRate() != mode2.getRefreshRate()){
return false;
}
return true;
}
/**
Se pone la pantalla a modo pantalla completa y se cambia
el modo de visualización. En caso de que no hubiese ninguno
compatible o no se pudiese cambiar, se utiliza el que tiene
el sistema
*/
public void setFullScreen(DisplayMode displaymode){
JFrame ventana = new JFrame();
ventana.setUndecorated(true);
ventana.setIgnoreRepaint(true);
ventana.setResizable(false);
gd.setFullScreenWindow(ventana);
//comprobamos que el sistema soporta el cambio
if(displaymode != null && gd.isDisplayChangeSupported()){
try{
gd.setDisplayMode(displaymode);
}catch(IllegalArgumentException e){}
}
ventana.createBufferStrategy(2);
}
public Graphics2D getGraphics(){
Window window = gd.getFullScreenWindow();
if(window != null){
BufferStrategy strategy = window.getBufferStrategy();
return(Graphics2D)strategy.getDrawGraphics();
}else{
return null;
}
}
public void update(){
Window window = gd.getFullScreenWindow();
if(window != null){
BufferStrategy strategy = window.getBufferStrategy();
if(!strategy.contentsLost()){
strategy.show();
}
}
//sincronizamos con la ventana del sistema
Toolkit.getDefaultToolkit().sync();
}
public Window getFullScreenWindow(){
return gd.getFullScreenWindow();
}
public int getWidth(){
Window window = gd.getFullScreenWindow();
if(window != null){
return window.getWidth();
}else{
return 0;
}
}
public int getHeight(){
Window window = gd.getFullScreenWindow();
if(window != null){
return window.getHeight();
}else{
return 0;
}
}
//restauramos los valores previos
public void restoreScreen(){
Window w = gd.getFullScreenWindow();
if(w != null){
w.dispose();
}
gd.setFullScreenWindow(null);
}
/**
Creamos una imagen compatible con el modo de visualización,
que se almacena en la memoria del sistema
*/
public BufferedImage createCompatibleImage(int w, int h, int transparency){
Window window = gd.getFullScreenWindow();
if(window != null){
GraphicsConfiguration gc = window.getGraphicsConfiguration();
return gc.createCompatibleImage(w, h, transparency);
}
return null;
}
}
</pre>
<br />
Animación.java<br />
<br />
<br />
<br />
<pre class="brush:java">import java.awt.Image;
import java.util.ArrayList;
public class Animación{
private ArrayList frames;
private int actualFrame;
private long tiempoAnimación;
private long tiempoTotal;
public Animación(){
frames = new ArrayList();
tiempoTotal = 0;
start();
}
public synchronized void addFrame(Image image, long duración){
tiempoTotal += duración;
frames.add(new AnimFrame(image, tiempoTotal));
}
public synchronized void start(){
tiempoAnimación = 0;
actualFrame = 0;
}
public synchronized void update(long tiempoTranscurrido){
if(frames.size()>1){
tiempoAnimación += tiempoTranscurrido;
if(tiempoAnimación >= tiempoTotal){
tiempoAnimación = tiempoAnimación % tiempoTotal;
actualFrame = 0;
}
while(tiempoAnimación > getFrame(actualFrame).endTime){
actualFrame++;
}
}
}
public synchronized Image getImage(){
if (frames.size() ==0){
return null;
}else{
return getFrame(actualFrame).image;
}
}
private AnimFrame getFrame(int i){
return (AnimFrame)frames.get(i);
}
private class AnimFrame{
Image image;
long endTime;
public AnimFrame(Image image, long endTime){
this.image = image;
this.endTime = endTime;
}
}
}
</pre>
<br />
<br />
AnimaciónTest.java<br />
<br />
<br />
<pre class="brush:java">import java.awt.*;
import javax.swing.ImageIcon;
public class AnimaciónTest {
public static void main(String args[]) {
//DisplayMode displayMode= new DisplayMode(1024, 768, 32,
//DisplayMode.REFRESH_RATE_UNKNOWN);
AnimaciónTest test = new AnimaciónTest();
test.run();
}
private static final DisplayMode POSSIBLE_MODES[]={
new DisplayMode(800, 600, 32, 0),
new DisplayMode(800, 600, 24, 0),
new DisplayMode(800, 600, 16, 0),
new DisplayMode(640, 480, 32, 0),
new DisplayMode(640, 480, 24, 0),
new DisplayMode(640, 480, 16, 0)
};
private static final long DEMO_TIME = 10000;
private PantallaCompleta pc;
private Image bgImage;
private Animación animación;
public void loadImages() {
// cargamos las imágenes
bgImage = loadImage("images/background.jpg");
Image cara1 = loadImage("images/cara1.png");
Image cara2 = loadImage("images/cara2.png");
Image cara3 = loadImage("images/cara3.png");
// creamos la animación
animación = new Animación();
animación.addFrame(cara1, 250);
animación.addFrame(cara2, 150);
animación.addFrame(cara1, 150);
animación.addFrame(cara2, 150);
animación.addFrame(cara3, 200);
animación.addFrame(cara2, 150);
}
private Image loadImage(String fileName) {
return new ImageIcon(fileName).getImage();
}
public void run() {
pc = new PantallaCompleta();
try {
DisplayMode displayMode = pc.findFirstCompatibleMode(POSSIBLE_MODES);
pc.setFullScreen(displayMode);
loadImages();
animationLoop();
}
finally {
pc.restoreScreen();
}
}
public void animationLoop() {
long tiempoInicio = System.currentTimeMillis();
long tiempoActual = tiempoInicio;
while (tiempoActual - tiempoInicio < DEMO_TIME) {
long tiempoTranscurrido =
System.currentTimeMillis() - tiempoActual;
tiempoActual += tiempoTranscurrido;
// actualizamos la animación
animación.update(tiempoTranscurrido);
// se dibuja en pantalla
Graphics2D g =
pc.getGraphics();
draw(g);
g.dispose();
pc.update();
// una pequeña pausa
try {
Thread.sleep(20);
}
catch (InterruptedException ex) { }
}
}
public void draw(Graphics g) {
// se dibuja el fondo
g.drawImage(bgImage, 0, 0, null);
// se dibuja la imagen y la centramos más o menos
g.drawImage(animación.getImage(), 300, 200, null);
}
}
</pre>
Si quieres ver más a fondo la clase BufferStrategy, puedes visitar estas páginas:<br />
<br />
<ul>
<li style="text-align: justify;"><a href="http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/BufferStrategy.html" rel="nofollow" target="_blank">Oracle</a></li>
<li style="text-align: justify;"><a href="http://gpsnippets.blogspot.com.es/2010/10/how-to-use-bufferstrategy-in-java.html" rel="nofollow" target="_blank">GPSnippets</a></li>
<li style="text-align: justify;"><a href="http://content.gpwiki.org/index.php/Java:Tutorials:Double_Buffering" target="_blank">GPWiki</a></li>
</ul>
<br />
Vale, están todas en inglés, así que, si no lo dominas, es una suerte que esté yo, ¿eh? ;-)Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com4tag:blogger.com,1999:blog-2330324486466201518.post-75535704622517820002012-12-02T13:45:00.003+01:002013-09-23T17:25:39.740+02:00Introducción a los genéricos (generics) en Java<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Érase una
vez, en una galaxia muy, muy lejana, antes de Java 5 y de la
existencia de genéricos, los programadores java que utilizaban
colecciones, se enfrentaban a un temible peligro.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Ellos
podían, por ejemplo, crear una lista de Strings como la siguiente:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List
miLista = new ArrayList( );</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">miLista.add(“Hola”);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">miLista.add(“Galaxia”);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">miLista.add(new
Integer(2001));</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">podían,
incluso, hacer un casting al obtener los elementos de esa lista:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">String s
= (String) miLista.get(0);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">String st
= (String) miLista.get(1);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">String
str = (String) miLista.get(2);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">¡Pero nada
de eso evitaba que al ejecutarse el programa se produjera un error!
¿Por qué? ¡Porque el tercer elemento no es un String, sino un
Integer, pero nada impedía añadirlo a la lista! Por suerte, los
genéricos vinieron al rescate de estos desdichados programadores y
nunca más se produjeron errores de este tipo.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Bueno, vale,
puede que la historia no fuese exactamente así, pero nos sirve para
explicar en qué consisten los genéricos y su función. Desde luego
los genéricos no se utilizan sólo con las colecciones, pero es
cierto que es en ellas donde te los vas a encontrar mayoritariamente.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Los
genéricos permiten asignar parámetros a las clases, interfaces,
métodos..., de forma que sólo admitan los tipos de objetos que tu
quieras. <b>No</b> se pueden utilizar con primitivos, pero si con las
clases que se corresponden con ellos. Por eso no puedes hacer un
genérico tipo int, pero sí un Integer. Veamos el ejemplo anterior
utilizando genéricos:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List
<String> miLista = new ArrayList <String>();</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: #38761d; font-size: medium;">//al
poner <String> estamos indicando que la lista sólo acepta
Strings</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><span style="color: blue;">miLista.add(“Hola”);</span>
<span style="color: #38761d;">//un String, perfecto</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><span style="color: blue;">miLista.add(“Galaxia”);</span> <span style="color: #38761d;">//otro String, muy bien</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><span style="color: blue;">miLista.add(new
Integer(2001));</span><span style="color: #38761d;"> //¡error de compilación, no es un String!</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Evidentemente,
es mucho más sencillo solucionar un error de compilación que un
error de ejecución. Además, no hace falta ningún casting para
obtener los elementos de la lista:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">String s
= miLista.get(0);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">String st
= miLista.get(1); </span>
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: #38761d; font-size: medium;">//el
compilador ya sabe que es un String, no hace falta casting.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: #38761d; font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Para
conseguir esto, basta poner entre los signos < >, llamados diamante, el tipo al que
queremos que pertenezcan los elementos: String, Integer o lo que sea.
Además, para facilitar más las cosas, <b><a href="http://javaparanulos.blogspot.com.es/2011/12/novedades-en-java-7.html" target="_blank"><span style="color: orange;">a partir de Java 7</span></a></b> la
primera línea de este código se escribiría así:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List
<String> miLista = new ArrayList<>();</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">porque el
compilador ya infiere de qué tipo son los elementos de la lista.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Pero, ¿cómo
crear nuestra propia clase genérica? Fíjate en este ejemplo:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">public
class Cajón<T>{</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;"> private
T t;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;"> public
void set (T t){</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;"> this.t
= t;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;"> }</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;"> public
T get( ){</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;"> return
t;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;"> }</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><span style="color: blue;">}</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Ya hemos
construído una clase genérica, y le hemos proporcionado dos
métodos. La T es el tipo de parámetro que le vamos a asignar. Supón
por ejemplo que quieres un Cajón de Calcetines y otro Cajón de
Camisetas, pues sustituyes T por Calcetines o por Camisetas (por
supuesto, si no existen las clases Camisetas ni Calcetines, debes
crearlas) de esta forma:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><span style="color: blue;">public
class Cajón<Calcetines> </span> o <span style="color: blue;">public class Cajón<Camisetas></span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Todos los
métodos de tu clase genérica pueden ser utilizados en cualquiera de
ellas, pero no podrás usar calcetines con Cajón<Camisetas> ni
camisetas con Cajón<Calcetines>.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Por
convención, los nombres de los tipos de parámetros se escriben como
una letra mayúscula, y los más habituales son :</span></div>
<ul>
<li><div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">T, de
tipo</span></div>
</li>
<li><div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">E, de
elemento, muy usado con la Java Collection Framework</span></div>
</li>
<li><div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">N, de
número (class Number)</span></div>
</li>
<li><div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">K, de
key</span></div>
</li>
<li><div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">V, de
value, estas dos últimas utilizadas sobre todo en mapas (Map)</span></div>
</li>
</ul>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">¿Y cómo
sería un método en el que estemos utilizando genéricos?</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">void
añadirCalcetines (Cajón<Calcetines> cal){</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;"> cal.add(new
Calcetines( ));</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">}</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Un método
muy simplón, pero sirve para que veas la sintaxis. Y hablando de
sintaxis, es muy habitual con los genéricos ver esto: <?>
acompañado a veces de “extends” o “super”. Ahora mismo te
explico lo que significa. Supongamos que tienes una lista de números
enteros: </span>
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List<Integer>
miLista = new List<>( );</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">y piensas,
“bueno, Integer es una subclase de Number, así que puedo hacer
esto” y escribes:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List<Number>
miLista = new List<Integer>( );</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">¡No
compila! ¿Por qué? ¡Porque List<Integer> no es un subtipo de
List<Number>! En List<Number> sólo pueden entrar objetos
que pertenezcan a la clase Number, no objetos de la clase Integer, ni
de la clase Double, ni Short, ni Long. Sólo de la clase Number, por
eso, aunque a la lista puedes añadirle números enteros, o decimales
o los que quieras que pertenezcan a Number, no puedes decir que es
una nueva lista de números enteros. Ahora bien, si escribimos esto:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List<?
extends Number></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">estamos
indicando que esta lista va a admitir objetos de la clase Number <i>y
de cualquier otra que la extienda </i>(“?”
significa cualquiera). Así pues, modificamos</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List<?extends
Number> miLista = new List<Integer>( );</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">y
ahora sí que compila. Y también compilará si en lugar de
List<Integer> utilizamos cualquier otra subclase de Number,
como List<Double>.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Pero,
¿qué ocurre si lo que queremos es lo contrario, es decir, que la
lista admita objetos de la clase Integer y su superclase, pero no
ninguna otra subclase de Number?</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">En
ese caso, haríamos lo siguiente:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List<? super
Integer> </span>
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">con
lo que la lista admitirá objetos de la clase Integer y de cualquier
otra clase superior a ella, como Number.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">¿Y
qué ocurre si hacemos esto?:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List<?></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Lo
que estamos indicando ahora es que la lista admitiría cualquier tipo
de objetos. No confundir con “objetos de la clase Object”. Es
decir, esto:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-size: medium;">List<Object> </span>
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">sólo
admite objetos que pertenezcan a la clase Object, y no podemos hacer
lo siguiente:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><span style="color: blue;">List<Object>
miLista = new List<Calcetines>( );</span> <span style="color: #38761d;">//no compila</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Por
último, quiero añadir que es cierto que los genéricos en Java no
son perfectos (como los programadores en C siempre señalan amablemente)
pero eso es así porque desde un principio se busco que fuese
compatible con todo el código escrito con anterioridad a Java 5, que
no los utilizaba. No era cuestión de que todo ese código dejase de
funcionar, ¿no?</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Si has tenido dificultades en seguir esta entrada porque no sabes lo que son las colecciones, puedes ver <a href="http://javaparanulos.blogspot.com.es/2011/12/colecciones.html" target="_blank"><span style="color: orange;"><b>esta entrada anterior</b></span></a>. Si el problema es con el polimorfismo y la herencia, <a href="http://javaparanulos.blogspot.com.es/2012/01/polimorfismo-y-herencia.html" target="_blank"><span style="color: orange;"><b>consulta esta otra</b></span></a>. Para ampliar conocimientos, consulta los <b><a href="http://docs.oracle.com/javase/tutorial/java/generics/" target="_blank"><span style="color: orange;">tutoriales de Oracle</span></a>.</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-size: medium;">Si tienes dudas, pregúntame. Y si te ha gustado, compártelo.;-)</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;"><b><i><u>En respuesta a la consulta de Anet (ver Comentarios)</u></i></b></span><br />
<span style="font-size: medium;">Hola, Anet:</span><br />
<span style="font-size: medium;">¡Es un placer ver una chica por aquí!</span><br />
<span style="font-size: medium;">Respecto a tu pregunta, no tengo muy claro qué es exactamente lo que quieres hacer, así que no sé si la respuesta será la que buscas.</span><br />
<span style="font-size: medium;">Como ya hemos visto, los genéricos siguen las reglas de herencia de Java a nivel de tipo, pero no a nivel de parámetro.</span><br />
<span style="font-size: medium;">Por ejemplo, podemos hacer</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;">Set<String> mySet = new HashSet<String>();</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;">porque HashSet es un subtipo de Set, pero no</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;">Set<Object> mySet = new HashSet<String>();</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;">porque sólo puedes usar Object como parámetro, no String, y por eso utilizamos los wildcards y extends, como muestro arriba.</span><br />
<span style="font-size: medium;">Con las interfaces, sería lo mismo, solo que en lugar de extends, usaríamos implements.</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;">A continuación te dejo un ejemplo de un código, donde creo una clase que va a ser un subtipo de ArrayList. Fíjate que por eso no necesitamos que mi clase implemente la interfaz List, porque eso ya lo hace ArrayList.</span><br />
<span style="font-size: medium;">Además, vamos a hacer que implemente una interfaz que yo he creado, de esa manera podrás ver cómo se hace.</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;">import java.util.*;</span><br />
<span style="font-size: medium;">public class TestGen{</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="font-size: medium;"> </span></span><br />
<span style="font-size: medium;"> public static void main(String args[]){</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span> MyGen<String> miLista = new MyGen<String>();</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>miLista.add(0,"A");</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>miLista.add(1,"B");</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>miLista.add(2,"C");</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>for (String item: miLista){</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>System.out.println(item);</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>ArrayList<String> miOtraLista = new MyGen<String>();</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>miOtraLista.addAll(miLista);</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>for (String item: miOtraLista){</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>System.out.println(item);</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>if (miOtraLista.containsAll(miLista)){</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>System.out.println("Tienen los mismos elementos");</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>String miEjemplo = miLista.ejemplo().toString();</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>System.out.println(miEjemplo);</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="font-size: medium;"> </span></span><br />
<span style="font-size: medium;">}</span><br />
<span style="font-size: medium;">//La clase MyGen extiende ArrayList (que a su vez implementa List) y además implementa la interfaz //Ejemplo</span><br />
<span style="font-size: medium;">class MyGen<String> extends ArrayList<String> implements Ejemplo<Double>{</span><br />
<span style="font-size: medium;">//aquí sustituímos T por Double, pero podríamos poner cualquier otro tipo</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>public MyGen(){</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>super();</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>//nuestra versión del método ejemplo</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>@Override</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>public Double ejemplo(){</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>return 15.25;</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="font-size: medium;">}</span><br />
<span style="font-size: medium;">//creamos la interfaz usando T, de forma que cuando la implementemos podamos usar el tipo que //queramos.</span><br />
<span style="font-size: medium;"> interface Ejemplo<T>{</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>T ejemplo();</span><br />
<span style="font-size: medium;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="font-size: medium;"><br /></span>
<span style="font-size: medium;">De esta manera, la clase MyGen puede utilizar los métodos de ArrayList, que a su vez tiene los de las interfaces que implementa, y además va a poder usar el método de la interfaz Ejemplo.</span><br />
<span style="font-size: medium;">Espero que ésto te ayude a aclarar los conceptos.</span><br />
<span style="font-size: medium;"></span><br />
<span style="font-size: medium;">¡Un saludo!</span></div>
Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com11tag:blogger.com,1999:blog-2330324486466201518.post-54336053385646677472012-11-24T16:31:00.001+01:002012-11-24T16:31:48.859+01:00Animación de Imágenes en Java<br />
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">En esta entrada del blog,
voy a enseñarte cómo hacer imágenes con animación en Java. Para
ello, lo primero que vamos a necesitar son...lo has adivinado:
imágenes. Pueden ser fotos, o pueden ser dibujos sencillos, pero eso
sí, tienen que mostrar movimientos consecutivos; por ejemplo, un
pájaro subiendo y bajando las alas, o una cara abriendo y cerrando
los ojos.</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;"><br />
</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">Si sabes utilizar
Photoshop, Gimp o cualquier otro programa por el estilo, enhorabuena,
dale rienda suelta a tu imaginación para crear las imágenes que
desees (y ya puestos, compártelas con nosotros).</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;"><br /></span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">Si por el contrario, eres
como yo, que a lo más que llegas es a dibujar un círculo con Paint,
pues nada, le pones dos circulitos más pequeños dentro para simular
ojos abiertos y dos líneas para simular ojos cerrados y ya tienes
una carita que parpadea. Ahora guardas los dos dibujos como .png y
listo.</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;"><br />
</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">También puedes añadirle
una imagen de fondo que ocupe toda la pantalla: una foto en formato
.jpg, otro dibujo o un fondo liso, lo que quieras.</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;"><br />
</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">Lo que vamos a hacer con
estas imágenes es, primero, crear un ArrayList para contenerlas, y
después, asignarles a cada una una duración determinada en
milisegundos. Por último, vamos a mostrarlas en pantalla en un bucle
para conseguir ese efecto de animación.</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;"><br />
</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">Para ello vamos a crear
una clase, Animación (qué sorpresa de nombre, ¿eh?) que contendrá
los métodos necesarios. Despues haremos otra para probarla, y
originales como somos la llamaremos AnimaciónTest.
PruebaDeAnimación tampoco está mal, pero es que es más largo. Dentro de esta clase AnimaciónTest vamos a utilizar un objeto de la clase PantallaCompleta, que creamos en una entrada anterior y que utilizamos, nunca lo adivinarías, para visualizar el resultado en una pantalla completa . <a href="http://javaparanulos.blogspot.com.es/2012/11/como-crear-una-pantalla-completa-para.html" target="_blank">Aquí</a> puedes ver el código de esa clase.</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;"><br />
</span></div>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">Para que luego no te líes
con el código, te voy a explicar el significado de algunas variables
que verás en él:</span></div>
<ul>
<li><div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">frames, que en
inglés viene siendo fotogramas, es el nombre del ArrayList</span></div>
</li>
<li><div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">actualFrame es el
número de índice de un elemento de frames</span></div>
</li>
<li><div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">tiempoAnimación es
el tiempo que dura toda la animación
</span></div>
</li>
<li><div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">tiempoTotal es la
suma de los milisegundos de duración que hemos asignado a cada
imagen</span></div>
</li>
</ul>
<div style="margin-bottom: 0pt; text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">Clase Animación.java</span>
</div>
<div style="margin-bottom: 0pt; text-align: justify;">
<br /></div>
<div style="margin-bottom: 0pt; text-align: justify;">
</div>
<pre class="brush:java">import java.awt.Image;
import java.util.ArrayList;
public class Animación{
private ArrayList frames;
private int actualFrame;
private long tiempoAnimación;
private long tiempoTotal;
public Animación(){
frames = new ArrayList();
tiempoTotal = 0;
start();
}
public synchronized void addFrame(Image image, long duración){
tiempoTotal += duración;
frames.add(new AnimFrame(image, tiempoTotal));
}
public synchronized void start(){
tiempoAnimación = 0;
actualFrame = 0;
}
public synchronized void update(long tiempoTranscurrido){
if(frames.size()>1){
tiempoAnimación += tiempoTranscurrido;
if(tiempoAnimación >= tiempoTotal){
tiempoAnimación = tiempoAnimación % tiempoTotal;
actualFrame = 0;
}
while(tiempoAnimación > getFrame(actualFrame).endTime){
actualFrame++;
}
}
}
public synchronized Image getImage(){
if (frames.size() ==0){
return null;
}else{
return getFrame(actualFrame).image;
}
}
private AnimFrame getFrame(int i){
return (AnimFrame)frames.get(i);
}
private class AnimFrame{
Image image;
long endTime;
public AnimFrame(Image image, long endTime){
this.image = image;
this.endTime = endTime;
}
}
}
</pre>
<div style="margin-bottom: 0pt;">
<span style="font-family: Georgia, Times New Roman, serif;"></span></div>
<div style="margin-bottom: 0pt;">
<span style="font-family: Georgia, Times New Roman, serif;"></span></div>
<div style="margin-bottom: 0pt;">
</div>
<div style="margin-bottom: 0pt;">
</div>
<div style="margin-bottom: 0pt;">
</div>
<div style="margin-bottom: 0pt;">
<span style="font-family: Georgia, Times New Roman, serif;">
Clase AnimaciónTest.java</span><br />
<span style="font-family: Georgia, Times New Roman, serif;"><br /></span></div>
<div style="margin-bottom: 0pt;">
<span style="font-family: Georgia, Times New Roman, serif;">
</span></div>
<pre class="brush:java">import java.awt.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class AnimaciónTest {
public static void main(String args[]) {
DisplayMode displayMode= new DisplayMode(1024, 768, 32,
DisplayMode.REFRESH_RATE_UNKNOWN);
AnimaciónTest test = new AnimaciónTest();
test.run(displayMode);
}
private static final long DEMO_TIME = 10000;
private PantallaCompleta pc;
private Image bgImage;
private Animación animación;
public void loadImages() {
// cargamos las imágenes
bgImage = loadImage("images/background.jpg");
Image cara1 = loadImage("images/cara1.png");
Image cara2 = loadImage("images/cara2.png");
Image cara3 = loadImage("images/cara3.png");
// creamos la animación
animación = new Animación();
animación.addFrame(cara1, 250);
animación.addFrame(cara2, 150);
animación.addFrame(cara1, 150);
animación.addFrame(cara2, 150);
animación.addFrame(cara3, 200);
animación.addFrame(cara2, 150);
}
private Image loadImage(String fileName) {
return new ImageIcon(fileName).getImage();
}
public void run(DisplayMode displayMode) {
pc = new PantallaCompleta();
try {
pc.setFullScreen(displayMode, new JFrame());
loadImages();
animationLoop();
}
finally {
pc.restoreScreen();
}
}
public void animationLoop() {
long tiempoInicio = System.currentTimeMillis();
long tiempoActual = tiempoInicio;
while (tiempoActual - tiempoInicio < DEMO_TIME) {
long tiempoTranscurrido =
System.currentTimeMillis() - tiempoActual;
tiempoActual += tiempoTranscurrido;
// actualizamos la animación
animación.update(tiempoTranscurrido);
// se dibuja en pantalla
Graphics g =
pc.getFullScreenWindow().getGraphics();
draw(g);
g.dispose();
// una pequeña pausa
try {
Thread.sleep(20);
}
catch (InterruptedException ex) { }
}
}
public void draw(Graphics g) {
// se dibuja el fondo
g.drawImage(bgImage, 0, 0, null);
// se dibuja la imagen y la centramos más o menos
g.drawImage(animación.getImage(), 300, 200, null);
}
}
</pre>
<div style="margin-bottom: 0pt;">
<span style="font-family: Georgia, Times New Roman, serif;"></span></div>
<div style="margin-bottom: 0pt;">
<span style="font-family: Georgia, Times New Roman, serif;"></span></div>
<div style="margin-bottom: 0pt;">
<span style="font-family: Georgia, Times New Roman, serif;"></span></div>
<div>
<span style="font-family: Georgia, Times New Roman, serif;">
</span></div>
<div>
<div style="text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">Yo he utilizado una imagen de fondo y tres dibujos de una cara, pero tú puedes usar el número de imágenes que quieras. Fíjate que cada imagen se puede añadir más de una vez, en distinto orden y con distinto tiempo asignado, para crear distintas animaciones. Tú puedes jugar con ello hasta encontrar la que te gusta.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;"><br /></span></div>
</div>
<div>
<span style="font-family: Georgia, Times New Roman, serif;">
</span></div>
<div>
<div style="text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">En otro momento te enseñaré a añadirle otros efectos y a utilizar la clase BufferStrategy para evitar que la imagen parpadee.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;"><br /></span></div>
</div>
<div>
<span style="font-family: Georgia, Times New Roman, serif;">
</span></div>
<div>
<div style="text-align: justify;">
<span style="font-family: Georgia, Times New Roman, serif;">¡Si tienes alguna duda, ya sabes dónde estoy!</span></div>
</div>
<div style="margin-bottom: 0pt; text-align: justify;">
</div>
Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com1tag:blogger.com,1999:blog-2330324486466201518.post-33685113845297426502012-11-17T17:17:00.000+01:002012-11-17T17:17:40.027+01:00Thread Pools en Java<br />
<div align="JUSTIFY" style="margin-bottom: 0pt;">
En otras entradas he
explicado que son los hilos o <a href="http://javaparanulos.blogspot.com.es/2012/04/threads-i-formas-de-crear-threads.html" target="_blank">threads</a>, cómo crearlos y cómo
funcionan. En esta entrada voy a tratar el tema de las <b>thread
pools</b>, literalmente “piscinas
de hilos”. ¿Por qué se llaman así? Bueno...ni idea. Pero ya que
le han dado ese nombre, voy a utilizarlo en mi metáfora para
explicarte en que consisten.</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
Imagínate
una thread pool como un grupo de nadadores vagueando al borde de una
piscina. De vez en cuando llega un entrenador con la orden de que uno
de los nadadores tiene que recorrer la piscina de arriba abajo. A
veces todos los nadadores reciben esas órdenes, un entrenador por
cada nadador. En ocasiones hay más entrenadores que nadadores, y
los últimos en llegar tienen que esperar a que vayan regresando los
nadadores para ir dándoles de nuevo la orden de recorrer la piscina.
Y otras veces sólo algunos nadadores están nadando mientras los
otros están jugando a las cartas, esperando a que llegue algún
entrenador.
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
Ahora
sustituye “entrenador” por “tarea” y “nadador” por “hilo”
y ya tienes una thread pool.
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
“Vale”,
te preguntarás, “¿y por qué hacer una thread pool? ¿No es mejor
ir creando los hilos según los necesitemos?”. Pues eso va a
depender del programa en cuestión. Ten en cuenta que cada hilo que
creas ocupa lugar en la memoria. Si tienes un programa que sólo va a
tener tres o cuatro tareas distintas, pues bueno, creas tres o cuatro
hilos. Pero, ¿y si es un programa con cientos o miles de tareas?.
Cientos de hilos ocuparán bastante memoria. Y lo que es peor: <i>tú
tendrás que escribir el código para crear todos esos hilos.</i>Créeme,
es buena práctica separar en ese caso las tareas de los hilos en tu
código. Y tú trabajarás menos.</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
Además,
está la cuestión de la eficiencia. Ya sé lo que estás pensando:
“¿No es más eficiente tener un hilo para cada tarea, en lugar de
tener tareas esperando que haya un hilo libre?” Volvamos a nuestro
ejemplo de la piscina.</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
Supón
que en la piscina hay cien nadadores y que todos reciben la orden de
nadar a la vez. ¿Has tratado alguna vez de nadar en una piscina
abarrotada? ¿Crees que alguno de los nadadores conseguiría un
récord de velocidad? Pues tu programa lo mismo. El sistema en el que
se ejecute tendrá que repartir sus recursos entre todos los hilos a
la vez.
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
Hagamos
ahora que los nadadores sean sólo diez, con las mismas cien tareas.
Es cierto que hay algunas tareas que tendrán que esperar a que los
nadadores vayan regresando para realizarse, pero como los nadadores
pueden ir y volver mucho más rápido, las primeras tareas serán
“visto y no visto” y el tiempo de espera de las últimas será
similar al producido si todas tuviesen un hilo propio. Y eso si todas
las órdenes se reciben a la vez, porque si los entrenadores van
llegando de forma separada, el tiempo de espera de los últimos no
será mayor que el de los primeros.</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
Bueno,
ya sabemos lo que es una thread pool, ¿pero cómo se utiliza?. Ah,
aquí entran en juego los “Ejecutores”. No, no es una película
de Schawzenegger. Los ejecutores en java son simplemente los que se
encargan de manejar la ejecución de las tareas.</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
Java
tiene una clase, Executors, con métodos estáticos para la creación
de thread pools, y tres interfaces:</div>
<ul>
<li><div align="JUSTIFY" style="margin-bottom: 0pt;">
Executor,
que simplemente ejecuta las tareas</div>
</li>
<li><div align="JUSTIFY" style="margin-bottom: 0pt;">
ExecutorService,
subinterfaz de la anterior que añade nuevos métodos para controlar
las tareas.</div>
</li>
<li><div align="JUSTIFY" style="margin-bottom: 0pt;">
ScheduledExecutorService,
subinterfaz de ExecutorService que soporta la ejecución de tareas
programadas.</div>
</li>
</ul>
<div style="margin-bottom: 0pt; text-align: justify;">
Todas
ellas forman parte del paquete java.util.concurrent.</div>
<div style="margin-bottom: 0pt; text-align: justify;">
<br /></div>
<div style="margin-bottom: 0pt; text-align: justify;">
A continuación, te voy a mostrar un ejemplo sencillísimo de thread pool. Vamos a crear dos clases, una que implementa la interfaz Runnable, porque los ejecutores trabajan con objetos "runnable" o "callable", y otra que contiene el método principal y donde crearemos una thread pool de 10 hilos.<br />
<br /></div>
<div style="margin-bottom: 0pt; text-align: justify;">
Tarea.java</div>
<div style="margin-bottom: 0pt; text-align: justify;">
<br /></div>
<pre class="brush:java">public class Tarea implements Runnable{
private int sleepTime;
private String name;
public Tarea(String name){
this.name = name;//le asignamos un nombre a cada tarea.
sleepTime = 1000;
}
public void run(){
try{
System.out.printf("El hilo de la tarea "+this.name+" va a dormir durante %d milisegundos.\n",sleepTime);
Thread.sleep(sleepTime);//hacemos que cada hilo duerma durante 1 segundo
}catch(InterruptedException exception){
exception.printStackTrace();
}
System.out.println("Este hilo ya ha dormido bastante");
}
}</pre>
</br>
</br>
EjemploThreadPool.java
<br />
<br />
<pre class="brush:java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EjemploThreadPool{
public static void main (String args[]){
System.out.println("Comienza la ejecución");
ExecutorService ex = Executors.newFixedThreadPool(10);
Tarea t;
for(int i = 0;i<200; i++){
t = new Tarea(""+i);
ex.execute(t);
}
ex.shutdown();
}
}</pre>
</br>
</br>
¿Qué es lo que hace este programa? No gran cosa. Se limita a escribir en la consola que el hilo que está ejecutando cada tarea, a las que hemos asignado un número, va a dormir durante 1 segundo. Pero, ¿y lo que has aprendido?
<br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Fíjate que al método execute es al que hay que darle un objeto runnable, y que el método shutdown se asegura de cerrar al finalizar las tareas. Ambos métodos pertenecen a la interfaz ExecutorService. Para crear la trhead pool hemos empleado el método newFixedThreadPool(), al que se le da un número específico de hilos. Pero existen más, como el newCachedThreadPool(), ambos de la clase Executors.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Para ampliar conocimientos, te recomiendo el <a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html" rel="nofollow" target="_blank">tutorial</a> sobre concurrencia de Oracle, y el libro "Java Threads", de S. Oaks y H. Wong, publicado por O´Reilly.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Y como siempre, si tienes alguna duda o comentario, ya sabes donde estamos.</div>
Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com14tag:blogger.com,1999:blog-2330324486466201518.post-11813916550339876312012-11-10T14:57:00.000+01:002012-11-10T22:51:44.184+01:00Cómo crear una pantalla completa para juegos en Java<div style="text-align: justify;">
Supongamos que has estado aprendiendo Java durante algún tiempo; ya sabes todo lo que hay que saber sobre clases, objetos, métodos, <a href="http://javaparanulos.blogspot.com.es/2012/01/polimorfismo-y-herencia.html" target="_blank">polimorfismo</a>, <a href="http://javaparanulos.blogspot.com.es/2012/04/threads-ii-synchronized.html" target="_blank">threads</a>...Pero ahora quieres hacer algo realmente espectacular, como un juego (no para presumir, por supuesto, sólo para ampliar conocimientos). Y no un juego cualquiera, no una pequeña applet ni un juego embebido en una frame, sino un juego a pantalla completa, sin menús, ni barras horizontales o laterales que distraigan al jugador. Pero, ¿por dónde empezar?</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Bueno, evidentemente, excede los límites de cualquier entrada de un blog el explicarte cómo hacer un juego en Java, pero lo que sí puedo hacer es mostrarte cómo crear una pantalla a tamaño completo para él. Antes de nada, vamos a aclarar algunos conceptos que necesitas saber (si ya los sabes, pues te vas directamente al código y listo).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Al diseñar un juego, hay que tener en cuenta que se tiene que poder ver en distintos ordenadores, de los que no vas a saber la resolución de los monitores ni la capacidad de la tarjeta de vídeo.¿Qué es la resolución? La pantalla de un monitor está dividida en pequeños puntitos llamados píxeles. El número de píxeles horizontales y verticales es la resolución de esa pantalla. Por ejemplo, un monitor con 800 píxeles horizontales y 600 píxeles verticales tiene una resolución de 800x600. Ten en cuenta que los píxeles se empiezan a contar desde 0, es decir 0 es el primer píxel y 799 el último.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Si tú pones una resolución en la pantalla de tu juego, pero el monitor tiene otra, la imagen no será tan nítida. Lo ideal es que el jugador pueda elegir la resolución según su monitor. Las resoluciones más utilizadas hoy en día son 800x600, 1024x768 y 1280x1024. En el código que verás después, hemos puesto una resolución fija, para no hacerlo muy extenso, pero tú puedes poner la de tu propio monitor si no es la misma.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Otro detalle en el que hay que fijarse, es en el Display Mode, o capacidad de bits de un monitor, que determina el número de colores que ese monitor puede mostrar. En nuestro ejemplo vamos a dejarlo en 32, que son 2 elevado a 32 colores (¿tienes una calculadora científica a mano? ¿no? bueno, son muchos colores) Si tu monitor es un poco más antiguo o prefieres aumentar la rapidez, puedes usar 16 bit, que son (esta me la sé) 65.536 colores.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Por último tenemos el Refresh Rate, que viene siendo la rapidez con la que la pantalla se está "repintando" una y otra vez. Lo que a ti te parece una imagen fija, en realidad no lo es, porque la luz de los píxeles se desvanece y el monitor está continuamente "encendiéndolos" de nuevo.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Ahora que ya hemos aclarado estos aspectos, para que sepas lo que son cuando los veas en el código, te voy a explicar lo que vamos a hacer. Vamos a crear una ventana, como las típicas de Windows, pero sin ninguna decoración, es decir, sin menús ni barras, ni botoncito de ningún tipo. En un juego normal, por supuesto, tienes la opción de salir cuando quieras, pero aquí, para favorecer la claridad del código y de lo que quiero enseñarte, vamos a dejar que esa pantalla se mantenga unos segundos y luego se desvanezca, que no es cuestión de que te quedes para siempre con ella. Si deseas que tenerla durante más o menos segundos, sólo tienes que cambiar el valor que yo le he puesto.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Hay algunos sistemas que no dejan que cambies el display que tienen por defecto, por lo que tendremos que asegurarnos primero de que ése no es el caso. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Así que vamos a hacer dos clases, la primera será la que tenga el constructor de la pantalla, y la segunda será la que tenga el método main, donde probaremos a ver si funciona. Con ellas crearemos una pantalla completa con un color de fondo naranja y una frase en negro, que se mantendrá durante 10 segundos.<br />
<br />
PantallaCompleta.java</div>
<div style="text-align: justify;">
<br /></div>
<pre class="brush:java">import java.awt.*;
import javax.swing.JFrame;
public class PantallaCompleta{
private GraphicsDevice gd;//tarjeta gráfica
public PantallaCompleta(){
//hay que usar los medios del propio sistema
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
gd = env.getDefaultScreenDevice();
}
public void setFullScreen(DisplayMode dm, JFrame ventana){
ventana.setUndecorated(true);
ventana.setResizable(false);
gd.setFullScreenWindow(ventana);
//comprobamos que el sistema soporta el cambio
if(dm != null && gd.isDisplayChangeSupported()){
try{
gd.setDisplayMode(dm);
}catch(IllegalArgumentException e){}
}
}
public Window getFullScreenWindow(){
return gd.getFullScreenWindow();
}
//restauramos los valores previos
public void restoreScreen(){
Window w = gd.getFullScreenWindow();
if(w != null){
w.dispose();
}
gd.setFullScreenWindow(null);
}
}
</pre>
<div style="text-align: justify;">
<br />
TestPantallaCompleta.java<br />
<br /></div>
<pre class="brush:java">import java.awt.*;
import javax.swing.JFrame;
public class TestPantallaCompleta extends JFrame{
public static void main(String[]args){
//Pon aquí los valores que prefieras
DisplayMode dm = new DisplayMode(1024,768,32,DisplayMode.REFRESH_RATE_UNKNOWN);
TestPantallaCompleta test = new TestPantallaCompleta();
test.run(dm);
}
public void run (DisplayMode dm){
setBackground(Color.ORANGE);
setForeground(Color.BLACK);
setFont(new Font("Dialog", Font.PLAIN,48));
PantallaCompleta pc = new PantallaCompleta();
try{
pc.setFullScreen(dm, this);
try{
//ponemos el tiempo que queremos que dure
Thread.sleep(10000);
}catch(InterruptedException ex){}
}finally{//pase lo que pase, se restaura a sus antiguos valores
pc.restoreScreen();
}
}
public void paint(Graphics g){
if (g instanceof Graphics2D){
Graphics2D g2 = (Graphics2D) g;
//difuminamos los bordes del texto
g2.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
//el texto va a aparecer 300px a la derecha y 400px hacia abajo
g.drawString("Aquí va a ir mi juego",300,400);
}
}
</pre>
<div style="text-align: justify;">
<br />
Eso de "antialiasing" que ves al final del código, no es que no dejes a los jugadores tener un alias, sino que sirve para que el texto aparezca como escalonado, como escrito en cuadraditos.<br />
<br />
A continuación te dejo una captura de pantalla para que veas cómo queda con los valores que yo le he asignado.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-w3yH2CsgAVA/UJ5Pvep58kI/AAAAAAAAAH0/S5-Kwrx_KiY/s1600/PantallaCompleta.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="http://1.bp.blogspot.com/-w3yH2CsgAVA/UJ5Pvep58kI/AAAAAAAAAH0/S5-Kwrx_KiY/s640/PantallaCompleta.JPG" width="640" /></a></div>
<br />
<br />
Si quieres más información sobre cómo crear juegos en Java, te recomiendo el libro <i style="font-weight: bold;">Developing Games in Java</i>, de David Brackeen, Bret Barker y Lawrence Vanhelsuwe, editorial New Riders Publishing. El código que te muestro aquí es una versión del que aparece en este libro. No sé si hay traducción en castellano, pero como creo que es muy interesante es seguro que en otras entradas os muestre otros ejemplos sacados de él.<br />
<br />
Además he encontrado unos tutoriales en vídeo en Youtube, que su autor no lo dice, pero yo juraría que están basados en este libro. Están en inglés, pero aunque no lo entiendas, puede que el código que muestra te sea útil. Podéis encontralos en esta<a href="http://www.youtube.com/thenewboston" rel="nofollow" target="_blank"> página</a>.</div>
<div style="text-align: justify;">
</div>
Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com1tag:blogger.com,1999:blog-2330324486466201518.post-65231100742538066762012-11-04T18:00:00.000+01:002012-11-10T22:47:20.199+01:00Drag and Drop: cómo funciona<div style="text-align: justify;">
¡Después de unos cuantos meses de ausencia, por fin he vuelto! No, no me he ido de vacaciones (que más quisiera), sino que el imponderable deber de tener que trabajar para vivir se interpuso entre este blog y yo. ¡Y mira que os pongo anuncios para que clickéis y me libréis de ese problema! Pero, nada, no os dáis por enterados. ;-)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Hablando ahora ya en serio, esta entrada esta dedicada al Drag and Drop. Para los que no sepáis lo que es, os diré que no se trata del nombre de un grupo pop, sino de ese efecto de arrastrar elementos de un lugar a otro, como cuando arrastramos ficheros de una carpeta al escritorio del ordenador.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
En principio, todos los componentes de Swing soportan el Drag and Drop, pero algunos tienen instalada la forma de ejecutarlo por defecto y otros no. Para los primeros, basta con invocar el método setDragEnabled(true) y listo. Para los segundos, hay que escribir el código necesario para adaptarlo a tus necesidades.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Los componentes que tienen un mecanismo de arrastre por defecto son:</div>
<div style="text-align: justify;">
</div>
<ul>
<li>JColorChooser</li>
<li>JEditorPane</li>
<li>JFileChooser</li>
<li>JFormattedTextField</li>
<li>JList</li>
<li>JTable</li>
<li>JTextArea</li>
<li>JTextPane</li>
<li>JTree</li>
</ul>
En cuanto al mecanismo para "dejar caer" los datos que queremos transferir, en estos componentes no hay que hacer nada más:<br />
<div style="text-align: justify;">
</div>
<ul>
<li>JEditorPane</li>
<li>JFormattedTextField</li>
<li>JPasswordField</li>
<li>JTextArea</li>
<li>JTextField</li>
<li>JTextPane</li>
<li>JColorChooser</li>
</ul>
mietras que estos otros necesitan un poco más de código para funcionar:<br />
<div style="text-align: justify;">
</div>
<ul>
<li>JList</li>
<li>JTable</li>
<li>JTree</li>
</ul>
Para los componentes que no tienen un método de trasnferencia de datos por defecto, deberemos usar la clase TransferHandler.<br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A continuación voy a poneros un par de ejemplos, simplificados hasta el extremo, para que veáis el funcionamiento del Drag and Drop en Java. En el primero crearemos dos selectores de color y arrastraremos el color seleccionado en el primero hasta el segundo. <b>Fijaos que no podemos arrastrar desde los cuadraditos pequeños, sino desde la vista previa</b>. Este primer ejemplo es una adaptación del que podéis encontrar en la siguiente <a href="http://www.java2v.com/Tutorial/Java/0240__Swing/DraggingandDroppingColorsAcrossJColorChooserComponents.htm" rel="nofollow" target="_blank"><span style="color: lime;">página</span></a>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
</div>
<pre class="brush:java">import java.awt.BorderLayout;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
public class DobleColor {
public static void main(String args[]) {
JFrame frame = new JFrame("Doble Selector de Color ");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JColorChooser izquierda = new JColorChooser();
izquierda.setDragEnabled(true);
frame.add(izquierda, BorderLayout.WEST);
JColorChooser derecha = new JColorChooser();
derecha.setDragEnabled(true);
frame.add(derecha, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
}
</pre>
<div style="text-align: justify;">
Podéis ver aquí cómo quedaría, tras haber arrastrado el color seleccionado desde el primero hasta el segundo.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-vUwCZozPeXo/UJaVHDfcPyI/AAAAAAAAAHU/qrelccn6Z70/s1600/Doble+Selector+de+Color.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="512" src="http://3.bp.blogspot.com/-vUwCZozPeXo/UJaVHDfcPyI/AAAAAAAAAHU/qrelccn6Z70/s640/Doble+Selector+de+Color.JPG" width="640" /></a></div>
<br />
<br />
<div style="text-align: justify;">
En el siguiente ejemplo, vamos a arrastrar un texto desde una etiqueta o JLabel a un campo de texto o JTextField. Para ello utilizaremos los método setTransferHandler y getTransferHandler, además de crear un evento al presionar con el ratón, para que funcione el gesto de arrastrar.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<pre class="brush:java">import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JFrame;
public class SimpleDnDs extends JFrame{
//Vamos a crear componentes
private JTextField textField;
private JLabel label;
private JPanel panel;
public static void main (String args[]){
SimpleDnDs dnd = new SimpleDnDs();
}
public SimpleDnDs(){ //constructor de SimpleDnDs
JFrame frame = new JFrame("Drag and Drop");
panel = new JPanel();
textField = new JTextField(40);
label = new JLabel("Este es el texto a arrastrar");
//especificamos qué tipo de dato vamos a transferir
label.setTransferHandler(new TransferHandler("text"));
MouseListener ml = new MouseAdapter(){
//creamos el método para transferir
//datos al presionar con el ratón
public void mousePressed(MouseEvent e){
JComponent jc = (JComponent)e.getSource();
TransferHandler th = jc.getTransferHandler();
th.exportAsDrag(jc, e, TransferHandler.COPY);
}
};
label.addMouseListener(ml);
panel.add(label);
panel.add(textField);
frame.add(panel); //añadimos el panel al marco
frame.setSize(600,600); //le ponemos las medidas que queramos
frame.setLayout(new FlowLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
</pre>
<div style="text-align: justify;">
Una vez ejecutado el programa, podréis arrastrar el texto desde la etiqueta al campo de texto. Es por supuesto muy sencillito, sólo para que veáis cómo funciona, y podáis crear vuestros propios programas, jugando con distintos componentes y tipos de datos a transferir.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Para ello, recomiendo a los que sepáis inglés que echéis un ojo al <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html" rel="nofollow" target="_blank">tutorial</a> de Oracle sobre Drag and Drop. Y como siempre, si tenéis dudas o comentarios, ya sabéis cómo. Además, si queréis saber cuándo publico las siguientes entradas sin tener que estar pendientes del blog, os recomiendo que os suscribáis.<br />
<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com7tag:blogger.com,1999:blog-2330324486466201518.post-1489246137611873162012-06-16T20:16:00.000+02:002012-06-16T20:16:54.013+02:00JDBC: Java y las bases de datos<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b>JDBC</b> es el nombre de una librería Java que posee un conjunto de interfaces y clases utilizadas para escribir programas Java que pueden acceder y manipular bases de datos relacionales. Al utilizarla, las aplicaciones escritas en Java pueden ejecutar sentencias SQL, presentar los datos en interfaces amigables para los usuarios y cambiar datos en la base de datos.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">JDBC puede ser utilizada tanto con bases de datos <b>MySQL</b>, como bases de datos <b>Oracle</b> o con <b>Access</b> de Microsoft. Pero para poder utilizar esta librería y acceder a las bases de datos en los programas hay que instalar los drivers correspondientes. Puesto que un driver JDBC es la interfaz que facilita las comuncaciones entre JDBC y la base de datos, es un driver específico de la base de datos. Así pues, hace falta un MySQL JDBC Driver para acceder a una base de datos MySQL, un Oracle JDBC Driver para acceder a una base de datos Oracle, pero para acceder a una base de datos Access, el JDK incluido trae un puente o Bridge JDBC-ODBC. ODBC es una tecnología desarrollada por Microsoft para el acceso a las bases de datos en la plataforma Windows. A su vez, un driver ODBC viene preinstalado en Windows, así que el puente JDBC-ODBC permite el acceso a cualquier base de datos ODBC de un programa Java.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Los drivers de MySQL y Oracle son:</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>MySQL</b>: <b>com.mysql.jdbc.Driver</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>Oracle: oracle.jdbc.driver.OracleDriver</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">que se pueden descargar de las compañías correspondientes. En concreto, el driver de MySQLestá en el archivo jar mysqljdbc.jar. Una vez descargado el driver, hay que añadirlo al classpath, ya sabéis: Equipo>>Propiedades>>Opciones avanzadas>>Variables del entorno...si lo habéis hecho al instalar Java, ya os lo sabéis de memoria.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Y ahora, ¿cómo se usa?. Bueno vamos a ver un ejemplo muy sencillito para que os hagáis una idea. Lo voy a hacer con MySQL, que es la base de datos que uso yo, pero también vale para cualquiera de las otras. Suponed que tenéis una base de datos de un colegio, y en ella una tabla con los datos personales de los estudiantes. Como este blog no es sobre SQL, vamos a hacerlo sin muchas explicaciones: </span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">CREATE DATABASE colegio;</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">USE colegio;</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">CREATE TABLE alumnos(</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> nombre varchar(15),</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> primer_apellido varchar(15),</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> segundo_apellido varchar(15),</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> nacimiento date,</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> teléfono char(10),</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> dirección varchar(20),</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> );</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Y a continuación la pobláis con los datos de alumnos imaginarios. Ahora vamos a crear un programa que se conecte a la base de datos y de como salida solo los nombres y los apellidos de los alumnos.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<pre class="brush:java">import java.sql.*; //no olvidéis esto
public class EjemploJdbc{
public static void main(String[] args)throws SQLException, ClassNotFoundException{ //podemos usar try-catch, pero así el ejemplo es más simple
Class.forName("com.mysql.jdbc.Driver"); //se carga el driver
System.out.println("Driver cargado");
//Ahora vamos a establecer una conexión
Connection conexión = DriverManager.getConnection
("jdbc:mysql://localhost/colegio","usuario","contraseña");
//Hemos puesto la base de datos con la que queremos conectar y el nombre de usuario y contraseña que usamos con ella
System.out.println("Base de datos conectada");
Statement st = conexión.createStatement();
ResultSet resultado = st.executeQuery
("select nombre,primer_apellido,segundo_apellido from alumnos");
//iteramos
while(resultado.next()){
System.out.println(resultado.getString(1)+ "\t"+ resultado.getString(2) + "\t" + resultado.getString(3));
}
conexión.close(); //cerramos la conexión
}
}</pre>
<div style="text-align: justify;">
<br />
<br />
<span style="font-family: Georgia, 'Times New Roman', serif;">La salida serán los nombres de los alumnos que hayáis introducido en la tabla. Ya véis que es muy sencillo. Se pueden usar cualquier sentencia SQL dentro del método executeQuery(String sql). El resultado será adjudicado a ResultSet. </span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;">Por supuesto JDBC es mucho más amplio, y en otra ocasión veremos alguna de sus interfaces y sus clases. Por ahora, espero que esto os haya servido para poder conectar vuestros programas Java a vuestras bases de datos.</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com2tag:blogger.com,1999:blog-2330324486466201518.post-57572294404264208032012-06-09T16:22:00.000+02:002012-06-09T16:24:49.315+02:00Formateo de textos en Java<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Para formatear textos, Java utiliza los métodos <b>format()</b> y <b>printf()</b>, que en realidad tienen las mismas funcionalidades. Por ejemplo, podemos hacer</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> </span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">System.out.printf(%s,%s, "Super","ejemplo");</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">o</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;"> String str = String.format(%s,%s,"Super","Ejemplo");</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">A los que vengáis de C o algún otro lenguaje esto os resultará familiar, ya que es similar a los métodos printf y sprintf. Eso sí, tened en cuenta que Java arroja una excepción si encuentra un String mal formateado.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">A los que veis esto por primera vez y os suena a chino, os lo voy a explicar con más detalle.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Supongamos que tenéis un texto:</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">String s = "El número de visitantes el "+nombredia+" fue de "+numerovisitantes;</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Formateando, lo dejaríamos así:</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">String s = String.format("El número de visitantes el %s fue de %d", nombredia, numerovisitantes);</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">¿Pero que son %s y %d?</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Bueno, eso son carecteres de conversión y los veremos en un momento, ahora sólo os digo que s significa string y d un número entero.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">La clase <b>java.util.Formater</b> es la que proporciona la base para la representación de texto formateado a través de sus métodos</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>format(String format, Object...args);</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> format(Locale l, String format, Object...args);</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">El texto resultante puede ser un String, un StringBuilder, un archivo o cualquier OutputStream.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Las dos versiones del método format() también son utilizadas por las clases <b>java.io.PrintStream</b> y <b>java.io.PrintWriter</b>, que además tienen dos versiones similares del método printf().</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">La clase <b>String</b> tiene un método format(), pero es estático.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">La sintaxis es la siguiente: el primer parámetro del método es el texto y los especificadores de formato, seguido de un array de argumentos.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Los especificadores se escriben en el siguiente orden (entre corchetes los que son opcionales):</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>%[argument_index] [flags] [width] [precision] conversion</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">donde % marca el inicio de un especificador.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">[argument_index] indica cuál de los argumentos se va a utilizar. Se hace con un número seguido de $. Por ejemplo:</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">String str = "Año, mes, día: %3$s-%2$-%1$s";</span></span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> System.out.printf(str, 5, "Febrero", 2012);</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">producirá la salida</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b> Año, mes, día: 2012-Febrero-5</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Los flags o banderas son opcionales, e indican (los coloco entre comillas aquí, pero no las llevarían en el código):</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b> "-": justifica el argumento a la izquierda.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> "#": incluye un radical para enteros y una coma para decimales.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> "+": incluye el signo(+ o -).</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> " ": espacio en los valores positivos.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> "0": se llenan los espacios con ceros en los valores positivos.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> ",": usa un separador de grupo específico según la zona geográfica.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> "(": encierra los números negativos en paréntesis.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b>Width</b> indica el número mínimo de caracteres que tendrá la salida. </span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b>Precision</b> indica el número máximo de dígitos después de la como en un decimal.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">El especificador conversion es obligatorio e indica de qué tipo es el argumento. Los más usados son</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>b: boolean.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> c: carácter Unicode.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> d: número entero.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> f: número decimal</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> s: String.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> t: fecha y hora.</b></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Veamos ahora un par de ejemplos para que lo acabéis de entender.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<pre class="brush.java"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> int in = 1234;
String s = String.format("El número es: %08d", in);
System.out.println(s);
</span>
</pre>
</div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">La salida será: </span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b> 00001234</b></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;">Vemos que se han añadido ceros a la izquierda, porque le hemos dado una anchura de ocho dígitos y queremos que lo que falta lo ocupen ceros.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<pre class="brush.java"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;">public class EjempoFormat{
public static void main(String[] args){
String nombre = args[0];
String apellido = args[1];
String s2 = String.format("Datos:\n%1$-10s\n%2$-10s\n",nombre,apellido);
System.out.println(s2);
}
}</span>
</pre>
<pre class="brush.java"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;">
</span></pre>
</div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">
En este caso la salida serán los argumentos que introduzcamos nosotros alineados a la izquierda. Por ejemplo:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><b>Datos:</b></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><b>Alfonso</b></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><b>López</b></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;">Se pueden hacer por supuesto cosas mucho más complicadas, pero espero que esto al menos os sirva para empezar. :-)</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com0tag:blogger.com,1999:blog-2330324486466201518.post-66143593490264755632012-06-01T18:40:00.000+02:002012-06-01T18:40:16.911+02:00Java Regex<div style="text-align: justify;">
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Vamos a tratar en esta
entrada las expresiones regulares en Java. Será sólo una
aproximación, porque esto de las expresiones regulares,<b> regex</b> para
abreviar, es un lenguaje en sí mismo y da para varios libros. Las
expresiones regulares no se utilizan sólo en Java, si no también en
otros lenguajes de programación, como Pearl o Groovy, y por supuesto
las puedes usar en Word o Writer. Sin embargo, en cada lenguaje
existen ligeras diferencias a la hora de usarlas. Como si no fuera ya
bastante complicado el tema. Lo que sí tienen en común es que se
usan para encontrar y manipular texto.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Una expresión regular
sustituye desde un simple carácter a oraciones enteras que deseas
encontrar en un texto. Evidentemente, si quieres encontrar más de
una palabra, o incluso una palabra larga, no es muy práctico tener
que escribirlas literalmente.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Java tiene dos clases,
dentro del paquete <b>java.util.regex</b>, especializadas en este tipo de
manipulación de texto: <b>Matcher</b> y <b>Pattern</b>. Pattern compila una
expresión regular para crear un patrón. Matcher utiliza dicho
patrón para hallar coincidencias en el texto.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Por ejemplo:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String texto =
“Este es el texto en el que vamos a buscar un patrón”;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String patrónDeTexto
= “.*el.*”;</span><span style="color: #38761d; font-family: Georgia, 'Times New Roman', serif;"> //.* significa cero o más caracteres antes y
después de la palabra.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> Pattern patrón =
Pattern.compile(patrónDeTexto); </span><span style="color: #38761d; font-family: Georgia, 'Times New Roman', serif;">//creamos una instancia de Pattern</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> Matcher match =
patrón.matcher(texto); </span><span style="color: #38761d; font-family: Georgia, 'Times New Roman', serif;">//creamos una instancia de Matcher</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> boolean b =
match.matches();</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;">
System.out.println(“Coincide: “+ b);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Si la expresión
regular sólo la vamos a usar una vez, podemos utilizar el método
<b>matches() </b>con Pattern sin necesidad de una instancia de Matcher,
simplificando lo anterior así:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String texto =
“Este es el texo en el que vamos a buscar un patrón”;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String patrónDeTexto
= “.*el.*”;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> boolean b =
Pattern.matches(patrónDeTexto, texto);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;">
System.out.println(“Coincide: “+b);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;">lo que nos daría la
misma salida que en el caso anterior:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> Coincide: true</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Supongamos ahora que
queremos saber exáctamente cuántas coincidencias hay en el texto de
la palabra “el” y en qué lugar se encuentran. Para ello
utilizaremos los métodos de Matcher <b>find()</b>, <b>start()</b> y <b>end()</b>,
teniendo en cuenta que el índice comienza en cero y que los espacios
en blanco también cuentan como caracteres.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String texto =
“Este es el texto en el que vamos a buscar un patrón”;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String
patrónDeTexto = “el”;</span><span style="color: #38761d; font-family: Georgia, 'Times New Roman', serif;"> //queremos saber cuántas veces aparece
esta palabra.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> Pattern patrón =
Pattern.compile(patrónDeTexto);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> Matcher match =
patrón.matcher(texto);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> int contador = 0;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> while
(match.find()){</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> contador++;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;">
System.out.println(“Coincidencia: “ + contador + “ de ” +
match.start() + “ a ” + matcher.end());</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><span style="color: blue;">}</span>
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><span style="color: blue;"><br /></span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> La salida en este caso
será la siguiente:
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> Coincidencia: 1 de
8 a 10</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> Coincidencia: 2 de
20 a 22</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Otro método
interesante es <b>split()</b>, utilizado para separar el texto en distintas
líneas, de esta manera:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String texto =
“Este es el texto, en el que vamos a buscar, un patrón”);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String
patrónDeTexto = “,”;</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> Pattern patrón =
Pattern.compile(patrónDeTexto);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> String[] split =
patrón.split(texto);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> for(String palabras
: split){</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;">
System.out.println(palabras);</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> }</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> La salida en este caso
es:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> Este es el texto</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> en el que vamos a
buscar</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> un patrón
</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Hasta ahora hemos
visto unos cuantos métodos de las clases Pattern y Matcher, pero
poco sobre las expresiones regulares en sí. Pero como ya hemos
dicho, utilizar expresiones literales suele ser muy inconveniente.
Veamos ahora algunas de las expresiones regulares más utilizadas en
Java.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> . </b> equivale a
cualquier carácter</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> \d</b> equivale a
cualquier dígito</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> \D</b> equivale a
cualquier carácter no dígito</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> \s</b> equivale a un
espacio en blanco</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> \S</b> equivale a
cualquier carácter excepto un espacio en blanco</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> \w</b> equivale a
cualquier letra</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> \W</b> equivale a
cualquier carácter excepto letras</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> [abc]</b> equivale a a,
b o c (o cualquier otro carácter que se indique)</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> [^abc]</b> equivale a
cualquier carácter excepto a, b o c</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> [a-zA-Z]</b> equivale a
cualquier carácter de la a a la z o de la A a la Z, todos inclusive</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> [a-d[m-p]] </b> equivale a
cualquier carácter de la a la d o de la m a la p</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> [a-z&&[def]] </b>
equivale a d, e o f</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> [a-z&&[^bc]]</b>
equivale a cualquier carácter de la a a la z excepto b o c</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> [a-z&&[^m-p]]</b>
equivale a cualquier carácter de la a a la z excepto los que van de
la m a la p</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Además, en java regex
se utilizan <b>cuantificadores</b> para indicar el número de veces que se
repiten los caracteres buscados. Estos cuantificadores se denominan
<b>greedy</b>, <b>reluctant</b> y <b>possessive</b>. Para indicar el cuantificador greedy,
siendo X un carácter cualquiera, se escribe:
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X*</b> para buscar
coincidencias de cero o más X</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X?</b> para buscar
coincidencias de una o ninguna X</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X+</b> para buscar
coincidencias de una o más X</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Para denotar el
cuantificador reluctant, a los signos anteriores se añade ?, de esta
manera:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X*?</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X??</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X+?</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Y para el
cuantificador possessive, el signo +:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X*+</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X?+</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b> X++</b></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> ¿Cómo funcionan
estos cuantificadores? Bueno, el cuantificador greedy “lee” todo
el texto de una vez y luego, de derecha a izquierda, se va
deshaciendo de caracteres y vuelve a leer lo que queda una y otra vez
hasta encontrar una coincidencia. El cuantificador reluctant, en
cambio, empieza leyendo el texto de iquierda a derecha hasta hallar
la coincidencia buscada. El cuantificador possessive lee el texto
entero como el greedy, pero solo una vez, y si no haya una
coincidencia esa vez, no sigue buscando más.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Veamos esto con un
ejemplo. Supongamos que tenemos el siguiente texto “ID usuario
Nombre usuario” y buscamos cero o más coincidencias de la
siguiente expresión regular .io(cualquier carácter seguido de io)</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Greedy: .*io. Leería
el texto entero, que no está seguido de io, e iría “soltando”
caracteres hasta que encontrase ID usuario Nombre usuar, seguido de
los caracteres io que habría soltado y encontraría una
coincidencia:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> ID usuario Nombre
usuario.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Reluctant: .*?io. Iría
leyendo el texto de izquierda a derecha y encontaría dos
coincidencias:</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> ID usuario</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Nombre usuario</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Possessive: .*+io.
Leería todo el texto, pero solo una vez, y claro, como el texto no
está seguido de io, no encontaría ninguna coincidencia.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Como hemos dicho, esto solo es una breve aproximación a las expresiones regulares en Java, pero esperamos que os sirva para ir practicándolas, así como a entender cómo funcionan las clases Pattern y Matcher.</span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
</div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com0tag:blogger.com,1999:blog-2330324486466201518.post-30730010046010793722012-05-19T12:46:00.000+02:002012-05-19T12:46:18.614+02:00Deployment o despliegue y distribución de aplicaciones<br />
<h1 align="CENTER" class="western">
</h1>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Llega un momento, en la vida de todo programador
principiante, en el que éste quiere enseñar a sus amigos/as el
programa tan genial que ha hecho (aunque sólo sea ese en el que sale
por la consola la frase “Hola, mundo”). En ese momento, los
susodichos amigos/as, hermanos/as, primos/as o padres le dirán algo
así como: “Ah, bien. Pero, ¿cada vez que quieras hacer eso tienes
que abrir Eclipse/NetBeans/cmd?. ¿No puedes hacer que funcione
dándole doble clic a un icono?.” Y nuestro pobre programador novel
se queda chafado.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Hoy os vamos a explicar cómo hacer para
desplegar vuestras aplicaciones para poder distribuirlas después, o
para poder iniciarlas desde el escritorio. Lo vamos a hacer a través
de la línea de comandos, porque cada IDE viene con su propio
botoncito para hacer esta tarea, y aquí no podemos cubrirlos todos.
Además, un poco de MS-Dos o Shell nunca viene mal. Si lo necesitáis,
seguro que googleando encontráis un tutorial específico para la IDE
que utilizéis vosotros.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Para empezar, lo primero que hay que hacer es
crear un fichero <b>.jar</b>. Un
fichero .jar no es más que un archivador de java (jar = java
archive) para guardar todos los archivos que necesites para ejecutar
el programa.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Por ejemplo,
supongamos que con tu Bloc de Notas has escrito un programa llamado
miPrograma.java. Al compilarlo, verás que automáticamente Java crea
miPrograma.class. Supongamos también que has escrito otro programa
más complicado que necesita varias clases más y otros archivos de
imágenes para funcionar. A este lo llamaremos miOtroPrograma.java.
Todos estos archivos los hemos guardado en MisProgramas dentro de
nuestro disco duro.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Vamos ahora al
cmd para crear los archivos .jar donde guardar estos programas. Para
no liarnos con Windows o con Linux, voy a poner simplemente los
comandos. Eso sí, recordad que en Windows para ir a algún
directorio es:
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">cd C:\MisProgramas con la barra\</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">y en Linux es:</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">$
/MisProgramas con la barra/</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Al crear un
.jar, Java automáticamente construye un manifiesto MANIFEST.MF donde
pone algunos datos sobre el mismo. Nosotros vamos a cambiar este
manifiesto para señalar cuál es la clase principal, es decir, dónde
está el método main, imprescindible para que todo funcione.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Esto es muy
sencillo de hacer. Simplemente abrimos nuestro editor de texto o bloc
de notas y escribimos:</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">Main-Class: miPrograma</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Podemos añadir
otra línea para que quede bien claro dónde va a estar este
programa, poniendo el nombre del fichero que vamos a crear:</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">Path: .\ficheroUno.jar</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Es
imprescindible que dejéis un espacio después de los dos puntos.
Ahora guardamos este manifiesto con la extensión .txt o .mf en
MisProgramas.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">A continuación,
en cmd, <u>dentro del
directorio MisProgramas</u>,
tecleamos:</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">jar
-cmf manifiesto.mf ficheroUno.jar miPrograma.class</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Y
ya está creado el fichero.Es muy importante que sigamos el orden del
comando, es decir, si la m de manifiesto va antes que la f de
fichero, así es como debemos escribirlos, si no se producirá un
error.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Si
ahora quisiésemos ver el contenido del fichero basta con teclear:</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">jar
tf ficheroUno.jar</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">También
podemos visualizar el proceso si en lugar de teclear <b>-cmf</b>
tecleamos <b>-cvmf</b>.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Pero
, ¿qué ocurre con el otro programa, el que tenía varias clases y
archivos?. Bueno, puedes crear un fichero .jar colocando todos los
archivos uno detrás de otro después de miPrograma.class, pero la
verdad es que eso es muy pesado. Lo más cómodo es manejarse con
paquetes. Tú ya sabes (o deberías) que para crear un paquete basta
que la primera línea de tu clase principal sea algo así:</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">package
miPaquete;</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Ordenadito
que tú eres, has creado el directorio miPaquete y allí has metido
todos los archivos de este paquete. Lo único que tienes que hacer es
añadir el paquete entero al fichero, así:</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">jar
-cmf manifiesto ficheroDos.jar miPaquete</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">Eso
sí, manifiesto, que deberás guardar en el mismo directorio en el
que esté miPaquete, quedaría así:
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">Main-Class:
miPaquete.miOtroPrograma</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">para
evitar el famoso error de que el fichero de la clase principal no se
encuentra o no ha sido cargado.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Ahora puedes ejecutar el programa de varias
maneras:
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> -desde el cmd, si no has modificado el
manifiesto, con
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><b>java -cp ficheroUno.jar miPrograma</b>
</span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">java -cp ficheroDos.jar
miPaquete.miOtroPrograma</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> -desde el cmd, si has
modificado el manifiesto, con</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">java -jar
ficheroUno.jar</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">java -jar
ficheroDos.jar</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> -o simplemente, en
Windows, yendo al fichero .jar que se ha creado en MisProgramas y
<b>cliqueando sobre él dos veces</b> (esto es cierto sólo a partir
de Java 1.5, aunque se puede modificar Windows para que también lo
haga con versiones anteriores, pero, vamos, ya es hora de que
actualices tu Java). También puedes crear un acceso directo en el
escritorio, para lucirte más.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Recuerda además que
puedes ver el contenido de tu fichero con WinZip o WinRar. Este mismo
fichero se ejecutará sin problemas en cualquier ordenador que tenga
instalada la JVM. ¿Y si no?. Bueno, en ese caso hay varias
soluciones.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Se puede crear una
carpeta en la que que se guarde el archivo jar, una carpeta con el
JRE (Java Runtime Environment) y un archivo .bat (o .sh en Unix) que
tenga el siguiente texto:</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;">jre\bin\java.exe
-jar installer.jar</span></b></div>
<div align="JUSTIFY">
<b><span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></b></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><u>Yo no lo he
probado</u>, así que no sé si
funciona. Si alguno lo ha hecho, por favor que nos lo comente.
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">
Otra opción , pensada sobre todo para los usuarios de Windows, son
los programas que convierten los archivos .jar en .exe. Algunos de
estos programas, como JSmooth o launch4j son gratuítos y puedes
configurarlos a tu gusto. Podéis encontrar tutoriales sobre el tema
incluso en YouTube.</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">
En fin, espero que esta entrada os haya servido al menos para poder
poner en vuestro escritorio esa aplicación tan chula que habéis
hecho. :-)</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;">
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /><br />
</span></div>
<div align="JUSTIFY">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
</div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com0tag:blogger.com,1999:blog-2330324486466201518.post-19441054736856983922012-05-12T19:41:00.000+02:002012-05-12T19:41:02.607+02:00Manejo de BufferedReader: convertirlo a ArrayList o Array<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> La entrada de hoy va a ser más breve, por su temática mayormente práctica. La clase <b>BufferedReader</b> es una de las más usadas en java, pero su utilización se aprende más a través de ejemplos que enrollándonos con un montón de teoría.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Aún así, para los que no la conozcáis, os diré que BufferedReader pertenece al paquete<b> <a href="http://docs.oracle.com/javase/7/docs/api/java/io/package-summary.html" target="_blank">java.io</a> </b>y se utiliza para "leer" archivos. Pero no se le puede pasar un archivo directamente como argumento al constructor, por que no lo admite, así que primero hay que crear un <b>FileReader</b>, que admite tanto archivos como Strings, y luego este FileReader será el argumento del constructor del BufferedReader. Si esto os parece muy lioso, veréis como se entiende mejor con un ejemplo.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Supongamos que tenéis un archivo que queréis leer, y no sólo eso, si no que después queréis trabajar con él y para ello necesitáis convertirlo en un ArrayList o un Array, o incluso separarlo en partes. Todo eso lo veremos con el siguiente ejemplo.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Yo he creado un mini-archivo para utilizar aquí, pero vosotros podéis usar alguno vuestro, todo lo amplio que queráis. El mío consiste en unas definiciones de unas palabras gallegas tomadas de un diccionario (no pasa nada si no entendéis gallego, lo importante es que comprendáis el código que viene luego ;) ).</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">lercho, -a: (de lercha<prerrom.*liscola<*lisca<celta *vlisca = vara).adx. 1.Lingoreteiro, insolente. 2.Dise da persoa que fala máis do debido. 3.Indecente. 4.Lacazán, preguiceiro. 5.Dise da persoa que come e bebe demasiado.</span></div>
<div style="text-align: justify;">
<div>
<span style="font-family: Georgia, 'Times New Roman', serif;">leria: (lat.lerias<gr.leros).s.f. 1.Conversa informal(estanche de leria). 2.Chanza, broma (tes moita gana de leria). 3.Conto, enredo, chisme, maraña, lío (déixate de lerias).</span></div>
<div>
<span style="font-family: Georgia, 'Times New Roman', serif;">leriante: (de leria). adx. e s. 1.Lercho. 2.Dise da persoa que é moi bromista ou da que ten moita labia.</span></div>
<div>
<span style="font-family: Georgia, 'Times New Roman', serif;">lerio: (de leria). s.m. 1.Asunto no que hai algunha complicación (andar metido nun lerio). 2.Lío, maraña, enredo (non se decataron do lerio). 3.Caso (o peor do lerio é que entre eles non se entenden). 4.Chisme, cousa sen importancia.</span></div>
<div>
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div>
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div>
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
</div>
<pre class="brush:java">import java.io.*;
import java.util.*;
import java.util.regex.*;
public class Archivos{
public static void main(String[] args){
try{
//El constructor de BufferedReader no admite directamente un archivo
//por eso usamos FileReader
BufferedReader reader = new BufferedReader(new FileReader("voc.txt"));
//Vamos ahora a convertir el reader en un ArrayList.
// Nunca inicializéis String linea = reader.readLine() o dentro de
// while se producirá un bucle infinito (puesto que linea nunca será nul
String linea;
List<String> arlist = new ArrayList<String>();
while((linea=reader.readLine())!= null){
arlist.add(linea);
}
System.out.println(arlist);
//Si ahora quisiésemos convertir ese ArrayList en un Array,
// haremos lo siguiente
String[] s1 = arlist.toArray(new String[arlist.size()]);
//Para separar el texto en dos array distintos
String[] palabras;
String[] definiciones;
for (String st : arlist){
Pattern patrón = Pattern.compile("[(].+$");
palabras = patrón.split(st);
System.out.println(palabras[0]);
}
for (String str : arlist){
Pattern patrón2 = Pattern.compile("[\\w]+:");
definiciones = patrón2.split(str);
System.out.println(definiciones[1]);
}
//Nunca olvidéis cerrar el BufferedReader.
reader.close();
}catch(IOException ioe){
System.out.println("Oh,oh");
}catch(PatternSyntaxException pse){
System.out.println("Oh,oh");
}
}
}
</pre>
<br />
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Como podéis ver, hemos utilizado también el paquete <b><a href="http://docs.oracle.com/javase/7/docs/api/java/util/regex/package-summary.html" target="_blank">java.util.regex</a><span id="goog_2046334832"></span><span id="goog_2046334833"></span><a href="http://www.blogger.com/"></a></b>, que utiliza expresiones regulares para el manejo de texto. Conocer estas expresiones regulares es casi como aprenderse un lenguaje de programación nuevo. Para los que no sepáis nada del tema, podéis echar un ojo al <a href="http://docs.oracle.com/javase/tutorial/essential/regex/" target="_blank">tutorial de Oracle</a>. </span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> En este ejemplo, con el uso de las clases de regex hemos separado por un lado las palabras y por otro sus definiciones.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Espero que esta entrada os haya sido útil.</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com4tag:blogger.com,1999:blog-2330324486466201518.post-12104724569333820812012-05-05T16:08:00.003+02:002012-05-05T16:08:53.588+02:00Redimensionamiento de imágenes en componentes de JFrame<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> En la entrada de esta semana vamos a tratar de cómo añadir imágenes en una interfaz gráfica de usuario o GUI.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Como este blog esta pensado para ayudar a los que empiezan, vamos a partir de cero y crear dicha interfaz. Los que ya seáis expertos podéis saltaros esta parte.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> En Java, la creación de ventanas, botones, campos de texto, etc. se hace a través de las apis de <b>java.awt.</b> y <b>javax.swing</b>. No vamos ahora a ver la jerarquía ni los aspectos teóricos de estas clases, porque es un tema muy extenso, pero os recomiendo que echéis un ojo a los <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/swing/" target="_blank">docs de Oracle</a>.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Yendo a lo práctico, si queréis hacer una ventana hay que crear primero un marco (frame) en el que pondremos un panel (panel) y en él todos los demás objetos que queramos añadir. Un ejemplo muy sencillo sería:</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<pre class="brush:java">import java.awt.*;
import javax.swing.*;
import javax.swing.JFrame;
public class DemosFrame extends JFrame{
//Vamos a crear componentes
private JButton botón = new JButton("Esto es un botón");
private JLabel label = new JLabel("Esto es una etiqueta");
private JTextField textfield = new JTextField("Esto es un campo de texto");
private JTextArea textarea = new JTextArea("Esto es un área de texto");
//Podríamos añadir más cosas, pero como muestra vale.
DemosFrame(){ //constructor de DemosFrame
JPanel panel = new JPanel(); //creamos el panel
//Ahora añadimos todo al panel
panel.add(botón);
panel.add(label);
panel.add(textfield);
panel.add(textarea);
setContentPane(panel); //añadimos el panel al marco
}
public static void main(String[] args){
DemosFrame frame = new DemosFrame(); //creamos el marco
frame.setSize(400,400); //le ponemos las medidas que queramos
frame.setLayout(new FlowLayout()); //colocamos los componentes según la disposición que mejor nos convenga
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //para salir del programa al cerrar la ventana
frame.setLocationRelativeTo(null); //para centrar la ventana en la pantalla
frame.setVisible(true); //¡Nunca hagáis visible el marco antes de añadirle todo lo demás!
}
}</pre>
<br />
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">Recordad que los componentes se colocan en el panel, no en el marco.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Ahora bien, supongamos que ahora queremos añadir una imagen. ¿Cómo lo hacemos? Lo habitual es utilizar <b>ImageIcon</b>, una implementación de la interfaz <b>Icon</b> que nos permite añadir archivos de imágenes con extensiones GIF, JPEG o PNG para colocarlas en botones, etiquetas o paneles.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Suponed que tenéis una imagen que queréis añadir a un botón. La forma de hacerlo es muy sencilla: </span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">ImageIcon icon = new ImageIcon("imagen.gif");</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">si la imagen está en el mismo directorio, o bien</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">ImageIcon icon = new ImageIcon("ruta/imagen.gif");</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">si la imagen está en otro.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;">(Notad que en Unix el path se separa con "/", mientras que en Windows podéis usar "/" o "\\")</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Y a continuación:</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">JButton botón = new JButton(icon);</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><span style="color: blue;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><span style="color: blue;"> </span>Pero si la imagen no la tenéis en vuestro equipo, si no que queréis descargarla de internet, tenéis que hacer lo siguiente:</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">java.net.URL sitio = new URL("http://www.sitio.com/imagen.gif");</span></span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> ImageIcon icon = new ImagenIcon(sitio);</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Y luego añadirlo a donde queráis. Tened en cuenta que lanza una <a href="http://javaparanulos.blogspot.com.es/2011/11/manejo-de-excepciones-en-java.html" target="_blank">MalformedURLException</a> que hay que declarar o manejar.</span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Pero, ¿qué ocurre si la imagen es demasiado grande? Por ejemplo, tenemos una foto y queremos colocarla en un botón, pero no nos cabe porque ocupa toda la pantalla. Bueno, ni Icon ni ImageIcon tienen un método para redimensionar imágenes, pero la clase <b>Image</b> sí, e ImageIcon tiene un <a href="http://javaparanulos.blogspot.com.es/2011/11/constructores-en-java.html" target="_blank">constructor </a>que acepta instancias de Image como parámetros. Así que, esto es lo que haremos: </span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span></div>
<pre class="brush:java">/*Método mostrado por Gregg Bolinger en JavaRanch*/ImageIcon icon = new ImageIcon("miimagen.jpeg");
Image img = icon.getImage(); //convertimos icon en una imagen
Image otraimg = img.getScaledInstance(115,230,java.awt.Image.SCALE_SMOOTH); //creamos una imagen nueva dándole las dimensiones que queramos a la antigua
ImageIcon otroicon = new ImageIcon(otraimg);
JButton botón = new JButton(otroicon);</pre>
<br />
<br />
<div style="text-align: justify;">
<span style="font-family: Georgia, 'Times New Roman', serif;"> Y eso es todo lo que hay que hacer para ajustar el tamaño de la imagen a nuestras necesidades. Fijaos en que el primer número de getScaled() corresponde al ancho y el segundo al alto de la imagen.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Esperamos que os haya sido útil. :-)</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com2tag:blogger.com,1999:blog-2330324486466201518.post-17326078837658085832012-04-20T23:32:00.001+02:002013-09-29T10:25:19.672+02:00Threads II - Synchronized<div style="text-align: justify;">
</div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br />
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">En la <a href="http://javaparanulos.blogspot.com.es/2012/04/threads-i-formas-de-crear-threads.html" target="_blank">entrada anterior </a>hablabamos de los <b>threads</b>, y veíamos las operaciones que podíamos realizar para ordenar el tiempo de ejecución. En esta entrada vamos a tratar de la <b>sincronización</b>, y lo vamos a hacer con un ejemplo ficticio muy sencillito, para que los conceptos queden bien claros.</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Supongamos que tenemos un bonito comercio que dispone de una página web donde se pueden hacer compras on-line. Pongamos que entre las cosas que se pueden comprar están CD´s. Nosotros, mañosos que somos, hemos hecho un programa en el que cada vez que un cliente compra un CD, este se resta a las existencias, y cuando ya no quedan, avisa de la situación:</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
</div>
<pre class="brush:java">//¡Método no sincronizado, va a fallar!
public class CompraCD{
public static void main(String[] args) throws InterruptedException{
Comprador c = new Comprador();
Thread uno = new Thread(c);
Thread dos = new Thread(c);
Thread tres = new Thread(c);
uno.setName("Elena");
dos.setName("Luis");
tres.setName("Alba");
uno.start();
dos.start();
tres.start();
}
static class Comprador implements Runnable{
int cantidad = 100;
public void run(){
while(cantidad > 0){
compra();
}
}
public void compra(){
if(cantidad>0){
System.out.println("Comprador " + Thread.currentThread().getName() + " encargando CD");
/*Vamos a ralentizar un poco el proceso para que se vea más claramente el output*/
try{
Thread.sleep(1000);/
}catch(InterruptedException e){
System.out.println("Oh, oh");
}
cantidad = cantidad – 1; //restamos 1 a las existencias
System.out.println("Comprador " + Thread.currentThread().getName() + " ha comprado. Quedan " + cantidad); //Vemos quién ha comprado y la cantidad de CD´s que quedan
}else{
System.out.println("No hay bastantes CD´s");
}
}
}
}
</pre>
<br />
<br />
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Ahora podéis probar a compilar y ejecutar el programa. ¿Cuál es el output?Ya os lo digo yo: un desastre. Terminaréis con números negativos en las existencias de CD´s y es posible incluso que el número de CD´s no disminuya de forma correcta, si no que haga cosas como 20-18-19. ¿Por qué?, os preguntaréis, si en el programa se especifica claramente que sólo se puede comprar mientras haya existencias. Pues porque puede haber más de una persona comprando a la vez. Suponed que sólo queda un CD y dos personas entran a la vez en la web: a las dos se les va a decir que hay existencias, y las dos van a poder realizar la compra, pero sólo vamos a tener un CD para enviar.</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Vale, en la vida real el proceso no es exactamente así, pero ya dije que esto era sólo un ejemplo para que lo entendiérais. Ahora, lo que necesitamos, es una forma de impedir que dos personas compren a la vez, es decir, que mientras una persona está comprando, otra no pueda iniciar el proceso. Para eso usamos la sincronización. Bastará con añadir esta simple palabra: synchronized en el método de esta manera: </span></span> </div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;"> <span style="color: blue;">public void synchronized compra(){}</span></span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">y a partir de ahí, si un thread lo está ejecutando, los demás no lo podrán usar hasta que el otro termine. Probad ahora a compilar y ejecutar el programa y veréis como ya no vende más CD´s de los que hay.</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Recordad que lo que se sincroniza son los métodos, no las clases. También puede ocurrir que tengamos un método más amplio y no necesitemos sincronizarlo todo, si no que haya partes de él que no importa si varios thread ejecutan a la vez. En ese caso, bastará con que sincronicemos el bloque que nos interesa:</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<br />
<pre class="brush:java">public class CuentaAtras extends Thread{
private int cuenta = 20;
public void contador(){
synchronized(this){
for(int i=0; i<10; i++){
cuenta--;
System.out.println(Thread.currentThread().getName()+": "+cuenta);
}
}
System.out.println("No sincronizado");
}
public void run(){
contador();
}
public static void main (String[] args){
CuentaAtras cd = new CuentaAtras();
Thread t1 = new Thread(cd);
Thread t2 = new Thread(cd);
t1.start();
t2.start();
}
}
</pre>
<br />
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">La salida de este código será la siguiente:</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 19</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 18</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 17</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 16</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 15</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 14</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 13</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 12</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 11</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-1: 10</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 9</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 8</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 7</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 6</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 5</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 4</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 3</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 2</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 1</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Thread-2: 0</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">No sincronizado</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">No sincronizado <span style="color: #38761d;">//Estas dos últimas líneas pueden variar</span></span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Vemos que el primer thread se ejecuta completamente antes de que empiece el segundo, y como cuando empieza el segundo la cuenta atrás ha ido desde el número 19 hasta el 10, él empieza en el 9.</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">La sincronización es como una llave que permite entrar a un thread en un bloque de código, y mientras ese thread tiene la llave, ningún otro thread puede entrar en él. De hecho, todos los objetos en java tienen un </span></span><span style="font-family: Georgia, serif;"><span style="font-size: medium;"><b>lock </b></span></span><span style="font-family: Georgia, serif;"><span style="font-size: medium;">o cerradura, también llamado </span></span><span style="font-family: Georgia, serif;"><span style="font-size: medium;"><b>monitor</b></span></span><span style="font-family: Georgia, serif;"><span style="font-size: medium;">. Pero eso es otra historia.</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<br /></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Esperamos que estas nociones básicas sobre threads y sincronización os hayan sido útiles.</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;"><br />
</span></span></div>
<div align="JUSTIFY" style="margin-bottom: 0pt;">
<span style="font-family: Georgia, serif;"><span style="font-size: medium;">Nos gustaría agradecer especialmente a los amables habitantes de <a href="http://www.javaranch.com/" target="_blank">JavaRanch</a> por su ayuda en la elaboración de esta entrada.</span></span></div>
Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com6tag:blogger.com,1999:blog-2330324486466201518.post-17705422964204116032012-04-14T15:16:00.001+02:002012-04-14T15:30:29.557+02:00Threads I - Formas de crear threads<div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Los <b>threads</b>, llamados en castellano hilos o hebras, son partes del código que se encargan de ejecutar tareas de forma simultánea en varios procesadores o de forma conmutada si se trata de un solo procesador ( aunque en este último caso, siendo las velocidades las que son, parezca que dichas tareas se ejecutan todas a la vez).</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Como este blog esta pensado para novatos, vamos a ir poco a poco y explicar de forma sencilla y con ejemplos cómo se pueden crear threads en un programa.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Hay que tener en cuenta que la tarea que ejecutan estas hebras pueden ser la misma, o bien pueden ser tareas distintas. Por ejemplo, supongamos que queremos hallar simultáneamente el factorial de tres números. En este caso lo haremos extendiendo la <b>clase Thread</b>:</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><pre class="brush:java">public class Factorial extends Thread{
long nf;
Factorial(long n){
nf = n;
}
public static void main (String[] args){
Factorial a = new Factorial(10);
Factorial b = new Factorial(15);
Factorial c = new Factorial(20);
a.setName("a");
b.setName("b");
c.setName("c");
a.start();
b.start();
c.start();
}
public void run(){
long fact = 1;
while(nf>1){
fact *= nf--;
}
System.out.println("El factorial de " + Thread.currentThread().getName() + " es: "+ fact);
}
}</pre><br />
<div style="text-align: justify;"> <span style="font-family: Georgia, 'Times New Roman', serif;">Vemos en este ejemplo que hemos extendido la clase Thread y a continuación hemos creado tres instancias de la subclase creada Factorial, cada una de las cuales ejecuta la misma tarea que las demás, pero sobre distintos números. La clase Thread tiene varios métodos interesantes, como setName() y getName(), para nombrar los distintos hilos (aunque por defecto son numerados a partir del 0) y currentThread() para saber que hilo se está ejecutando en un momento preciso. </span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Pero además, la clase Thread implementa la interfaz Runnable, que sólo contiene un método: <b>run()</b>.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> El método run() es la tarea que queremos realizar; por ello debemos sobreescribirlo con lo que queremos que hagan nuestros threads. Pero fijaos bien, para que una hebra comience a hacer la tarea que queremos,<u><i> nunca, jamás, podemos utilizar run()</i></u>.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">a.run(); </span><span style="color: #38761d;">//<b>¡JAMÁS!</b></span></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><span style="color: #38761d;"><b><br />
</b></span></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Lo que usamos es el método <b>start()</b>, como vemos en el ejemplo:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">a.start(); </span><span style="color: #38761d;">//correcto.</span></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><span style="color: #38761d;"><br />
</span></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Este método es el que se encarga de llamar al método run().</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> La forma que hemos visto en este ejemplo de crear threads es la más sencilla, pero no es la más habitual. ¿Por qué?. Pues para empezar, porque si extiendes la clase Thread, ya no puedes extender ninguna otra clase, y eso limita bastante. Además, lo correcto es extender una clase sólo cuando se quiere un comportamiento más especializado de la misma.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> La forma de crear hebras que nos va a permitir mayor flexibilidad para trabajar es crear una clase que implemente la interfaz Runnable, como hace la clase Thread, y luego pasar las referencias de sus instancias como argumentos a las instancias de Thread.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Lo entenderéis más fácilmente con el siguiente ejemplo:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> </span></div><pre class="brush:java">public class DemoThread{
public static void main(String[] args)throws InterruptedException{
Runnable r1 = new TextoUno(); //creamos una instancia de una clase que implementa Runnable
Runnable r2 = new TextoDos(); //creamos una instancia de otra clase que también implementa Runnable
/*creamos dos instancias de la clase Thread y le asignamos a cada una "tarea" distinta*/
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start(); //t1 comienza su ejecución
t1.join(); //t1 obliga a t2 a esperar hasta que acaba su ejecución
t2.start(); //t2 comienza su ejecución
}
}
class TextoUno implements Runnable{
public void run(){ //sobreescribimos el método run()
System.out.println("Esto es una demostración");
for(int i=0; i<10; i++){
System.out.println("Estamos esperando...");
try{
Thread.sleep(1000); //ralentizamos la ejecución
}catch (InterruptedException e){
System.out.println("¡Madre mía!");
}
}
}
}
class TextoDos implements Runnable{
public void run(){ //sobreescribimos el método run() de forma distinta
System.out.println(Thread.currentThread().getName());
System.out.println("Por fin acabó t1");
}
}</pre><br />
<div style="text-align: justify;"> <span style="font-family: Georgia, 'Times New Roman', serif;"> En este segundo ejemplo tenemos dos hilos, cada uno de los cuales hace una cosa distinta. Pero, atención: <i>el orden en el que nosotros iniciamos los hilos no es necesariamente el orden que ellos van a seguir. </i></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Imaginemos que tenemos dos hilo: t1, que tiene como salida los números del 1 al 10, y t2, que tiene como salida las vocales, e iniciamos primero t1 y luego t2. Puede que nos salgan primero los números y después las vocales, o puede que nos salga cualquier mezcla entre números y vocales. Es más, si volvemos a ejecutar el código, el resultado no tiene porqué ser el mismo. Entonces, ¿cómo hacemos si queremos que los hilos se ejecuten en un orden específico?. Hay varias formas de conseguirlo. La más eficaz es con el método <b>join()</b> que hemos utilizado aquí. Cuando este método es llamado por un hilo le indica a los demás que tienen que esperar a que dicho hilo acabe. En un pr0grama tan sencillo como este, lo hemos aplicado a toda la ejecución, pero en otros más complejos se puede dejar que los hilos comienzan simultáneamente y se entrecrucen, y usarlo en el momento necesario de la ejecución.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Hay otras formas, no tan eficaces, de intentar "manejar los hilos" (mal juego de palabras, ya sé). Puede usarse por ejemplo el método <b>sleep()</b> que pausa la ejecución de un hilo durante unos milisegundos o nanosegundos. Tanto el método sleep() como el método join() lanzan una InterruptedException, que hay que declarar o manejar. Si no entiendes esto, hecha un vistazo a la entrada sobre <span style="color: red;"><a href="http://javaparanulos.blogspot.com.es/2011/11/manejo-de-excepciones-en-java.html" target="_blank">excepciones en java</a>.</span></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> También se pueden establecer prioridades, que pueden o no funcionar como el programador espera. La manera de hacerlo es con el método <b>setPriority( int priority)</b> con valores del 1 al 10. O se pueden usar las constantes <b>Thread.MAX_PRIORITY</b>, <b>Thread.MIN_PRIORITY</b> y <b>Thread.NORM_PRIORITY</b>. Pero esto tampoco es muy fiable y depende mucho del sistema operativo que se use.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> La moraleja de todo esto, es que nunca des por sentado cómo se van a comportar los threads, o que porque tu programa funcione de una manera en un procesador, funcionará igual en todos. Así que asegúrate de que tu programa multihebra no depende de estos factores. </span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Y si esta falta de control te parece irritante, espera a ver nuestra próxima entrada, que trata de la sincronización.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Si deseas más información, puedes consultar el libro de Scott Oaks y Henry Wong, <i>Java Threads</i>, publicado por O´Reilly, o los <span style="color: blue;"><a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/" target="_blank">Tutoriales de Oracle</a>.</span></span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> </span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com0tag:blogger.com,1999:blog-2330324486466201518.post-74991213837341735792012-04-06T17:16:00.000+02:002012-04-06T17:16:18.099+02:00Anotaciones en Java<div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Esta entrada va a ser básicamente teórica, porque hoy vamos a hablar de las anotaciones en Java.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Las anotaciones son una especie de comentarios o metadatos que puedes introducir en tu código, pero que no son en realidad parte del programa. Puedes elegir que sean procesadas durante la compilación o bien durante la ejecución, a través del API de Reflection. La regla de oro a seguir es que el programa debe funcionar igual tanto si le añades como si le quitas las anotaciones.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Las anotaciones se escriben siempre antes del elemento al que anotan, por ejemplo:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;"> @MiAnotación(nombre = "unNombre", valor = "unValor")</span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> public class MiClase{ }</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Si sólo tiene un parámetro, puede escribirse así: </span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">@MiAnotación("unNombre")</span></span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> La forma de definir una anotación es como la de una interfaz con el signo @ delante:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">public @ interface MiAnotación{</span></span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;"> String nombre();</span> <span style="color: #38761d;">//miembros declarados como métodos sin argumentos</span></span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">String valor();</span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> }</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Una vez que has definido una anotación, ya puedes usarla en tu código. Por ejemplo, puedes crear una anotación para especificar los autores y versiones de un determinado programa:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> </span></div><pre class="brush:java">@interface Creación{
String autores();
String fecha();
int versión() default 1;
}
</pre><br />
<div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Y ahora, al inicio del programa:</span></div><br />
<pre class="brush:java">@Creación( //con paréntesis
autores = "Java Para Nulos", //parámentros separados por comas
fecha = "05/04/2012",
versión = 3 //si no se indicase nada, se aplicaría el valor por defecto
)</pre><br />
<div style="text-align: justify;"> <span style="font-family: Georgia, 'Times New Roman', serif;">Hay algunas anotaciones ya predefinidas en el lenguaje y que resultan útiles a la hora de compilar:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>@Override</b> - informa al compilador que el método al que anota está sobreescribiendo un método de la superclase. Si por algún motivo no sobreescribimos bien el método, el compilador genera un error indicando dónde está el fallo.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>@Deprecated</b> - un elemento marcado con esta anotación indica que está en desuso, bien porque es peligroso, bien porque hay otra alternativa mejor. Un elemento así debería ser también comentado utilizando la etiqueta @deprecated(con minúscula). El compilador genera un aviso cuando se utiliza un elemento marcado @Deprecated.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>@SuppressWarnings</b> - indica al compilador que elimine dos tipos de advertencias que generaría de otro modo: </span><br />
<br />
<ul><li><span style="font-family: Georgia, 'Times New Roman', serif;">deprecation: para que no genere una advertencia cuando se utiliza un elemento marcado como @Deprecated.</span></li>
<li><span style="font-family: Georgia, 'Times New Roman', serif;">unchecked: cuando se utiliza código creado antes de la aparición de los genéricos ( y no hablamos de medicamentos aquí).</span></li>
</ul><span style="font-family: Georgia, 'Times New Roman', serif;"> La forma de escribir esta anotación es la siguiente:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> @SuppressWarnings("deprecation")</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> o en caso de que sean los dos tipos:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> @SuppressWarnings({"unchecked", "deprecation"})</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> La anotación @SuppressWarnings debe utilizarse con precaución y aplicándola al mínimo elemento posible. Es decir, si no quieres que el compilador genere una advertencia por utilizar un método en desuso, marca ese método, y no toda la clase, porque podrías eliminar otras advertencias importantes.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Esto nos lleva a las Meta-Anotaciones, o anotaciones de anotaciones. Por ejemplo, si marcamos una anotación con <b>@Target(ElementType.METHOD)</b> estamos indicando que dicha anotación sólo se aplica al método. ElementType es un enum, y los demás valores que tiene son:</span><br />
<br />
<ul><li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>FIELD</b></span></li>
<li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>PARAMETER</b></span></li>
<li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>CONSTRUCTOR</b></span></li>
<li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>LOCAL_VARIABLE</b></span></li>
<li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>ANNOTATION_TYPE</b></span></li>
<li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>PACKAGE</b></span></li>
</ul><span style="font-family: Georgia, 'Times New Roman', serif;"> Además de @Target, tenemos las siguientes meta-anotaciones:</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>@Retention</b> - que indica hasta dónde se mantienen las anotaciones. Hay tres modos posibles:</span><br />
<br />
<ul><li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>Retention(RetentionPolicy.SOURCE)</b>, la anotación sólo se aplica al código fuente, siendo ignorada por el compilador y la JVM.</span></li>
<li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>Retention(RetentionPolicy.CLASS)</b>, el compilador puede ver la anotación y actuar en consecuencia, pero es ignorada por la JVM.</span></li>
<li><span style="font-family: Georgia, 'Times New Roman', serif;"><b>Retention(RetentionPolicy.RUNTIME)</b>, la JVM puede ver la anotación y utilizarla en tiempo de ejecución con Reflection.</span></li>
</ul><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
<b>@Documented</b> - indica que la anotación deberá ser tenida en cuenta por la herramienta javadoc o similares. Estas anotaciones pasan a ser parte del API público de los elementos anotados. Es un tipo de anotación "marcador", es decir, no tiene miembros.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> <b>@Inherited</b> - indica que una anotación es automáticamente heredada. Esta meta-anotación sólo tiene efecto en anotaciones de clase, y sólo se hereda de superclases, no de interfaces.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"> Cualquier duda o comentario que queráis hacer, ya sabéis dónde estamos ; )</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com2tag:blogger.com,1999:blog-2330324486466201518.post-60976163594133921212012-03-24T16:25:00.000+01:002012-03-24T16:25:31.419+01:00Serialización de objetos en Java II<div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> </span> <span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span style="font-size: large;"> </span>En la <a href="http://javaparanulos.blogspot.com.es/2012/03/serializacion-de-objetos-en-java-i.html" target="_blank"><span style="color: purple;">entrada anterior</span></a> vimos la forma de serializar objetos por defecto, es decir, utilizando los métodos <b>writeObject()</b> y <b>readObject() </b> tal cual.</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> Pero, ¿qué ocurre si los métodos así implementados no cubren nuestras necesidades? Por ejemplo, supongamos que tenemos un campo declarado transient pero que aún así necesitamos serializar, o unos datos que sólo queremos en el servidor receptor, y no en el emisor, como por ejemplo la actualización automática de la hora. </span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> Para esto bastará con que escribamos nuestros propios métodos writeObject() y readObject() así:</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> <span style="color: blue;">private void writeObject(ObjectOuputStream os){</span></span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span style="color: blue;"> </span><span style="color: #38761d;"> //aquí el código que necesitemos</span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> private void readObject(ObjectInputStream is){</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span style="color: blue;"> </span><span style="color: #38761d;">//aquí el código que necesitemos</span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> Estos métodos "tuneados" van dentro de la clase que implementa Serializable, y una vez que los llamemos desde el método main() completarán la serialización según nuestras necesidades. Aquí tenéis un ejemplo:</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><pre class="brush:java">import java.io.*;
import java.util.*;
public class TestSer{
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("test.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
Prueba p = new Prueba(358);
os.writeObject(p);
os.close();
FileInputStream fis = new FileInputStream("test.ser");
ObjectInputStream is = new ObjectInputStream(fis);
p = (Prueba) is.readObject();
System.out.println("Datos: " + p.getDatos());
System.out.println("Hora actual: " + p.getHoraActual());
is.close();
}
}
class Prueba implements Serializable{
private static final long seriaVersionUID = 3L; //luego explico esto
private transient int datos; //son transient pero necesitamos serializarlos
private transient Date horaActual;//lo queremos sólo en el servidor receptor
public Prueba(int datos){
this.datos = datos;
this.horaActual = new Date();
}
private void writeObject(ObjectOutputStream os){
try{
os.defaultWriteObject(); //el método por defecto
/*ahora escribimos lo que queremos que haga*/
os.writeInt(datos);
System.out.println("Serialización");
}catch(IOException e){
e.printStackTrace();
}
}
private void readObject(ObjectInputStream is){
try{
is.defaultReadObject();
datos = is.readInt();
horaActual = new Date();
System.out.println("Recuperación");
}catch(IOException e){
e.printStackTrace();
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
public int getDatos(){
return datos;
}
public Date getHoraActual(){
return horaActual;
}
}
</pre><br />
<div style="text-align: justify;"> <span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Voy a explicaros ahora qué es eso de <b>serialVerionUID</b>. Ocurre que normalmente la serialización sucede en una JVM, y la reconstrucción en otra. Pero la JVM le asigna un número de versión, el serialVersionUID, a la clase serializable. Ahora bien, si más adelante se añaden o modifican campos en un objeto ya serializado, ese objeto no se podrá reconstruir porque el número de versión de la clase emisora no coincidirá con el de la clase receptora. Por eso se recomienda escribir el propio número de versión declarando un campo llamado serialVersionUID, que debe ser static, final y de tipo long, preferentemente private.</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> private static final long serialVersionUID = 17L;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> Veamos por último cómo afecta la herencia a la serialización. Ya hemos visto que si una superclase implementa Serializable, entonces todas sus subclases la implementarán también automáticamente. Pero, ¿qué ocurre si una subclase es serializable pero su superclase no lo es?.</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> En la entrada anterior veíamos que las variables serializadas mantenían el valor que tuvieran antes de la serialización al ser recuperadas. Por el contrario, las marcadas como transient reciben el valor por defecto tras la serialización, es decir, null en el caso de referencias a objetos y 0 en el caso de tipos primitivos. Sin embargo, todas las variables heredadas de la superclase serán reconstruidas con los valores que tenían inicialmente asignados, y no los que tenían en el momento de la serialización. Esto ocurre porque el constructor de la superclase, al contrario de lo que pasa con el constructor de la clase serializable, se ejecutará. Veamos un ejemplo:</span></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><pre class="brush:java">import java.io.*;
public class SuperClase{
public static void main(String... args){
Empleado emp = new Empleado(1000, "Reponedor");
System.out.println("Antes de la serialización. "+ emp.categoría + ": " + emp.sueldo +"€");
try{
FileOutputStream fos = new FileOutputStream("archivo.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(emp);
os.close();
}catch(Exception e){ //simplificamos para no alargar el ejemplo
e.printStackTrace();
}
try{
FileInputStream fis = new FileInputStream("archivo.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
emp = (Empleado) ois.readObject();
ois.close();
}catch(Exception e){
e.printStackTrace();
}
System.out.println("Después de la serialización. " + emp.categoría + ": " + emp.sueldo +"€");
}
}
class Empleado extends Empresa implements Serializable{
String categoría;
Empleado(int s, String c){
sueldo = s; //esto se hereda de la superclase
categoría = c;
}
}
class Empresa{ //esta clase no es serializable
int sueldo = 800;
}</pre><br />
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Este programa produce la salida: </span><br />
<b><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Antes de la serialización. Reponedor: 1000€</span></b><br />
<b><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> Después de la serialización. Repondedor: 800€</span></b><br />
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br />
</span><br />
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Como veis, hay que tener cuidado con esto, porque aunque los dos sean sueldos de miseria, no es lo mismo cobrar 1000€ que 800€. : )</span>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com9tag:blogger.com,1999:blog-2330324486466201518.post-59382008611585898432012-03-16T21:07:00.001+01:002012-03-24T16:28:08.756+01:00Serialización de objetos en Java I<div style="text-align: justify;"> <span style="font-family: Georgia, 'Times New Roman', serif;">La <b>serialización</b> consiste en convertir un objeto en una secuencia de bytes para guardarlo en un archivo o enviarlo por la red, y luego reconstruirlo, con los valores que tenía al ser serializado, para su posterior utilización. La serialización es muy utilizada en las bases de datos relacionales, pero tiene también otras aplicaciones.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> En Java, esta capacidad de serialización, es decir, de guardar información sobre un objeto para luego recuperarla, se llama <b>persistencia</b>.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Para que un objeto sea serializable basta con que la clase a la que pertenezca, o una superclase de ésta, implemente la interfaz <b>Serializable</b> o su subinterfaz <b>Externalizable</b>, ambas en el paquete <b>java.io</b>.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Muchas clases en la Java API implementan Serializable: clases de utilidad, como java.util.Date, o todas las clases de componentes de Swing GUI; pero por si acaso, asegúrate siempre, porque si intentas serializar un objeto de una clase que no implementa la interfaz Serializable, se producirá una <b>NotSerializableException</b> al ejecutar el programa.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Implementar Serializable es muy sencillo, porque no tiene métodos. En realidad actúa como un marcador que indica que los objetos de una clase (o de sus subclases) son serializables, de esta manera: </span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;"> class MiClase implements Serializable</span></span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><span style="color: blue;"><br />
</span></span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Ahora bien, para utilizar correctamente Serializable, sin liarla, hay que tener en cuenta algunos detalles.</span><br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Primero, lo que estamos serializando son objetos y sus campos, así que las variables marcadas como static, es decir, que pertenecen a la clase y no al objeto, no pueden ser serializadas.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Segundo, supongamos que queremos serializar un objeto que contiene una referencia a una instancia de una clase que no es serializable. Esto produciría la ya conocida NotSerializableException. Para evitarlo, debemos marcar esa instancia como <b>transient.</b></span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><b> </b>Todos los campos marcados como transient serán ignorados por la JVM en el proceso de serialización.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Veamos todo esto con un ejemplo:</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> <span style="color: blue;">public class MiClase implements Serializable{</span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> private int variable1;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> private static double variable2;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> private transient OtraClase oc = new OtraClase();</span></div><div style="text-align: justify;"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: Georgia, 'Times New Roman', serif;"> class OtraClase{} </span><span style="color: #38761d; font-family: Georgia, 'Times New Roman', serif;">//OtraClase no es serializable</span></div><div style="text-align: justify;"><span style="color: #38761d; font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Cuando un objeto de la clase MiClase sea serializado, sólo su variable "variable1" será serializada. La variable "variable2" no, porque es static y por tanto pertenece a la clase y no al objeto, y la variable oc tampoco porque está marcada transient. Si no añadiéramos el modificador transient tendríamos una NotSerializableException, pero también podemos utilizarlo cuando no nos interese serializar algo.</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Georgia, 'Times New Roman', serif;"> Pasemos a ver ahora un ejemplo práctico de serialización y recuperación de objetos. Vamos a escribir unos datos en un archivo, serializarlos y recuperarlos después.</span></div><br />
<pre class="brush:java">import java.io.*;
public class TestAgenda{
public static void main(String[] args){
Agenda a1 = new Agenda("Ana", "Martínez", "Fernández");
Agenda a2 = new Agenda("Ernesto", "García", "Pérez");
try{
FileOutputStream fs = new FileOutputStream("agenda.ser");//Creamos el archivo
ObjectOutputStream os = new ObjectOutputStream(fs);//Esta clase tiene el método writeObject() que necesitamos
os.writeObject(a1);//El método writeObject() serializa el objeto y lo escribe en el archivo
os.writeObject(a2);
os.close();//Hay que cerrar siempre el archivo
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
try{
FileInputStream fis = new FileInputStream("agenda.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
a1 = (Agenda) ois.readObject();//El método readObject() recupera el objeto
a2 = (Agenda) ois.readObject();
ois.close();
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}catch(ClassNotFoundException e){
e.printStackTrace();
}
System.out.println(a1);
System.out.println(a2);
}
}
class Agenda implements Serializable{
private String nombre;
private String p_Apellido;
private String s_Apellido;
/*getters y setters*/
public String getNombre(){
return nombre;
}
public void setNombre(String nombre){
this.nombre = nombre;
}
public String getP_Apellido(){
return p_Apellido;
}
public void setP_Apellido(String p_Apellido){
this.p_Apellido = p_Apellido;
}
public String getS_Apellido(){
return s_Apellido;
}
public void setS_Apellido(String s_Apellido){
this.s_Apellido = s_Apellido;
}
public Agenda(String nombre, String p_Apellido, String s_Apellido){
super();
this.nombre = nombre;
this.p_Apellido = p_Apellido;
this.s_Apellido = s_Apellido;
}
public String toString(){
return( getNombre() + " " + getP_Apellido() + " " + getS_Apellido());
}
}
</pre><div style="text-align: justify;"> <span style="font-family: Georgia, 'Times New Roman', serif;">Lo visto hasta ahora es la serialización por defecto. En la próxima entrada veremos como implementarla según nuestras necesidades. : )</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com12tag:blogger.com,1999:blog-2330324486466201518.post-47110970001691721732012-03-10T14:07:00.000+01:002012-03-10T14:07:00.854+01:00String, StringBuffer y StringBuilder<div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><b>String</b>, <b>StringBuffer</b> y <b>StringBuilder</b> son de las clases más utilizadas en programación Java, porque representan cadenas de caracteres y es difícil encontrar programas que no usen estas cadenas. En esta entrada vamos a explicar cuáles son las diferencias entre ellas, o más bien entre String y las otras dos, porque entre StringBuffer y StringBuilder sólo existe una diferencia, como veremos luego.</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Comencemos por la clase String. Los objetos de esta clase son inmutables, lo que significa que una vez creados no vas a poder modificarlos. Por ejemplo, si escribes</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">String str = new String("Hola mundo");</span> <span style="color: #38761d;">//que originales que somos</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;">ese <b>"Hola mundo"</b> queda "archivado" con str referenciándolo. Pero entonces, pensarás, si quieres añadirle algo a ese texto, ¿no puedes?. Sí, claro que puedes, pero no estarás modificando ese String, si no creando otro nuevo, por ejemplo</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">str += " y parte del extranjero";</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;">o utilizando el método <b>.concat()</b></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">str = str.concat(" y parte del extranjero");</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;">te daría <b>"Hola mundo y parte del extranjero"</b>, pero str ya no referenciaría a <b>"Hola mundo"</b>, que quedaría "archivado", sin nada que lo referenciase, porque str ahora referenciaría al nuevo String.</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Veamos otro caso:</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">String s1 = new String("abc");</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> String s2 = new String("abc");</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> ¿Cuántos objetos se han creado?. ¿Uno, dos?. En realidad, hay dos objetos de clase String creados por "new", pero un solo literal "abc". Para ahorrar memoria, los literales no se repiten, quedan "archivado" para futuros usos. Así que, aunque s1 y s2 no son iguales, porque son dos objetos distintos, si en lugar de usar new utilizamos sólo literales:</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <b>String s1 = "abc";</b></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><b> String s2 = "abc";</b></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;">en este caso s1 == s2 porque referencian al mismo espacio en la memoria.</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Por último, si hacemos</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">String s1 = "Hola mundo";</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> String s2 = s1;</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> s1 = s1.concat(" y parte del extranjero");</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;">¿a qué se está refiriendo ahora s2?. Pues a <b>"Hola mundo"</b>, porque s2 = s1 significa que los dos "apuntan" (no os riais los de C) a un mismo lugar en la memoria, y el nuevo s1 referencia ahora a otro lugar, con un nuevo String, pero s2 sigue refiriéndose al viejo, inmutable, <b>"Hola mundo"</b>.</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Precisamente para asegurar la inmutabilidad de sus objetos, la clase String está marcada como final: sus métodos no pueden sobreescribirse.</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Llegamos así a la necesidad de las clases StringBuilder y StringBuffer: si tienes que hacer muchas modificaciones en tus objetos String, acabas con un montón de objetos inútiles ocupando espacio en la memoria. En cambio, los objetos de tipo StringBuffer y StringBuilder sí que pueden ser modificados.</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> ¿Cuál es la diferencia entre los dos?. Bueno, los métodos de StringBuffer están sincronizados, y los de StringBuilder no. Eso significa que StringBuilder es más rápido, pero que si trabajas con programación multihebra es mejor que uses StringBuffer. Por lo demás son exactamente iguales y tienen la misma API.</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Veamos su diferencia con la clase String con un ejemplo:</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">String s = "Hola mundo";</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> s.concat(" y parte del extranjero";</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> System.out.println(s);</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> ¿Cuál será la salida?. ¡Pues <b>"Hola mundo"</b>, porque no hemos asignado el nuevo String a s así:</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">s = s.concat(" y parte del extranjero");</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Sin embargo, con StringBuffer: </span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"> StringBuffer sb = new StringBuffer( "Hola mundo");</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"> sb.append(" y parte del extranjero");</span><span style="color: #38761d;">//append hace lo mismo que concat</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">System.out.println("sb: " + sb);</span></span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> La salida es <b>"Hola mundo y parte del extranjero"</b>, porque hemos modificado sb.</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> A continuación os dejamos un programita para mostrar algunos de los usos y métodos de estas clases. Consiste en averiguar si un String es palíndromo o no, es decir, si se puede leer igual hacia delante que hacia atrás. Para simplificarlo, hemos pasado de las tildes, pero podéis modificarlo a vuestro gusto.</span></div><pre class="brush:java">import javax.swing.JOptionPane;
public class Palindromo{
public static void main(String[] args){
String s = JOptionPane.showInputDialog("Introduce una frase o palabra: ");
String output = " ";
s = s.replace(" ",""); //quitamos los espacios en blanco
StringBuffer sb = new StringBuffer(s); //pasamos s como argumento a StringBuffer
sb = sb.reverse(); //invertimos el orden de las letras
if(s.equalsIgnoreCase(sb.toString())){ //comparamos sin importar si hay mayúsculas
output = "Es un Palíndromo";
}else{
output = "No es un Palíndromo";
}
JOptionPane.showMessageDialog(null, output);
}
}</pre><div><span style="font-family: Verdana, sans-serif;"> Si deseáis más información sobre estas clases y sus métodos, podéis acudir a <span style="color: orange;"><a href="http://docs.oracle.com/javase/7/docs/api/" target="_blank"><span style="color: orange;">los docs de Oracle</span></a>. </span></span><br />
<span style="font-family: Verdana, sans-serif;"><span style="color: orange;"> </span>Y como siempre, si tenéis alguna consulta, ya sabéis dónde estamos.; )</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com3tag:blogger.com,1999:blog-2330324486466201518.post-12014068375144976432012-03-03T13:15:00.001+01:002012-03-08T10:22:05.667+01:00Aseveraciones (Assertions) en Java<div style="text-align: justify;"> <span style="font-family: Verdana, sans-serif;"> Hace algunas entradas, estuvimos viendo el <a href="http://javaparanulos.blogspot.com/2011/11/manejo-de-excepciones-en-java.html" target="_blank"><span style="color: orange;">manejo de excepciones</span></a> en Java. Hoy vamos a tratar de un tema relacionado: el uso de <b>assert</b>, o aseveraciones, en Java.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Las aseveraciones te permiten comprobar las presunciones que haces sobre tu código mientras lo estás desarrollando, sin tener que manejar excepciones que tú crees que nunca, nunca, ocurrirán.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> Supongamos que escribes un código según el cual si x>0, sucede una cosa, y si x==0, sucede otra. Podríamos expresarlo así:</span></div><div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><br />
</span></div><pre class="brush:java">if(x>0){
//código
}else{
//más código
}
</pre><span style="font-family: Verdana, sans-serif;"> Tú supones que nunca, jamás de los jamases x<0; pero, ¿y si algo va mal y resulta que x tiene un valor negativo?. En este caso, se ejecutaría la parte de código correspondiente a else, como si x==0, con resultados impredecibles.</span><br />
<span style="font-family: Verdana, sans-serif;"> Para evitarlo, podemos usar una aseveración:</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<pre class="brush:java" style="text-align: justify;">if(x>0)
//código
}else{
assert(x==0);
//Ejecutar este código a menos que x sea negativo
}</pre><br />
<div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;">De esta forma, si tu aseveración es cierta, el código continua ejecutándose normalmente. Pero si resulta ser falsa, se lanza un <b>AssertionError</b> que para el programa. Este AssertionError nunca debe manejarse.</span></div><br />
<span style="font-family: Verdana, sans-serif;"> A pesar de su utilidad durante el proceso de depuración, las aseveraciones no son tan utiliazadas por los desarrolladores como debieran. Por supuesto, esto no significa que debas lanzarte a escribir aseveraciones en tu código a diestro y siniestro. Deben ser usadas sobre todo para comprobar errores de lógica, y siempre en bloques de código sobre los que tengas un control total.</span><br />
<br />
<span style="font-family: Verdana, sans-serif;"> Esto es así porque las aseveraciones pueden ser habilitadas o inhabilitadas durante la ejecución. Si escribes una aseveración en un método público, ese método puede ser utilizado más adelante en condiciones desconocidas para ti. Por este mismo motivo, una aseveración nunca, nunca, nunca, puede afectar al desarrollo de un programa, porque imagínate qué ocurriría si del resultado de una aseveración dependiera una acción, pero quien utiliza el programa tiene inhabilitadas las aseveraciones.</span><br />
<br />
<span style="font-family: Verdana, sans-serif;"> Normalmente, las aseveraciones se habilitan mientras se depura el código, y después se vuelven a inhabilitar, y para el JVM es como si no existiesen. Pero si alguna vez el programa o la aplicación se comportan de forma extraña, pueden volver a habilitarse para ver qué es lo que ocurre.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"> Hay dos tipos de aseveraciones:</span><br />
<ul><li><span style="font-family: Verdana, sans-serif;">assert expresión;</span></li>
<li><span style="font-family: Verdana, sans-serif;">assert expresión1: expresión2;</span></li>
</ul><div><span style="font-family: Verdana, sans-serif;"> La única diferencia es que en el segundo tipo, además de lanzar un AssertionError, puedes añadir una frase que especifique el error. Por ejemplo, en el caso anterior podríamos haber escrito:</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><pre class="brush:java">assert(x==0): "x es negativo";</pre></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;"> Para habilitar o inhabilitar las aseveraciones se utiliza la línea de comandos:</span></div><div><ul><li><span style="font-family: Verdana, sans-serif;">java -ea o java -enableassertions para habilitarlas</span></li>
<li><span style="font-family: Verdana, sans-serif;">java -da o java -disableassertions para inhabilitarlas</span></li>
</ul><div><span style="font-family: Verdana, sans-serif;"> Si no se le añaden argumentos, se aplican a todas las aseveraciones de todas las clases, pero se puede especificar, de forma que sólo afecten a un paquete, a una clase... Por ejemplo:</span></div></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;"> java -ea:com.ejemplo.Test sólo habilita a las de la clase Test del paquete ejemplo.</span></div><div><span style="font-family: Verdana, sans-serif;"> java -ea -da:com.ejemplo.Test habilita a todas excepto a las de la clase Test del paquete ejemplo.</span></div><div><span style="font-family: Verdana, sans-serif;"> java -ea -da:com.ejemplo...habilita a todas excepto a las del paquete ejemplo y sus subpaquetes.</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;"> Por último, una advertencia, assert sólo está disponible a partir de Java 1.4 Si tu versión es más antigua, ya estás tardando en actualizarte.(¿Cómo puedes sobrevivir en la prehistoria?).</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;"> Para más información sobre el tema, podéis ir a <span style="color: orange;"><a href="http://docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html" target="_blank"><span style="color: orange;">docs.oracle.com</span></a> </span>o leer los libros <u>Just Java</u> de Joshua Linden y <u>SCJP Sun Certified Programmer for Java 6</u> de Kathy Sierra y Bert Bates.</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com0tag:blogger.com,1999:blog-2330324486466201518.post-77012061977931476082012-02-11T12:26:00.001+01:002012-03-08T10:21:18.532+01:00Comparable en Java<div style="text-align: justify;"> <span style="font-family: 'Trebuchet MS', sans-serif;"> En la <a href="http://javaparanulos.blogspot.com/2012_02_01_archive.html" target="_blank">entrada anterior</a>, vimos el uso de Comparator en Java. En ésta nos vamos a centrar en el uso de Comparable. Comparable es una interfaz que sólo contiene un método: <b>compareTo</b>, que nos sirve para ordenar los valores según un orden natural, bien sea numérico o alfabético. Si en Comparator debíamos especificar que tipo de comparación queríamos, y proporcionar un <b>comparator</b>, en este caso vemos que eso no es necesario.</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"> Lo veremos más claro con un ejemplo, y para eso cogeremos el mismo de la pasada entrada, donde teníamos tres alumnos con sus respectivas notas. Vamos a ordenarlo primero de forma alfabética. Pero antes de nada, un pequeño inciso para principiantes: el método compareTo devuelve un <b>int</b>, que puede ser 1, -1 o 0; da igual que estés comparando nombres. </span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"> Bien, lo primero que hay que hacer es, por supuesto, implementar la interfaz Comparable, y después sobreescribir el método compareTo, como muestra el ejemplo:</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;">import java.util.*;</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><span style="color: blue;">public class Alumnos2 implements Comparable <Alumnos2>{</span><span style="color: #38761d;">//usamos genéricos </span></span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><span style="color: blue;"> private int nota; </span><span style="color: #38761d;"> </span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> private String nombre;</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><span style="color: blue;"> public Alumnos2(int nota, String nombre){</span><span style="color: #38761d;">//muestra del uso de un constructor</span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> super( );</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> this.nota = nota;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> this.nombre = nombre;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><span style="color: blue;"> public void setNota(int nota){</span><span style="color: #38761d;">//muestra del uso de getters y setters</span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> this.nota = nota;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> public int getNota( ){</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> return nota;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> public void setNombre(String nombre){</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> this.nombre = nombre;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> public String getNombre( ){</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> return nombre;</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><span style="color: blue;"> public String toString( ){</span><span style="color: #38761d;">//adecuamos el resultado de compareTo a nuestras necesidades </span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> return String.format("Nombre:%s, Nota:%s", nombre, nota);</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> public int compareTo(Alumnos2 a){</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> return nombre.compareTo(a.nombre);</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> public static void main(String[ ] args){</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"><span style="color: blue;"> Set <Alumnos2> a = new TreeSet <Alumnos2>( );</span><span style="color: #38761d;">//añadimos los valores</span></span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> a.add(new Alumnos2(8, "Ana"));</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> a.add(new Alumnos2(6, "Xose"));</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> a.add(new Alumnos2(3, "Carlos"));</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> System.out.println(a);</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;">}</span></div><div style="text-align: justify;"><span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"> El resultado sería el siguiente:</span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"> <b>[Nombre:Ana, Nota:8, Nombre:Carlos, Nota:3, Nombre:Xose, Nota:6]</b></span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"> </span></div><div style="text-align: justify;"><span style="font-family: 'Trebuchet MS', sans-serif;"> Fijaos en el uso del método toString( ). Probad a omitirlo y veréis que el resultado cambia a una serie de extraños números: el <a href="http://javaparanulos.blogspot.com/2011/12/hashcode-y-equals.html" target="_blank"><b>hashcode</b></a>.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div><div style="text-align: justify;"><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> Ya tenemos nuestro ejemplo ordenado alfabéticamente. Pero, ¿y si queremos ordenarlo según las notas de cada alumno?. Entonces lo único que tendremos que hacer es cambiar el método compareTo de la siguiente manera: </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> <span style="color: blue;">public int compareTo(Alumnos2 a){</span></span><br />
<span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> return this.nota - a.nota;</span><br />
<span style="color: blue; font-family: 'Trebuchet MS', sans-serif;"> }</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> De esta forma la salida sería:</span><br />
<b><span style="font-family: 'Trebuchet MS', sans-serif;"> [Nombre:Carlos, Nota:3, Nombre:Xose, Nota:6, Nombre:Ana, Nota:8]</span></b><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> Si lo que queremos son las notas de mayor a menor, bastaría con hacer esto: </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> <span style="color: blue;">return a.nota - this.nota;</span></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> El método compareTo debe seguir un contrato, o "reglas", similares a las del método <b><a href="http://javaparanulos.blogspot.com/2011/12/hashcode-y-equals.html" target="_blank">equals( )</a></b>, que son las siguientes: </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> Tomando<b> sgn(expresión) </b>donde sgn devuelve -1, 0 o 1, según el valor de la expresión sea negativo, cero o positivo, y con explicaciones para los que no sean de ciencias</span><br />
<br />
<ul><li><span style="font-family: 'Trebuchet MS', sans-serif;"> sgn(x.compareTo(y)) == -sgn(y.compareTo(x)). Si el primer objeto es menor que el segundo, el segundo debe ser más grande que el primero, y al revés. Y si el primero es igual al segundo, el segundo es igual al primero.</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"> (x.compareTo(y)>0 && y.compareTo(z)>0) implica que x.compareTo(z)>0. Si un objeto es más grande que un segundo objeto, y éste es más grande que un tercero, entonces el primero es más grande que el tercero.</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"> x.compareTo(y) == 0 implica que sgn(x.compareTo(z)) == sgn(y.compareTo(z)). Todos los objetos que son iguales al compararlos deben dar el mismo resultado al compararlos con un tercer objeto.</span></li>
</ul><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> Y esto es todo. Si queréis ampliar conocimientos podéis leer el libro de Joshua Bloch "Effective Java". Y no olvidéis visitar nuestra web <a href="http://www.javaparanulos.com/" target="_blank">Java Para Nulos</a> ; )</span><br />
<br />
</div><div style="text-align: justify;"> </div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com3tag:blogger.com,1999:blog-2330324486466201518.post-39811603326884809152012-02-04T16:26:00.001+01:002012-03-08T10:20:01.562+01:00Comparator en Java<div style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"> A veces en tu programa necesitas comparar varios elementos, por ejemplo para ordenarlos. En Java hay diversas formas de hacer esto, como usando Comparable, que ordena los elementos según su orden natural (de menor a mayor o alfabéticamente) o usando Comparator, en el que tú especificas la forma en la que quieres que sean ordenados.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"> Hoy vamos a ver este último método con un ejemplo muy sencillo. Vamos a usar un array de alumnos y lo vamos a ordenar según sus notas y sus nombres. Podríamos hacerlo con cualquier tipo de colecciones y genéricos, y también simplificarlo para que el código fuese más corto, pero hemos decidido hacerlo así para que podáis ver bien todo el proceso. Notad también que igualmente podríamos haber utilizado Comparable en este código.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"></span><br />
<div style="color: blue;"><span style="font-family: Verdana, sans-serif;">import java.util.*;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;">class Alumnos{</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> private int nota;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> private String nombre;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> public void setNota(int nota){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> this.nota = nota;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> public int getNota( ){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> return this.nota;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> public void setNombre(String nombre){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> this.nombre = nombre;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> public String getNombre( ){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> return this.nombre;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;">}</span></div><span style="font-family: Verdana, sans-serif;"><span style="color: blue;">class ComparaNota implements Comparator{</span><span style="color: #38761d;">/**hay que implementar la interfaz</span><span style="color: #38761d;">Comparator y definir el método </span><span style="color: #38761d;">compare()*/</span></span><br />
<div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> public int compare (Object alum1, Object alum2){</span></div><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> int alum1Nota = ((Alumnos)alum1).getNota( );</span><span style="color: #38761d;">//hacemos un casting</span></span><br />
<div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> int alum2Nota = ((Alumnos)alum2).getNota( );</span></div><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> if(alum1Nota > alum2Nota){</span><span style="color: #38761d;">//ordenamos de mayor a menor</span></span><br />
<div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> return -1;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }else if(alum1Nota < alum2Nota){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> return 1;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }else{</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> return 0;</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;">}</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;">class ComparaNombre implements Comparator{</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> public int compare(Object alum1, Object alum2){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> String alum1Nombre = ((Alumnos) alum1).getNombre( );</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> String alum2Nombre = ((Alumnos) alum2).getNombre( );</span></div><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> return alum1Nombre.compareTo(alum2Nombre);</span><span style="color: #38761d;">/**usamos el método </span><span style="color: #38761d;">compareTo para un orden </span><span style="color: #38761d;">alfabético*/ </span></span><br />
<div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;">}</span></div><span style="font-family: Verdana, sans-serif;"><span style="color: blue;">public class EjemploComparatorJava{</span><span style="color: #38761d;">//creamos el array y le añadimos valores</span></span><br />
<div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> public static void main(String[ ] args){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> Alumnos alumnos[ ] = new Alumnos[3];</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[0] = new Alumnos( );</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[0].setNota(8);</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[0].setNombre("Ana");</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[1] = new Alumnos( );</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[1].setNota(6);</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[1].setNombre("Xose");</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[2] = new Alumnos( );</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[2].setNota(3);</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> alumnos[2].setNombre("Carlos");</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> System.out.println("Alumnos desordenados");</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> for(int i = 0; i<alumnos.length;i++){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> System.out.println("Alumno "+(i+1)+" Nombre: "+alumnos[i].getNombre( )+" Nota: "+alumnos[i].getNota( ));</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> Arrays.sort(alumnos, new ComparaNota( ));</span><span style="color: #38761d;">/**usamos el método sort para ordenar las notas*/</span></span><br />
<div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> System.out.println("Alumnos ordenados por notas");</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> for(int i = 0; i<alumnos.length; i++){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> System.out.println("Alumno "+(i+1)+" Nombre: "+alumnos[i].getNombre( )+" Nota: "+alumnos[i].getNota( ));</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><span style="font-family: Verdana, sans-serif;"><span style="color: blue;"> Arrays.sort(alumnos, new ComparaNombre( ));</span><span style="color: #38761d;">/**ahora ordenamos los </span><span style="color: #38761d;">nombres*/</span></span><br />
<div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> System.out.println("Alumnos ordenados por nombre");</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> for(int i = 0;i<alumnos.length; i++){</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> System.out.println("Alumno "+(i+1)+" Nombre: "+alumnos[i].getNombre( )+" Nota: "+alumnos[i].getNota( ));</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;"> }</span></div><div style="color: blue;"><span style="font-family: Verdana, sans-serif;">}</span></div><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"> La salida será como sigue:</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumnos desordenados</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 1 Nombre: Ana Nota: 8</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 2 Nombre: Xose Nota: 6</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 3 Nombre: Carlos Nota: 3</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumnos ordenados por notas</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 1 Nombre: Ana Nota: 8</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 2 Nombre: Xose Nota: 6</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 3 Nombre: Carlos Nota: 3</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumnos ordenados por nombres</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 1 Nombre: Ana Nota: 8</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 2 Nombre: Carlos Nota: 3</b></span><br />
<span style="font-family: Verdana, sans-serif;"><b>Alumno 3 Nombre: Xose Nota: 6</b></span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"> Si al ordenarlos por notas hubiésemos decidido hacerlo de menor a mayor (basta con cambiar el signo de los unos) el orden hubiese sido Carlos, Xose, Ana.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"> Os animamos a que practiquéis con este código, probando con distintas variantes, para que veáis que es muy sencillo.</span></div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com3tag:blogger.com,1999:blog-2330324486466201518.post-38290535312947098392012-01-21T10:56:00.001+01:002013-11-09T12:19:42.711+01:00Polimorfismo y herencia<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> El polimorfismo es una de las claves de la programación orientada a objetos, y aunque no es muy complicado, hay que tener bien claro el concepto para no liarse.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> En realidad, ya hemos visto el polimorfismo en los métodos en la entrada en que tratamos de <a href="http://javaparanulos.blogspot.com/2011/11/overload-vs-override-en-java.html" target="_blank"><span style="color: magenta;">overloading y overriding</span></a>, pero ahora vamos a verlo relacionado con la herencia.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Será más sencillo con un ejemplo. Supongamos que en un juego tenemos la clase Monstruo:</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;">abstract class Monstruo{</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> public void hacerCosasMonstruosas(){</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> </span><span style="color: #38761d; font-family: Verdana, sans-serif;">//código</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> }</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> public abstract andar(){ }</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> public abstract atacar(){ }</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;">}</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Pero nosotros queremos tener distintos monstruos en el juego, así que extendemos la clase Monstruo con los siguientes "hijos": Vampiro, Momia, Zombie, Hombre-Lobo.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> En Java, las clases hijas tienen los mismos miembros (métodos y datos) que la clase madre que no sean declarados privados. Eso es la herencia.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Lo bueno es que estas clases hijas estarán más especializadas que la clase que extienden. Vampiro, Momia, Zombie y Hombre-Lobo, cada uno implementará su propia versión de los métodos abstractos andar() y atacar(); y en cuanto al método hacerCosasMonstruosas(), lo podrán usar tal cual si les conviene, o bien podran modificarlo si es necesario(overriding). Además, podrán tener sus propios campos si hace falta.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Veamos ahora la forma correcta de usar la herencia. Creemos por ejemplo una instancia de Vampiro:</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">Vampiro v = new Vampiro();</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Supongamos ahora que <u>Monstruo no fuese abstracta</u> y creemos una instancia m de dicha clase. Entonces podemos hacer esto:</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"> m = v;</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Y de esta forma ahora m y v hacen referencia al mismo objeto. </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> También podemos hacer esto otro:</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">Monstruo m = new Vampiro();</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Pero <b>nunca</b> podemos hacer lo siguiente:</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"> Vampiro v = new Monstruo()</span><span style="color: #38761d;">//nunca jamás!!</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: #38761d;"><br />
</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: #38761d;"> </span>La razón es clara: todo vampiro es un monstruo, pero no todo monstruo es un vampiro; así que, podemos decir que un objeto Monstruo m es un vampiro sin problema, pero no podemos decir que un objeto Vampiro v es un monstruo, porque ¿y si ese monstruo resulta ser un zombie?. Aún así, si nos vemos en la necesidad de asignar v a m, podemos hacer un casting:</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">v = (Vampiro)m;</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: blue;"><br />
</span></span></div>
<div style="text-align: justify;">
<span style="color: red; font-family: Verdana, sans-serif;"> </span><span style="font-family: Verdana, sans-serif;">De esta forma, el programa compila y la conversión se comprueba durante la ejecución. Si el casting no es correcto, se produce una <a href="http://javaparanulos.blogspot.com/2011/11/manejo-de-excepciones-en-java.html" target="_blank"><span style="color: magenta;">ClassCastException</span></a>. </span><span style="font-family: Verdana, sans-serif;">Pero aún hay más.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Imaginemos ahora que en lugar de la clase Monstruo tenemos la inerfaz Monstruoso. En este caso, m puede referenciar (puede que no exista el verbo referenciar, pero es muy útil) a cualquier objeto de cualquier clase que implemente dicha interfaz. Un ejemplo típico de esto lo vemos en:</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">List miLista = new ArrayList();</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: blue;"><br />
</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Volvamos ahora al método hacerCosasMonstruosas(). Vemos que en la clase Monstruo tiene un código, pero queremos que en la clase Vampiro sea más especializado, y le añadimos cosas propias de un vampiro, como chupar sangre. Si ahora escribimos lo siguiente: </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"> Monstruo m = new Vampiro();</span></span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> m.hacerCosasMonstruosas{</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> </span><span style="color: #38761d; font-family: Verdana, sans-serif;">//código</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> }</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> ¿Qué método será el utilizado, hacerCosasMonstruosas() de la clase Monstruo, o el nuevo y modificado de la clase Vampiro?.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> La respuesta es que para el compilador, un Vampiro es un Monstruo, que tiene el método hacerCosasMonstruosas(), pero en tiempo de ejecución la JVM sabe lo que realmente es m (un vampiro) así que utilizará la versión del método de la clase Vampiro.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Pero hay que ser cuidadosos con esto, porque supongamos que a la clase Vampiro le añadimos un método que no existe en la clase Monstruo, como por ejemplo volar(). ¿Qué ocurrirá si hacemos esto?</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;">Monstruo m = new Vampiro();</span></span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> m.volar(){</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> </span><span style="color: #38761d; font-family: Verdana, sans-serif;">//código</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> }</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Lo que pasará es que esto no funcionará de ninguna manera. Da igual que tú sepas que m es un vampiro, a todos los efectos, m para el compilador es de la clase Monstruo, y la clase Monstruo no tiene el método volar().</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Y aquí está la clave del polimorfismo, porque vemos que m es en realidad varias cosas: es un vampiro, es un monstruo y, por supuesto, es un objeto.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Si utilizamos m como referencia de la clase Vampiro</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"> Vampiro m = new Vampiro();</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: blue;"><br />
</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">podemos usar todos los métodos de dicha clase. Pero si escribimos</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"> Monstruo m = new Vampiro();</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: blue;"><br />
</span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">m podrá usar la versión de los métodos de la clase Vampiro que tenga la clase Monstruo, pero no un método que no exista en dicha clase, aunque sí en la clase Vampiro.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Por supuesto, podemos usar un casting, como ya vimos:</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"> Monstruo m = new Vampiro();</span></span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> Vampiro v = (Vampiro)m;</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"> v.volar();</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> Espero que esta entrada haya ayudado a comprender el polimorfismo.</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="color: blue; font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"> </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br />
</span></div>
Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com2tag:blogger.com,1999:blog-2330324486466201518.post-87456954573387752162012-01-14T16:17:00.001+01:002012-03-08T10:17:42.077+01:00Clases anidadas<div style="text-align: justify;"> En Java, cuando una clase se complica demasiado, o cuando necesita métodos de otra clase, a veces es conveniente utilizar clases dentro de otras clases, o dentro de interfaces, antes que escribirlas varias páginas más allá en el código. Estas clases se llaman <b>clases anidadas </b>y pueden ser de dos tipos:<br />
<ul><li>Estáticas</li>
<li>Internas</li>
</ul> A su vez, las clases internas pueden ser:</div><div style="text-align: justify;"><ul><li>Miembro</li>
<li>Locales</li>
<li>Anónimas</li>
</ul> Vamos a ver con más detalle estas clases, comenzando por las estáticas.</div><div style="text-align: justify;"> Las <b>clases anidadas estáticas</b> son muy sencillas de declarar:</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><span style="color: blue;"> class Externa{</span></div><div style="text-align: justify;"><span style="color: blue;"> static class AnidEstatic{</span></div><div style="text-align: justify;"><span style="color: blue;"> </span><span style="color: #38761d;">//código</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> Una clase anidada estática puede acceder directamente a los métodos y atributos estáticos de la en la que está inmersa, incluido los privados, pero no a los no estáticos (es lo mismo que ocurre con los métodos estáticos). Para acceder a estos necesita hacerlo a través de una instancia de la clase:</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><span style="color: blue;"> class Externa{</span></div><div style="text-align: justify;"><span style="color: blue;"> int i;</span></div><div style="text-align: justify;"><span style="color: blue;"> static class AnidEstatic{</span></div><div style="text-align: justify;"><span style="color: blue;"> Externa e = new Externa( );</span></div><div style="text-align: justify;"><span style="color: blue;"> {</span></div><div style="text-align: justify;"><span style="color: blue;"> e.i = 8; </span><span style="color: #38761d;">//acceso a un miembro variable a través de una instancia de la clase externa</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> El nombre completo de una clase estática anidada incluye el de la clase externa, así que para crear una instancia de esta clase desde fuera de la clase contenedora, tendríamos que crear escribir lo siguiente:</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> <span style="color: blue;">Externa.AnidEstatic ae = new Externa.AnidEstatic( );</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> Pasemos ahora a las clases internas, comenzando por las del tipo miembro. Una <b>clase interna miembro</b> se llama así porque es un miembro más de la clase que la contiene y tiene por lo tanto acceso a cualquier otro miembro, incluso los privados. La clase externa debe declarar una instancia de la clase interna antes de poder invocar sus métodos o utilizar sus atributos.</div><div style="text-align: justify;"> Para declarar una clase interna miembro, hacemos exactamente lo mismo que con una clase anidada estática, solo que sin el static delante:</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> <span style="color: blue;">class Externa{</span></div><div style="text-align: justify;"><span style="color: blue;"> class InMi{</span></div><div style="text-align: justify;"><span style="color: blue;"> </span><span style="color: #38761d;"> //código</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> Al compilar una clase interna miembro, se crean dos archivos distintos:</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> <span style="color: blue;">Externa.class</span></div><div style="text-align: justify;"><span style="color: blue;"> Externa$InMi.class</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> Al contrario que la clase interna miembro, una <b>clase interna local </b>no es un miembro de la clase externa. Es declarada dentro de un bloque, normalmente un método, y no es accesible fuera del mismo, pero se puede crear un objeto de ella y utilizarlo como referencia.</div><div style="text-align: justify;"> </div><div style="text-align: justify;"> <span style="color: blue;">void método( ){</span></div><div style="text-align: justify;"><span style="color: blue;"> class InLo{</span></div><div style="text-align: justify;"><span style="color: blue;"> </span><span style="color: #38761d;"> //código</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> InLo il = new InLo( );</span></div><div style="text-align: justify;"><span style="color: blue;"> nuevoMétodo(il);</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"><span style="color: red;"> </span>Una clase interna local no puede utilizar las variables locales del método en el que está alojada, a no ser que estén marcadas como <b>final</b>, es decir, que no puedan cambiar, ya que la vida de una instancia de la clase interna puede ser mayor que la del método en la que dicha clase fue creada y las variables locales solo pueden vivir mientras viva su método.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> Veamos finalmente las <b>clases internas anónimas</b>, así llamadas porque son declaradas sin ningún nombre de clase.</div><div style="text-align: justify;"> Las clases anónimas pueden ser declaradas dentro de un método e incluso dentro del argumento de un método. Esto puede hacerse porque se declaran e instancian en una única expresión.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><span style="color: blue;"> class Ejemplo{</span></div><div style="text-align: justify;"><span style="color: blue;"> public void ej( ){</span></div><div style="text-align: justify;"><span style="color: blue;"> System.out.println("clase Ejemplo");</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> class Externa{</span></div><div style="text-align: justify;"><span style="color: blue;"> Ejemplo ej = new Ejemplo( ){ </span><span style="color: #38761d;">//esto no es una referencia a una instancia de Ejemplo, sino una referencia </span></div><div style="text-align: justify;"><span style="color: #38761d;"> //a una subclase de Ejemplo (anónima)</span></div><div style="text-align: justify;"><span style="color: blue;"> public void ej( ){</span></div><div style="text-align: justify;"><span style="color: blue;"> System.out.println("clase Ejemplo anónima");</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }; </span><span style="color: #38761d;">//¡acaba con un punto y coma!</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> Las clases anónimas son tratadas por el compilador como si fuesen clases locales internas, por lo tanto, sólo pueden acceder a las variables del método en el que están inmersas si éstas están marcadas como final.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com4tag:blogger.com,1999:blog-2330324486466201518.post-23247584822813266552011-12-31T13:13:00.001+01:002013-11-08T19:16:03.921+01:00Colecciones<div style="text-align: justify;">
Cuando en un lenguaje de programación es necesario tratar con un conjunto de datos, como por ejemplo el número de ventas realizadas, o el stock de un almacén, se emplean colecciones. En Java, las colecciones utilizan el marco de trabajo <b>Java Collections Framework</b>. Dentro de este marco, existen una serie de interfaces y clases diseñadas para tratar específicamente con conjuntos de datos. Si se te escapa el concepto de interfaz, puedes consultar la <a href="http://javaparanulos.blogspot.com/2011/12/interfaces.html" target="_blank"><span style="color: red;">entrada correspondiente</span></a>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Este marco esta ordenado de forma jerárquica. Primero está la interfaz <b>Collection</b> (no confundir con la clase Collections, en plural) a la que extienden las interfaces <b>Set</b>, <b>List </b>y <b>Queue</b>. A su vez, de estas interfaces parten otras interfaces y clases que tratan los datos de forma diferente según las necesidades de los mismos.</div>
<div style="text-align: justify;">
Por otro lado tenemos la interfaz <b>Map</b>. Map forma parte del Java Collection Framework pero no tiene nada que ver con Collection. Más tarde volveremos con esta interfaz.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Vayamos por ahora con Collection. Una colección es simplemente un grupo de objetos a los que llamamos elementos. Hay que tener en cuenta que las colecciones usan <b>Genéricos</b>, es decir, hay que declarar qué tipo de elementos los componen. Así, para declarar la interfaz Collection haríamos lo siguiente:</div>
<div style="text-align: center;">
<span style="color: blue;"><span style="background-color: white;">public interface Collection<E></span></span></div>
<div style="text-align: justify;">
<span style="background-color: white;">siendo E el nombre de los objetos de que está formada la colección. Por ejemplo, Collection<String>, o Collection<Integer>.</span></div>
<div style="text-align: justify;">
<span style="background-color: white;"><br />
</span></div>
<div style="text-align: justify;">
<span style="background-color: white;"> Collection se usa cuando no hay que ser muy específico sobre cómo tratar los datos, y nos llega con los métodos que tiene esta interfaz. Cuando esto no es suficiente, usamos las interfaces que extienden Collection:</span></div>
<div style="text-align: justify;">
</div>
<ul>
<li style="text-align: justify;"><b>Set</b>: es una colección que no puede contener elementos duplicados, como entradas de cine o nombres de clientes. Estos elementos pueden estar ordenados o no. La extiende la interfaz <b>SortedSet</b>, que tiene sus elementos ordenados, y la implementan tres clases</li>
</ul>
<div>
<b>-HashSet</b>: los elementos no están ordenados.</div>
<div>
<b> -TreeSet</b>: los elementos están ordenados según un orden natural (de menor a mayor, lexicográficamente...) o según las reglas de comparación que provea el programador.</div>
<div>
-<b>LinkedHashSet</b>: los elementos están colocados por el orden en que son insertados.</div>
<div>
<ul>
<li><b>List</b>: es una colección ordenada y que permite duplicados, por ejemplo, los libros vendidos en una semana. <b>ArrayList</b>, <b>Vector</b> y <b>LinkedList</b> son las tres clases que implementan List. Las tres tienen sus elementos ordenados según su índice.</li>
<li><b>Queue</b>: es una colección que sirve para mantener los elementos antes de procesarlos. Normalmente, pero no siempre, los elementos están ordenados según el sistema <b>FIFO</b> (first-in-first-out), es decir, el primero en entrar es el primero en salir. <b>PriorityQueue</b> es una clase que implementa Queue y que ordena los elementos según su orden de prioridad.</li>
</ul>
</div>
<div>
Volvamos ahora con la interfaz <b>Map</b>. Map es utilizado cuando tenemos un conjunto de valores y a cada uno de ellos le asignamos una clave. Por ejemplo, el nombre y el DNI, o el nombre de usuario y la contraseña. Un Map no puede contener claves duplicadas y cada clave referencia a un sólo valor (existen los multimaps, cuyas claves pueden referenciar a varios, pero ése es otro tema). <b>Hashtable</b>, <b>TreeMap</b> y <b>HashMap </b>son tres clases que implementan Map. De ellas, sólo TreeMap está ordenada según un orden natural o por las reglas de comparación dadas. Map también tiene una interfaz que la extiende: <b>SortedMap</b> (en realidad, TreeMap implementa NavigableMap, que extiende SortedMap, que extiende Map).</div>
<div>
<br /></div>
<div>
Hay por último dos clases, <b>Arrays</b> y <b>Collections</b>, que extienden la clase Object, y que contienen un grupo de métodos útiles para usar con las colecciones. Puedes encontrar todos los métodos usados en estas clases e interfaces en los <a href="http://docs.oracle.com/javase/7/docs/api/" target="_blank"><span style="color: red;">docs de Oracle</span></a>.</div>
<div>
<br /></div>
<div>
</div>
<br />
<div style="text-align: justify;">
<br /></div>
Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com5tag:blogger.com,1999:blog-2330324486466201518.post-10641223910582278192011-12-24T14:21:00.001+01:002012-03-08T10:15:02.322+01:00Novedades en Java 7<div style="text-align: justify;"> Acabo de leer un panfleto escrito por <b>Madhusudhan Konda</b> y publicado por <b>O´Reilly</b> sobre algunas de las novedades en Java 7 y he pensado que estaría bien hacer un resumen para aquellos que no lo conozcáis. Todos los ejemplos que aparecen a continuación son parte del escrito de Konda. Obviamente, no se tratan aquí todas las novedades que hay en Java 7, pero sí algunas de las que serán más útiles a los desarrolladores.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> Konda empieza tratando de las mejoras del lenguaje que se solicitaron a través del <b>Project Coin</b>. Una de las mejoras que se reclamaban en este proyecto era sobre el uso de Genéricos. Un ejemplo del uso de Genéricos hasta Java 7 sería como sigue:</div><div style="text-align: justify;"><span style="color: blue;"> Map<String, List<Trade>> trades = new TreeMap<String, List<Trade>>( );</span></div><div style="text-align: justify;"> Esto resulta un poco lioso, porque hay que declarar los tipos a ambos lados. Observad ahora como quedaría usando Java 7:</div><div style="text-align: justify;"> <span style="color: blue;"> Map<String, List<Trade>> trades = new TreeMap<>( );</span></div><div style="text-align: justify;"> Mucho mejor, ¿verdad?. Ya no hay que declarar los tipos a la derecha, porque el compilador infiere de qué tipos se trata viendo los que hay a la izquierda. Incluso sería legal omitir el operador de Genéricos (diamond operator), así:</div><div style="text-align: justify;"> <span style="color: blue;"> trades = new TreeMap( );</span></div><div style="text-align: justify;">pero el compilador lanzaría advertencias de seguridad.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> Otra de las peticiones que se hicieron en el proyecto Coin fue el poder usar strings en sentencias Switch. Hasta ahora, las sentencias Switch usaban o bien tipos primitivos o bien tipos enumerados. Con Java 7 se pueden usar también strings, que antes tendrían que ir en una serie de if-else como estos:</div><div style="text-align: justify;"> <span style="color: blue;"> private void processTrade(Trade t){</span></div><div style="text-align: justify;"><span style="color: blue;"> String status = t.getStatus( );</span></div><div style="text-align: justify;"><span style="color: blue;"> if(status.equalsIgnoreCase(NEW)){</span></div><div style="text-align: justify;"><span style="color: blue;"> newTrade(t);</span></div><div style="text-align: justify;"><span style="color: blue;"> }else if(status.equalsIgnoreCase(EXECUTE)){</span></div><div style="text-align: justify;"><span style="color: blue;"> executeTrade(t);</span></div><div style="text-align: justify;"> <span style="color: blue;"> }else if(status.equalsIgnoreCase(PENDING)){</span></div><div style="text-align: justify;"><span style="color: blue;"> pendingTrade(t);</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"> Comparadlo ahora en como queda al poder usar una sentencia Switch:</div><div style="text-align: justify;"><span style="color: blue;"> public void processTrade(Trade t){</span></div><div style="text-align: justify;"><span style="color: blue;"> String status = t.getStatus( );</span></div><div style="text-align: justify;"><span style="color: blue;"> switch (status){</span></div><div style="text-align: justify;"><span style="color: blue;"> case NEW : newTrade(t);</span></div><div style="text-align: justify;"><span style="color: blue;"> break;</span></div><div style="text-align: justify;"><span style="color: blue;"> case EXECUTE : executeTrade(t);</span></div><div style="text-align: justify;"><span style="color: blue;"> break;</span></div><div style="text-align: justify;"><span style="color: blue;"> case PENDING : pendingTrade(t);</span></div><div style="text-align: justify;"><span style="color: blue;"> break; </span></div><div style="text-align: justify;"><span style="color: blue;"> default : break;</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> Konda habla a continuación del manejo automático de recursos tales como Files, Input/OutputStreams, etc., que los desarrolladores tienen que cerrar manualmente, pero que ahora Java 7 puede realizar de forma automática. Hasta ahora el proceso era el siguiente:</div><div style="text-align: justify;"> <span style="color: blue;"> public void oldTry( ){</span></div><div style="text-align: justify;"><span style="color: blue;"> try{</span></div><div style="text-align: justify;"><span style="color: blue;"> fos = new FileOutputStream("movies.txt");</span></div><div style="text-align: justify;"><span style="color: blue;"> dos = new DataOutputStream(fos);</span></div><div style="text-align: justify;"><span style="color: blue;"> dos.writeUTF("Java 7 Block Buster");</span></div><div style="text-align: justify;"><span style="color: blue;"> }catch (IOException e){</span></div><div style="text-align: justify;"><span style="color: blue;"> e.printStackTrace( );</span></div><div style="text-align: justify;"><span style="color: blue;"> }finally{</span></div><div style="text-align: justify;"><span style="color: blue;"> try{</span></div><div style="text-align: justify;"><span style="color: blue;"> fos.close( );</span></div><div style="text-align: justify;"><span style="color: blue;"> dos.close( );</span></div><div style="text-align: justify;"><span style="color: blue;"> }catch (IOException e){</span></div><div style="text-align: justify;"><span style="color: blue;"> //maneja la excepción</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"> Y así es como se haría con Java 7:</div><div style="text-align: justify;"> <span style="color: blue;">public void newTry( ){</span></div><div style="text-align: justify;"><span style="color: blue;"> try(FileOutputStream fos = new FileOutputStream("movies.txt");</span></div><div style="text-align: justify;"><span style="color: blue;"> DataOutputStream dos = new DataOuputStream(fos))</span></div><div style="text-align: justify;"><span style="color: blue;"> {</span></div><div style="text-align: justify;"><span style="color: blue;"> dos.writeUTF("Java 7 Block Buster");</span></div><div style="text-align: justify;"><span style="color: blue;"> }catch (IOException e){</span></div><div style="text-align: justify;"><span style="color: blue;"> //maneja la excepción</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"> Eso sí, para que esto funcione, los recursos que queremos que se cierren automáticamente tienen que implementar la interfaz <span style="color: blue;">java.lang.AutoCloseable. </span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> Otra de las novedades introducidas en Java 7 es el uso de la barra baja para separar números literales y que sea más fácil leerlos. Por ejemplo, si hasta ahora un millón se escribía así:</div><div style="text-align: justify;"> <span style="color: blue;">1000000</span></div><div style="text-align: justify;">ahora lo escribiremos de esta forma:</div><div style="text-align: justify;"> <span style="color: blue;">1_000_000</span></div><div style="text-align: justify;"> También se introducen los literales binarios, con lo que ya no hay que convertirlos a hexadecimales y nos ahorramos un trabajo.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> Se ha mejorado también el manejo de excepciones múltiples, que ahora se pueden atrapar usando un único bloque. Hasta ahora, si tenías un método con, por ejemplo, tres excepciones, tenías que atraparlas de forma individual. Con Java 7 se puede hacer lo siguiente:</div><div style="text-align: justify;"> <span style="color: blue;">public void newMultiCatch( ){</span></div><div style="text-align: justify;"><span style="color: blue;"> try{</span></div><div style="text-align: justify;"><span style="color: blue;"> methodThatThrowsThreeExceptions( );</span></div><div style="text-align: justify;"><span style="color: blue;"> }catch(ExceptionOne | ExceptionTwo | ExceptionThree e){</span></div><div style="text-align: justify;"><span style="color: blue;"> //maneja las excepciones</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"> Sin embargo, si tienes excepciones que pertenecen a distintos tipos que deben manejarse de distinta manera, se puede hacer lo siguiente: </div><div style="text-align: justify;"> <span style="color: blue;">public void newMultiMultiCatch( ){</span></div><div style="text-align: justify;"><span style="color: blue;"> try{</span></div><div style="text-align: justify;"><span style="color: blue;"> methodThatThrowsThreeExceptions( );</span></div><div style="text-align: justify;"><span style="color: blue;"> }catch (ExceptionOne e){</span></div><div style="text-align: justify;"><span style="color: blue;"> //maneja ExceptionOne</span></div><div style="text-align: justify;"><span style="color: blue;"> }catch (ExceptionTwo | ExceptionThree e){</span></div><div style="text-align: justify;"><span style="color: blue;"> //maneja ExceptionTwo y ExceptionThree</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"> }</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"> Java 7 tiene también una nueva API, <b>NIO 2.0</b>, que proporciona mejoras a la hora de trabajar con Java IO. El nuevo paquete<b> java.nio.file</b> viene con nuevas clases e interfaces como <b>Path</b>, <b>Paths</b>, <b>FileSystem</b>, <b>FileSystems</b> y otras. Path, por ejemplo, es el equivalente mejorado de java.io.File. Lo mejor para comprobar como funciona NIO 2.0 es ir a los <a href="http://docs.oracle.com/javase/7/docs/api/" target="_blank">docs</a> de Oracle y ver allí cómo funcionan estas nuevas clases y métodos.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> Otras de las mejoras está relacionada con la multitarea, para lo que se han creado las nuevas clases <b>ForkJoinPool</b> y <b>ForkJoinTask.</b></div><div style="text-align: justify;"><b><br />
</b></div><div style="text-align: justify;"><b> </b>Por último, hay que mencionar la creación de otro nuevo paquete, <b>java.lang.invoke</b>, que permite que la JVM soporte mucho mejor la utilización de lenguajes dinámicos tales como Phyton, Ruby y Clojure. Algunas de las nuevas clases que incorpora este paquete son MethodHandle y CallSite.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> Os recuerdo que este trabajo y los ejemplos aquí expuestos son obra de Madhusudhan Konda, que lo ha publicado en O´Reilly. Si queréis leerlo completo, yo me he descargado una versión gratuita a través de Amazon, y supongo que O´Reilly también ofrecerá esta posibilidad. ; )</div><div style="text-align: justify;"> </div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"><span style="color: blue;"><br />
</span></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"> </div><div style="text-align: justify;"> </div>Anonymoushttp://www.blogger.com/profile/14726324449337290251noreply@blogger.com8