Hilo General - Dudas de Java

Wasd

Me tomo la libertad de crear este hilo para que vayamos colgando nuestras dudas y problemas a la hora de programar en Java, ya que cada vez que entro al foro veo varios "Duda Java tal cosa" "Duda Java tal otra". De hecho sería partidario de crear un hilo general para cada lenguaje (en el momento de escribir este hilo, hay 3 hilos que comienzan por "Duda C++ ..." en la primera página).

Soy un aprendiz novicio de Java, y en estos momentos me encuentro con un pequeño problema.
Me han mandado de deberes programar el juego de "hundir la flota" y tengo un problema con un bucle bastante estúpido, presupongo que me podréis ayudar:
El problema lo tengo en

if(intro_fila != "loquesea"){}

Teoricamente, cuando no cumple la condición de ese if, se mete en el else y lo convierte a CharArray, a la vez que termina el bucle dandole el valor de "true" a fila, sin embargo, haga lo que haga SIEMPRE se mete en el bucle, tanto si pongo "A" como si pongo "847566"

for(boolean fila = false; fila == false;){
		System.out.println("Introduce la posicion del barco a colocar"); 
		System.out.println("Ejemplo: Fila: A | Casilla: 0");
		System.out.print("Fila: ");
		String intro_fila = buffer.readLine();
		 if(intro_fila != "A" || intro_fila != "B" || intro_fila != "C" || intro_fila != "D" || intro_fila != "E" || intro_fila != "F" || intro_fila != "G" || intro_fila != "H" || intro_fila != "I" || intro_fila != "J"){
			 System.out.println("");
			 System.out.println("Por favor, introduce un dato valido.");
			 System.out.println("");
		     }
		 else{
			 intro_fila.toCharArray();
			 fila = true;
		  }
		 }
		System.out.print("Casilla: ");
		String intro_casilla = buffer.readLine();
		int casilla = Integer.parseInt(intro_casilla);

El corchete del for se cierra más abajo, ya que estoy dentro de un switch que a su vez está dentro de otro for.

Lecherito

#1 el problema que tienes es el siguiente

int i = 1;
if (i != 1 || i != 2) { println("No"); }

Si i no es 1 o no es 2, esa condición se va a cumplir SIEMPRE, por que sea el numero que sea, no puede ser dos veces el mismo, y es el problema que tienes con este IF

if(intro_fila != "A" || intro_fila != "B" || intro_fila != "C" || intro_fila != "D" || intro_fila != "E" || intro_fila != "F" || intro_fila != "G" || intro_fila != "H" || intro_fila != "I" || intro_fila != "J"){

Que por cierto quizá se podria acortar un poquito xDD del tipo

 int charAscii = ascii(intro_fila)

if (charAscii >= 64 && charAscii <= 72) { asdf }

si es que creo que te he entendido bien xDD

Por otra parte loco, usa los \n en los "println" y no tendrás lineas de println vacías, como por ejemplo la 9 y la 7:

System.out.println("\nPor favor, introduce un dato valido.\n");
1 respuesta
Wasd

#2 Ostias, no conocía lo del uso de Ascii en java. guay, pues usaré lo que dices (que por cierto, según veo en una tabla, de la A a la J sería

if (charAscii >= 65 && charAscii <= 74) { asdf }

, me equivoco?) Gracias por la ayuda ;)
En cuanto a lo de \n lo usaré mas a menudo, esas son la clase de cosas que suelo mirar al acabar un programa, limpiar un poquito el código xD.

1 respuesta
Lecherito

#3 realmente eso del ascii en java no sé muy bien como va, ya que en C es automático, pero vamos, creo que sería algo por el estilo xD
PD: a lo que realmente me referia es que en el if de todas las letras has de usar un AND, no un OR como estás usando xD,

1 respuesta
Wasd

#4 No puedo usar lo de Ascii en java, quizás tenga que importar algo, no lo se. En cuanto a lo del error, tenías razón en lo de "&&", pero el verdadero fallo estaba en que no se debe decir

if(intro_fila == "A"){}

, sino

if(intro_fila.equalsIgnoreCase("A")){}

, por suerte me he acordado xDD.
De todas formas gracias por la ayuda ;)

JuAn4k4

si puedes usarlo...

String a = "A";

char ascii = a.charAt(0);

if (ascii >= 45) ...

1 respuesta
Wasd

#6 El valor de ascii me sale que es "A", no me da ningún valor numérico. Quiero decir... como lo va a comparar con >= 45 si el valor es "A"?
Pregunto.
Repito que estoy empezando y tengo muchas dudas.

1 respuesta
dagavi

Para comparar strings ("A" es un string ya que está entre comillas dobles) tienes el método de strings: compareTo:

String str = "Hola";
str.comparteTo("Otro string" );

O lo que es lo mismo:
"Hola".compareTo("Otro string" );

No puedes comparar "A" con 45 porque no tiene sentido. "A" es un objeto de tipo string, pero si puedes comparar (o al menos en C se puede) 'A' con 45 puesto que 'A' es un carácter, un tipo básico cuya representación en ASCII es comparable.

Ya te han dicho que tu IF, suponiendo que estuviera bien programado (con temas de strings, etc.), no sirve de nada, es siempre cierto (si no es diferente una cosa la es otra).

Y para comparar caracteres no uses los valores ASCII (a no ser que vayas a hacer alguna cosa a nivel de bits), es menos portable (teóricamente) y menos legible (esto obviamente). En Java y C los caracteres se ponen con 'A' (comilla simple) por lo que puedes hacer:

char ch = input.charAt(0);
if (ch < 'A' || ch > 'F' ) // Cosas

Sin embargo no compruebas que input sea realmente correcto, solo miras la primera letra, deberías mirar que tiene un tamaño de 1 y después que la letra sea una de las correctas.

Ronso

Buenas, me uno al hilo, yo tengo una duda de "explicación", tengo este ejercicio que compila todo muy bien pero no entiendo varías cosas...

import java.util.Random;
public class TirarDados
{
	public static void main (String args[])
	{
		Random aleatorios = new Random();
		int a[] = new int[7];
		
	for (int tiro=1; tiro <= 6000; tiro++)
		++a[1 + aleatorios.nextInt(6)];
		
	System.out.printf("%s%10s\n", "Cara", "Frecuencia");
	
	for (int cara=1; cara < a.length; cara++)
		System.out.printf("%4d%10d\n", cara, a[cara]);
}
}

Porque son 7 y no 6? al poner 6 me da error, pero no entiendo el porque, solo tiene 6 caras el dado.

int a[] = new int[7];

Porque pone al final el 6? para que el número máximo del random sea el 6?

++a[1 + aleatorios.nextInt(6)];

Gracias!

2 respuestas
dagavi

#9 La segunda parte, la de "porque pone al final el 6" lo puedes averiguar tu mismo, pero te voy a decir como hacerlo para próximas veces:

"aleatorios" es un objeto de la clase random, vamos a mirar la especificación de esta clase en la documentación de Java. Algo típico es poner en google "random api java" y te suele salir el primero.
La API de java la puedes encontrar en su web, buscando en Google (no está escondida, se encuentra muy fácilmente) y en el link http://docs.oracle.com/javase/6/docs/api/

Entra en ese link, control + f y "Random" (para buscar "Random" en la página) y haces click a la clase Random. Ahora buscamos el método nextInt, aquí tenemos la descripción corta:

int nextInt(int n)
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.

Aquí una más larga: http://docs.oracle.com/javase/6/docs/api/java/util/Random.html#nextInt(int)

Por lo tanto ya sabes que es "nextInt(6)" devuelve un valor entre 0..5 (o lo que es lo mismo: 0 incluido 6 excluido).

Ahora que ya sabemos que hay dentro de a[algo] veamos porque te peta el new int[6] y no el new int[7]

Sabes que el random da un valor entre 0 y 5, y tu quieres acceder a la posición a[1 + random] es decir, entre 1 y 6.

Los vectores de tamaño N se indexan desde la posición 0 a la N-1 (que son N elementos: si hacemos new int[2] pues puedes acceder a 0 y a 1, que son 2 elementos).

Ahora ya puedes ver el problema, tu has creado un vector de 6 elementos, 0..5 pero accedes a las posiciones 1..6, el 6 no existe dentro del vector. Podrías quitar el 1+ y ya te funcionaría. De hecho no tiene utilidad alguna que pongas 1+Random y dejes la posición 0 sin usar.

Esto te cambia el bucle final, de hecho verás que lo típico es hacer for (int i = 0; i < v.size(); ++i) y no i = 1 puesto que la primera posición es 0. Si quieres que en pantalla se escriba de 1 a N pues simplemente cambia el System.out.printf() y donde has puesto "cara" pon "cara + 1":

                Random aleatorios = new Random();
                int a[] = new int[6];
               
for (int tiro=1; tiro <= 6000; tiro++) ++a[aleatorios.nextInt(6)]; System.out.printf("%s%10s\n", "Cara", "Frecuencia"); for (int cara = 0; cara < a.length; cara++) System.out.printf("%4d%10d\n", cara + 1, a[cara]);

Esto también es guarro:

                System.out.printf("%s%10s\n", "Cara", "Frecuencia");

Si estás escribiendo un string (y no es ni variable ni nada) lo puedes poner directamente
No hace falta que digas "%s %s %s", "Hola", "Que", "Tal" pudiendo hacer directamente "Hola Que Tal"

1 respuesta
Ronso

#10 Gracias! Creo que más o menos lo he pillado, pero en

++a[aleatorios.nextInt(6)];

al poner 6 dices que va del 0 al 5 (es decir excluye el número que pongas) por tanto... como sabemos las veces que saco el número 6? Que hace contar 0 como 1 y el 5 como 6?

En cuanto a lo de printf

System.out.printf("%s%10s\n", "Cara", "Frecuencia");

simplemente lo uso porque estoy siguiendo un libro que lo pone así y porque al ponerlo en columnas pues tengo que poner la segunda a 10 espacios.

PD: antes solía concatenar todo con + no con , es decir así:

System.out.print("Son "+x+"euros.")
1 respuesta
dagavi

#11 "al poner 6 dices que va del 0 al 5 (es decir excluye el número que pongas) por tanto... como sabemos las veces que saco el número 6? Que hace contar 0 como 1 y el 5 como 6?"

El 6 no va a salir nunca, tu vas a guardar las veces que sale el 0, el 1, el 2, el 3, el 4 y el 5 (de hecho es lo que ya había, solo que tu le sumabas un 1 artificial, cuando te salía un 0 decías: ++a[1 + 0 = 1] cuando te ha salido un 0).

Así pues puedes hacer lo que te de la gana con tu vector de apariciones del 0..5, decir que el 0 es el 6 y el resto son la posición que indica. Decir que tienes apariciones del 0 al 5, decir que la posición 0 es como 1, la 1 como 2... la 5 como 6 (de hecho mi printf te hace esto, si te das cuenta escribo cara + 1).

JuAn4k4

#7 Yo no estoy comparando "A" , estoy comparando "A".charAt(0); que es un char, y si se hace cast a (int) de un char, se transforma en su representacion ascii.

Ronso

Hola de nuevo, estoy ahora enfrascado en un ejercicio de arrays multidimensionales. Quiero hacer lo siguiente, cargar el array numérico de dos dimensiones tabla[3][5] desde teclado y visualizarlo. Empecé a hacerlo de la siguiente manera:

import java.util.*;
public class Ejer2
{
	public static void main (String args[])
	{
		int a[][] = new int[3][5];
		
	Scanner teclado = new Scanner(System.in);
	
	for (int cont=0; cont<5; cont++)
		{
			System.out.print("Introduzca un numero: ");
			a[0][cont] = teclado.nextInt();
		}
		
	for (int cont=0; cont<5; cont++)
		{
			System.out.print("Introduzca un numero: ");
			a[1][cont] = teclado.nextInt();
		}
		
	for (int cont=0; cont<5; cont++)
		{
			System.out.print("Introduzca un numero: ");
			a[2][cont] = teclado.nextInt();
		}
	
}
}

Pero he visto que a la hora de mostrarlo por pantalla no se como hacerlo, porque creo que lo estoy haciendo mal, ya que debería de usar un bucle for anidado... pero no se como hacerlo que uno cuente 3 y otro cuente solo 5.

Gracias!

EDITO: Ya lo he conseguido.

import java.util.*;
public class Ejer2
{
	public static void main (String args[])
	{
		int a[][] = new int[3][5];
		
	Scanner teclado = new Scanner(System.in);
	
	for (int cont=0; cont<3; cont++)
		{
			for (int i=0; i<5; i++)
			{
				System.out.print("Introduzca un numero: ");
				a[cont][i] = teclado.nextInt();
			}
		}
		
	System.out.println("Los numeros introducidos son: ");
	
	for (int cont=0; cont<3; cont++)
		{
			for (int i=0; i<5; i++)
			{
				System.out.print(a[cont][i]+" ");
			}
			System.out.println();
		}
}
}
1 respuesta
tOWERR

#14
Ya he visto que lo has conseguido, te iba a decir que para hacer ese tipo de lectura de array se utilizan 2 bucles, uno dentro de otro. Pero vi que lo solucionaste sin problema.

1 respuesta
Ronso

#15 Si xD, me costo un poco sacarlo pero bueno, así ya no se me olvida nunca jaja. Por cierto si alguno puede poner un ejemplo del try y catch para saber como va. Es que en un ejercicio pido un numero entero del 1-10 pero si meto una letra me salta el programa con una exception y si meto otro número mayor o menor me lo coje igualmente...

Gracias!

1 respuesta
tOWERR

#15
El trato de las excepciones es facil, te dejo un ejemplo:

try{

//Codigo que se va a ejecutar

}catch(Exception e){
    System.out.println("Solo puede introducir números entre 1 y 10);
}

Esto seria el trato de la excepción que te sucede.

1 respuesta
zoeshadow

Buena iniciativa la de este hilo, estoy estudiando y trasteando ahora con java y la verdad es que a veces me surgen dudas bastante tontas y me da palo crear un hilo solo para eso...

Alguien podría decirme si http://en.wikipedia.org/wiki/Singleton_pattern se usa realmente, o es mas una teoría que no se utiliza en la practica..?

1 respuesta
dagavi

#16 - #17 Te ha dado el ejemplo para capturar toda excepción (todas heredan de Exception por lo que esta es la más general).

Otra cosa es ir pillando excepciones más concretas y lo harías con

try {
    // código que puede lanzar MiEx1
    // código que puede lanzar MiEx2
    // código que puede lanzar IOException
}
catch(MiEx1) {
    // ¿Algo?
}
catch(MiEx2) {
    // ¿Algo?
}
catch(IOException) {
    // ¿Algo?
}

Así pillas las diferentes excepciones en vez de 1 genérica (si es que te hiciera falta, claro).

El propio IDE Eclipse te marca el código que genera excepciones y te anida automáticamente las cosas en try...catch (si le das al error y te pone como solución: anidar en try...catch, aunque también te puede decir: generar throw, esto último hace que la función en la que estás lance la excepción, en vez de capturarla, por lo que el código que llame a esta función será la que se encargue de gestionar la excepción, o de volver a propagarla)

dagavi

#18 Se utiliza, si bien rivaliza con clases con todo estático (en internet hay debates de si hacer una clase estática o bien singleton)

1 respuesta
zoeshadow

#20 Interesante, buscaré mas sobre ello, gracias!

1 respuesta
BLZKZ

¿Algún ejemplo en código de uso de RowSet?

Haciendo DAO's me ha entrado la curiosidad pero no se muy bien como usarlo.

saludos xD

#21 si te interesan los patrones http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html

Singleton se usa mucho para DAO, o todo lo que vaya a acceder a una BBDD directamente. A mi me parece una solución muy buena para evitar complicaciones y asegurar seguridad xD

1 respuesta
zoeshadow

#22 Justo era ese el problema que tenia, iba a hacer un programa/practica que iba a trabajar con bases de datos y veia una tonteria crear una instancia de una clase para cada "campo", si luego iba a hacer lo mismo en la bbdd.
Está bien saber que iba bien encaminado :)

JuAn4k4

En cuanto a base de datos, si podeis usar Hibernate, os recomiendo usarlo y aprenderlo, actualmente es lo mas utilizado en Java para bases de datos (Hibernate y la java persistence api JPA).

Un ResultSet es un conjunto de filas resultado de una consulta , en si, todas estas clases son Interfaces, que las implementa el driver de la base de datos, por lo que lo que estas recojiendo son las instancias que tu driver ha generado para la consulta que has ejecutado.

PD: Exception no es la mas generica, pero si es la generica de las recomendadas a capturar, pero por encima esta Throable, y por debajo de esta esta Error y Exception, en teoria y por lo general un Error seria un error no recuperable (ClassNotFound seria un ejemplo) pero alguna vez, se puede dar el caso de que se puedan recuperar.

En si lo recomendable es crear tus propias excepciones, capturar aquellas que sean declaradas que se lancen en las librerias que uses, y nunca capturar NullPointerException.

11 días después
Perurena

Hola! Pregunto aquí antes de crear un hilo nuevo. Tengo una duda con los Thread, he programado una thread para que me reproduzca una canción, el código lo he encontrado en internet pero la verdad que no lo entiendo... Sobre todo los Thread.sleep(1000), que función tiene en este caso?

 
	public class SonidoFondo extends Thread{
	private String nombre;
	private Clip sonido;
	public SonidoFondo(String nombrep){
		nombre=nombrep;
	}
	public void run() 
	{ 
		
	try {
		// Se obtiene un sonido
		sonido = AudioSystem.getClip();
		// Se carga con un fichero wav
		sonido.open(AudioSystem.getAudioInputStream(
		new File(nombre+".wav")));
		// Comienza la reproducción
		sonido.loop(0);
		Thread.sleep(1000);
		// Espera mientras se esté reproduciendo.
		while (sonido.isRunning()){
			if (interrupted()) {
				sonido.stop();
				break;
			}
		}
		// Se cierra
		sonido.close();
	}
	catch(InterruptedException e){
		
	}
	catch (Exception e) {
		System.out.println("File not found");
	}
} 
}

Gracias de antemano!

2 respuestas
tOWERR

#25

Yo esa función de sleep() no la he visto, pero por lo que tiene el significado será para pausar la ejecución del hilo durante el tiempo que se le pase a la función. Y sino, papa Google te dirá lo que es.

dagavi

#25 Como digo en #10 una simple consulta a la API te da la respuesta de que cojones hace Thread.sleep

http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#sleep%28long%29

El link a la API debería estar puesto al inicio del tema y poner algo como: quien haga una consulta de que hace una función de la API de Java -> golpe de remo

Aun así me da la impresión de que la pregunta de #25 no va exactamente de que hace Thread.sleep() (que yo también creo que se entiende), si no su utilidad antes del bucle ese, es decir ¿porque esperar 1 segundo?. Pero ni zorra, tal vez sea porque el reproductor ese de audio tarda un rato en ponerse en modo "active" (para que el método isActive retorne true) y por eso se le da tiempo. Prueba a quitarlo y si funciona pues tal vez lo han puesto simplemente para que el sonido se reproduzca y durante el rato estimado (1 segundo) ese thread no esté consumiendo CPU.

PD: Una cosa es preguntar que hace una función (que en este caso está claro, y sería golpe de remo) y otra es que no se termine de entender su comportamiento, en que puede ayudar, etc. es decir, que tras mirar que hace en la API se siga con dudas / no se entienda.

1 respuesta
Perurena

#27 Gracias por la explicación. Pero mi duda era lo que comentas(no qué hace el .sleep()), que no se que coño pinta ahí, porque quitándolo deja de reproducirse... Y era por si alguien podía saberlo!

litoss

A ver un problemete que tengo, al crear un Jbutton y ponerle un icono/imagen encima del mismo tamaño el boton sinsentido se hace mas grande.

       volver2 = new JButton();
       volver2.setIcon(new ImageIcon("menupclima2.jpg"));
       volver2.setActionCommand("volver2");

Aqui podeis ver en la imagen lo que pasa. Se supone que hago el icono del tamaño del boton, pero cuando le pongo el icono el boton se hace mas grande :/

Y otra duda, para poner una imagen de fondo al jframe, no hay algun comado tipo setImage o algo?

1 respuesta
litoss

He descubierto que solo me pasa en los layout que no son Grid , sinsen.

Alguna idea?

PD: Doblepost :_(

Tema cerrado