Professional Documents
Culture Documents
SCJP 1.2
Traducción del tutorial de Marcus Green.
RuGI
Isaac Ruiz Guerra
rugi@javahispano.org
javaHispano
Tu lenguaje, tu comunidad.
Versión Julio del 2003.
Tutorial para el examen de certificación: SCJP 1.2
La mayor parte de este documento cubre tambien los objetivos para la versión 1.4
únicamente se deben pasar por alto las secciones 8 y 11, y agregar el tema de Aserciones.
Nombre: Sección:
Isaac Ruiz Guerra 1, 2, 3, 4, 6, 8, 9, 10
Joslyn Flores Romero 7
Francisco Fernández Miser 5
Alberto Molpeceres 11
Copyright (c) 2003,Isaac Ruiz Guerra. Este documento puede ser distribuido solo bajo
los términos y condiciones de la licencia de Documentación de javaHispano v1.0 o
posterior (la última versión se encuentra en http://www.javahispano.org/licencias/).
2
javaHispano. Tu comunidad, tu lenguaje.
3
Tutorial para el examen de certificación: SCJP 1.2
4
javaHispano. Tu comunidad, tu lenguaje.
5
Tutorial para el examen de certificación: SCJP 1.2
6
javaHispano. Tu comunidad, tu lenguaje.
Arreglos.
Los arreglos en Java son similares en sintaxis a los arreglos en otros lenguajes
como C/C++ y Visual Basic. Sin embargo, Java elimina la característica de C/C++
mediante la cual puedes pasar los corchetes ([]) accediendo a los elementos y obteniendo
sus valores utilizado punteros. Esta capacidad en C/C++, aunque poderosa, propicia la
escritura de software defectuoso. Debido a que Java no soporta esta manipulación directa
de punteros, se remueve esta fuente de errores.
Todos los elementos de un arreglo deben ser del mimo tipo. El tipo de elementos de un
arreglo, se decide cuando se declara el arreglo.
int num[5];
int num[];
num = new int[5];
7
Tutorial para el examen de certificación: SCJP 1.2
Además los corchetes pueden ser también colocados después del tipo de dato o después
del nombre del arreglo. Por lo tanto son legales las siguientes declaraciones:
int[] num;
int num[];
Una gran diferencia entre java y C/C++ es que en java se conocen de que
tamaño son los arreglos, y el lenguaje proporciona protección para no
sobrepasar los limites del arreglo.
Para recorrer un arreglo, la manera mas común es a través del campo length de los
arreglos, así:
8
javaHispano. Tu comunidad, tu lenguaje.
Nota que los arreglos tienen el campo length y no el método length(). Cuando
comiences a utilizar Strings usaras el método length, de la siguiente manera:
s.length();
Una diferencia importante entre los arreglos multidimensionales, como en C/C++ y los
arreglos anidados, es que cada arreglo no tiene que ser del mismo tamaño. Si vemos
un arreglo como una matriz, la matriz no tiene que ser una matriz rectángulo .
De acuerdo con la Especificación del Lenguaje Java:
(http://java.sun.com/docs/books/jls/html/10.doc.html#27805)
int [][];
9
Tutorial para el examen de certificación: SCJP 1.2
Puedes crear y llenar arreglos simultáneamente con cualquier tipo de dato, por lo tanto
puedes crear un arreglo de cadenas, de la siguiente manera:
Ejercicio 1)
Crea una clase con un método que simultáneamente cree e inicialize un arreglo de
cadenas. Inicializa el arreglo con cuatro nombres, después muestra el primer nombre
contenido en el arreglo.
Ejercicio 2)
Crea una clase que cree un arreglo de cadenas de 5 elementos llamado Fruit en el
nivel de clase, pero no lo inicializes con cualquier valor. Crea un método llamado
amethod. En amethod inicializa los primeros cuatro elementos con nombres de frutas.
Crea otro método llamado modify y cambia el contenido del primer elemento del
arreglo Fruit para que contenga la cadena “bicycle”. Dentro del método modify
crea un ciclo for que imprima todos los elementos del arreglo.
10
javaHispano. Tu comunidad, tu lenguaje.
}
public void Claines(){
String[] names= new
String[]{"Peter","John","Balhar","Raj"};
System.out.println(names[0]);
}
}
}
}
Nota: Cuando el ciclo ejecute la salida de elemento final este será null.
11
Tutorial para el examen de certificación: SCJP 1.2
Preguntas.
Pregunta 1)
¿Cómo puedes redimensionar un arreglo con una declaración sencilla manteniendo el
contenido original?
Pregunta 2)
Quieres averiguar el valor del último elemento de un arreglo. Escribiendo el siguiente
Código.¿Qué pasara cuando lo compiles y ejecutes?
Pregunta 3)
Quieres hacer un ciclo a través de un arreglo y detenerte cuando llegues al ultimo
elemento. Siendo un buen programador en Java, y olvidando lo que alguna vez conociste
sobre C/C++, sabes que los arreglos contienen información acerca de su tamaño.
¿Cuál de las siguientes sentencias puedes usar?
1)myarray.length();
2)myarray.length;
3)myarray.size
4)myarray.size();
Pregunta 4)
Tu jefe esta complacido por que escribiste el programa Hello World y te ha dado un
aumento. Ahora te encomienda que crees un juego como el TicTacToe(o puntos y cruces
como lo conocí en mi adolescencia). Decides que para eso necesitas un arreglo
multidimensional. ¿Cuál de las siguientes líneas realizan el trabajo?
Pregunta 5)
12
javaHispano. Tu comunidad, tu lenguaje.
Quieres encontrar una manera más elegante para llenar un arreglo que a través de un
ciclo con la sentencia for. ¿Cuál de las siguientes líneas usarías?
1)
myArray{
[1]="One";
[2]="Two";
[3]="Three";
end with
Respuestas
Respuesta 1)
No puedes redimensionar un arreglo. Necesitas crear un nuevo arreglo temporal con
un tamaño diferente y llenarlo con el contenido del arreglo original. Java Proporciona
contenedores redimencionables con clases como Vector o uno de los miembros de la
clase collection .
Respuesta 2)
Intentar avanzar mas allá del final del arreglo genera un error en tiempo de ejecución.
Debido a que los arreglos son indexados desde 0, el elemento final será i[4] y no
i[5].
Respuesta 3)
2) myarray.length;
Respuesta 4)
3) int[][] = new int[3][3];
Respuesta 5)
3) String s[] = new String[]{“Zero,”One”,”Two”,”Three”,”Four”};
13
Tutorial para el examen de certificación: SCJP 1.2
14
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 2.
Declarar clases, clases internas, métodos, variables de instancia estáticas, variables y
variables automáticas(métodos locales), haciendo un uso apropiado de todos los
modificadores permitidos (como son: public, final, static, abstract, y
demás). Conocer importancia de cada uno de estos modificadores ya sea solos o en
combinación
native
transient
synchronized
volatile
El lenguaje C++ implementa la herencia múltiple y así una clase puede tener más de un
padre (o clase base) Java únicamente permite la herencia simple, es decir, las clases
pueden tener únicamente un padre. Para sobreponer esta limitación, Java tiene una
característica llamada: Interfaces, a la cual los diseñadores del lenguaje le decidieron dar
algunas de las ventajas de la herencia múltiple, pero sin las desventajas. Todas las clases
en Java son descendientes de una gran clase antecesora llamada Object.
15
Tutorial para el examen de certificación: SCJP 1.2
class classname {}
es una definición sintacticamente correcta para una clase, pero no es una clase
particularmente útil (sorprendentemente, me he encontrado definiendo clases como esta,
cuando creo ejemplos para ilustrar la herencia)
La palabra clave public es un modificador de visibilidad que indica que la clase deberá
ser visible para cualquier otra clase. Solo una clase por archivo puede ser declarada
publica. Si declaras mas de una clase en un archivo como publica, ocurrirá un error en
tiempo de ejecución. Observa que Java es sensible a mayúsculas en todos los aspectos. El
archivo que contenga esta clase deberá llamarse HelloWorld.java
La palabra clave class indica que una clase comienza a ser definida y HelloWorld es
el nombre de la clase. Observa que la llave de cierre que finaliza la definición de la clase
no involucra un punto y coma de cerradura. El comentario:
Usa el estilo de comentario de una sola línea que esta disponible en C/C++. Java también
comprende los comentarios multilíneas de la forma /* */.
16
javaHispano. Tu comunidad, tu lenguaje.
Dando a un método la siguiente forma, esté obtiene cierta significancia (o magia) cuando
indica a Java que es aquí en donde el programa debe empezar a ejecutarse. (similar al
main del lenguaje C).
Esta línea indica que esta definiéndose un método llamado main, y que toma como
parámetros (o argumentos) a un arreglo de cadenas. Este método es publico, es decir es
visible desde cualquier parte de la clase. La palabra clave static indica que este método
puede ejecutarse sin crear una instancia de la clase. Si eso no significa nada para ti, no te
preocupes, en su momento se cubrirán con detalle los métodos estáticos (static) en otra
parte de este tutorial. La palabra clave void indica el tipo de dato retornado por el
método cuando se llama. Usar void indica que ningún valor será retornado.
String argv[]
Indica que el método toma un arreglo de tipo String. Los corchetes indican –como ya
vimos- un arreglo. Observa que el tipo de dato String comienza con una “S”
mayúscula. Esto es importante ya que Java es totalmente sensible a las mayúsculas. Sin
estas exactitudes, la Maquina virtual de Java (JVM) no reconocerá el método como el
lugar en donde se debe comenzar la ejecución del programa.
17
Tutorial para el examen de certificación: SCJP 1.2
Esta sintaxis para crear una nueva instancia de una clase es básica para el uso de clases.
Observa cómo el nombre de la clase aparece dos veces. La primera vez indica el tipo de
dato de la referencia a la clase. Esta necesidad no es la misma que el tipo actual de la
clase puesto que ésta se indica después de usar la palabra clave new. El nombre de esta
instancia de la clase es hw. Éste simplemente es un nombre escogido para una variable.
Este es un nombramiento convencional (es decir, utilizando la convención para escritura
de código Java)ya que una instancia de una clase empieza con una letra minúscula,
considerando que la definición de una clase empieza con una letra mayúscula.
El paréntesis vacío para el nombre de la clase HelloWorld() indica que la clase está
creándose sin algún parámetro en su constructor. Si estuvieras creando una instancia de
una clase que se inicializa con un valor o un arreglo como la clase Label o Button el
paréntesis contendría uno o mas valores de inicialización.
Creando Métodos.
Como ilustro en el último ejemplo HelloWorld2, un método en Java es similar a una
función en C/C++ y a una función o sub función en Visual Basic. El método llamado
amethod en este ejemplo se declara como:
public
que indica que puede accederse desde cualquier parte. Retorna el tipo:
void
Indicando que ningún valor será retornado. Y los paréntesis vacíos indican que no toma
parámetros.
Estos ejemplos ilustran algunas otras firmas típicas de declaración de métodos. El uso de
las palabras clave private y protected se cubrirá en otro apartado.
18
javaHispano. Tu comunidad, tu lenguaje.
Las dos instancias de la clase: hw y hw2 podrían tener acceso a variables diferentes.
Variables Automáticas
Las variables automáticas son las variables de los métodos. Estas entran en el alcance del
programa cuando empieza a ejecutarse el código del método y dejan de existir una vez
que el método deja de ejecutarse. Son sólo visibles dentro del método y son útiles
principalmente para la manipulación de datos temporales. Si quieres que un valor
permanezca entre las llamadas de un método entonces la variable necesita ser creada al
nivel de la clase.
19
Tutorial para el examen de certificación: SCJP 1.2
Modificadores y Encapsulamiento.
A menudo estos métodos son para recuperar y actualizar los valores de una variable local
privada. Son conocidos como métodos accessor (acceder o obtener el valor de la
variable) y mutator (modificar el contenido de una variable). La convención para
nombrar a estos métodos es setFoo para modificar y getFoo para obtener el contenido
de una variable. Así si estuvieras almacenado una variable llamada age deberías hacerla
privada y actualizarla con:
setAge
getAge
Private
Las variables privadas son sólo visibles dentro de la misma clase donde se crean. Esto
significa que NO son visibles dentro de las subclases. Esto permite que la variable sea
aislada de ser modificada por cualquier método, exceptuando aquellos en la clase actual.
Como se dijo anteriormente, esto es útil para separar la interfase de la implementación.
class Base{
private int iEnc=10;
public void setEnc(int iEncVal){
if(iEncVal < 1000){
iEnc=iEncVal;
}else
System.out.println("Enc value must be less than 1000");
//Or Perhaps thow an exception
}//End if
}
public class Enc{
public static void main(String argv[]){
Base b = new Base();
b.setEnc(1001);
}//End of main
}
20
javaHispano. Tu comunidad, tu lenguaje.
Public
Esto es porque para iniciar el método mágico la JVM, sólo revisa en una clase declarada
como publica:
Una clase pública tiene alcance global, y una instancia puede crearse desde cualquier
parte dentro o fuera de un programa. Únicamente una clase en un archivo puede definirse
con la palabra clave public. Si defines más de una clase en un archivo con la palabra
clave public el compilador generará un error
class Base {
public int iNoEnc=77;
}
public class NoEnc{
public static void main(String argv[]){
Base b = new Base();
b.iNoEnc=2;
System.out.println(b.iNoEnc);
}//End of main
}
Protected
21
Tutorial para el examen de certificación: SCJP 1.2
Se dice que una variable definida sin modificador de acceso tiene visibilidad predefinida.
La visibilidad predefinida significa que una variable puede verse dentro de la clase, y
desde otra parte dentro del mismo paquete, pero no desde una subclase que no esté en el
mismo paquete.
Static
class MyClass{
public int iMyVal=0;
}
public class NonStat{
public static void main(String argv[]){
MyClass m1 = new MyClass();
m1.iMyVal=1;
MyClass m2 = new MyClass();
m2.iMyVal=2;
MyClass m3 = new MyClass();
m3.iMyVal=99;
//Esto mostrará 1. Ya que cada instancia de
// la clase tiene su propia copia de MyVal
System.out.println(m1.iMyVal);
}//End of main
}
El Ejemplo siguiente muestra que pasa cuando tienes múltiples instancias de una clase
que contiene una variable estática, en este ejemplo la variable estática es iMyEval.
class MyClass{
public static int iMyVal=0;
}//End of MyClass
public class Stat{
public static void main(String argv[]){
MyClass m1 = new MyClass();
m1.iMyVal=0;
MyClass m2 = new MyClass();
m2.iMyVal=1;
MyClass m3 = new MyClass();
m2.iMyVal=99;
//Debido a que iMyVal es static,
//hay sólo una copia de él no importa
22
javaHispano. Tu comunidad, tu lenguaje.
Ten presente que no puedes acceder a variables no estáticas desde dentro de un método
estático. Así lo siguiente causará un error en tiempo de compilación.
Un método estático no puede ser sobreescrito para ser no estático en una clase
hija.
Un método estático no puede ser sobreescrito para ser no estático en una clase hija. No
hay ninguna regla similar con referencia a la sobrecarga. El código siguiente causará un
error cuando intentes sobreescribir el método amethod de la clase Base para ser no
estático.
class Base{
public static void amethod(){
}
}
public class Grimley extends Base{
public void amethod(){}//Causa un error en tiempo de
compilación
}
Native
El modificador native sólo se usa para los métodos e indica que el cuerpo del código
esta escrito en un lenguaje que no es Java como C y C++. Se escriben a menudo métodos
23
Tutorial para el examen de certificación: SCJP 1.2
Un método nativo termina con punto y coma en lugar de un bloque del código. Así lo
siguiente llamaría una rutina externa, escrita quizás en C++,
Abstract
Si una clase tiene algún método abstracto esta debe ser asimismo declarada
abstracta .
Sin embargo, no te distraigas pensado que una clase abstracta no puede tener métodos
no abstractos. Cualquier clase que descienda de una clase abstracta debe implementar los
métodos abstractos de la clase base o debe declararlos abstractos ella misma. ¿Tienden
estas reglas a generar la pregunta por qué querrías crear métodos abstractos?
24
javaHispano. Tu comunidad, tu lenguaje.
Final
El modificador final indica que un método no puede ser heredado. Otra manera de
entender esto es que una clase final no puede ser una clase padre. Cualquier método en
una clase final es automáticamente final. Esto puede ser útil si no quieres que otros
programadores "hechen a perder tu código". Otro beneficio es la eficacia puesto que el
compilador tiene menos trabajo al trabajar con un método final. Esto se cubre mejor en el
Volumen 1 de Core Java.
El código siguiente ilustra el uso del modificador final en una clase. Este código mostrará
la cadena "amethod":
Shynchronized
La palabra clave synchonized se usa para prevenir que más de un thread acceda a un
bloque de código a la vez. Ve la sección 7 sobre threads para entender más cómo
funciona esto.
Transient
Volatile
"le dice al compilador que una variable puede cambiar asincrónicamente debido a los
threads"
25
Tutorial para el examen de certificación: SCJP 1.2
Acepta que es parte del lenguaje y entonces mejor preocúpate por otras cosas.
• native
• transient
• synchronized
• volatile
Ejercicio 1)
Crea un archivo llamado Whitley.java. En este archivo define una clase llamada Base
con un método abstracto llamado lamprey que retorne un valor de tipo int. En el
mismo archivo crea una clase llamada Whitley que descienda de la clase Base.
Proporciona a la clase Whithley un método llamado lamprey con el código necesario
para mostrar en pantalla la cadena “lamprey”.
Crea un método nativo para la clase llamado mynative. Ahora compila y ejecuta el
código.
Ejercicio 2)
26
javaHispano. Tu comunidad, tu lenguaje.
Crea una clase publica llamada Malvern. Crea una clase interna y privada llamada
Great que tenga un método llamado show de la forma public void. Haz que este
método muestre en pantalla la cadena “Show”. Proporciona a la clase Malvern un
método publico llamado go que cree una instancia de Great y después de ser
instanciada llame al método show. En el método main de la clase Malvern crea una
instancia de sí misma. Haz que esta instancia llame al método go. Compila y ejecuta el
código.
}
public int lamprey(){
System.out.println("lamprey");
return 99;
}
native public void mynative();
}
27
Tutorial para el examen de certificación: SCJP 1.2
Preguntas.
Pregunta 1)
¿Qué pasará cuando intentes compilar y ejecutar este código?
}
}
Pregunta 2)
¿Qué pasara cuando intentes compilar y ejecutar este código?
28
javaHispano. Tu comunidad, tu lenguaje.
1) El compilador indicara que main es una palabra reservada y no puede ser usada
para nombrar una clase.
2) El código se compilará y cuando se ejecute mostrara en pantalla la cadena
“Hello cruel world”.
3) El código se compilara pero indicará un error en tiempo de ejecución: el
constructor no esta definido.
4) El código se compilara pero indicara que la función main no esta definida
correctamente.
Pregunta 3)
¿De los siguientes cuales son modificadores de Java?
1) public
2) private
3) friendly
4) transient
Pregunta 4)
¿Qué pasará cuando intentes compilar y ejecutar este código?
class Base{
abstract public void myfunc();
public void another(){
System.out.println("Another method");
}
}
public class Abs extends Base{
public static void main(String argv[]){
Abs a = new Abs();
a.amethod();
}
public void myfunc(){
System.out.println("My func");
}
public void amethod(){
myfunc();
}
}
29
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 5)
¿Para que defines un método como nativo?
Pregunta 6)
¿Qué pasará cuando intentes compilar y ejecutar este código?
class Base{
public final void amethod(){
System.out.println("amethod");
}
}
public class Fin extends Base{
public static void main(String argv[]){
Base b = new Base();
b.amethod();
}
}
1) Un error en tiempo de compilación indicando que una clase con algún método
final debe ser declarado final por si misma.
2) Un error en tiempo de compilación indicará que no puedes heredar de una clase
con métodos final
3) Un error en tiempo de ejecución indicando que Base no esta definida como
final
4) Éxito en la compilación y al ejecutarse mostrará en pantalla “amethod”.
Pregunta 7)
¿Qué pasará cuando intentes compilar y ejecutar este código?
30
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 8)
¿Qué pasará cuando intentes compilar y ejecutar este código?
Pregunta 9)
¿Qué pasara cuando intentes compilar y ejecutar estos dos archivos en el mismo
directorio?
//Archivo P1.java
package MyPackage;
class P1{
void afancymethod(){
System.out.println("What a fancy method");
}
}
//Archivo P2.java
public class P2 extends P1{
afancymethod();
}
31
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 10)
¿Cuáles de las declaraciones siguientes son legales?
Respuestas.
Respuesta 1)
1) El código se compilara y se ejecutara, mostrando la cadena “My func”
Una clase abstracta puede tener métodos no abstractos, pero cualquier clase que
descienda de ella, debe implementar todos los métodos abstractos.
Respuesta 2)
Respuesta 3)
1) public
2) private
4) transient
Aunque algunos textos usan la palabra “friendly” cuando tratan el tema de visibilidad,
esta no es una palabra reservada de Java. Toma en cuenta que será casi seguro que el
examen contenga problemas que te pidan que identifiques palabras claves de Java en una
lista.
Respuesta 4)
32
javaHispano. Tu comunidad, tu lenguaje.
^
1 error
Respuesta 5)
Respuesta 6)
Este código llama a una versión de amethod de la clase Base. Si intentas implementar
una versión sustituida del método en la clase Fin conseguirás un error en tiempo de
compilación.
Respuesta 7)
Esta línea no es una llamada a un método nativo –solo se esta declarando- y por lo tanto
no ocurre un error en la ejecución.
Respuesta 8)
Una clase de un nivel alto, al igual que una clase base, no puede ser declarada como
privada
Respuesta 9)
Aunque P2 esta en el mismo directorio que P1, debido a que P1 fue declarado como parte
de un paquete, P1 no esta visible para P2.
Respuesta 10)
Si pensaste que la opción 3 es legal utilizando como parámetro el argumento void, debes
quitarte un poco de C/C++ de la cabeza.
33
Tutorial para el examen de certificación: SCJP 1.2
34
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 3.
Para una clase dada, determinar si se debe crear un constructor predefinido, y si ese es el
caso, declarar el prototipo de ese constructor.
¿Qué es un constructor?
Aquí hay un ejemplo de una clase con un constructor que muestra "Greetings from
Crowle" cuando se crea una instancia de la clase.
35
Tutorial para el examen de certificación: SCJP 1.2
En cuanto creas algún constructor propio, pierdes el constructor predefinido con cero
parámetros. Si intentas crear una instancia de una clase, sin pasarle algún parámetro
(invocando la clase con el constructor con cero parámetros), obtendrás un error. Así,
cuando crees algún constructor para una clase necesitarás crear el constructor con cero
parámetros. Esta es una de las razones por las que generadores de código como
Borland/Inprise o JBuilder, crean un constructor con cero parámetros cuando generan el
esqueleto de una clase.
//Advertencia: no se compilará
class Base{
Base(int i){
System.out.println("single int constructor");
}
}
//Esto si se compilará
class Base{
Base(int i){
System.out.println("single int constructor");
}
Base(){}
}
36
javaHispano. Tu comunidad, tu lenguaje.
El objetivo te pide que estes consciente del prototipo del constructor predefinido.
Naturalmente no debe tener ningún parámetro. La predefinición más evidente es no tener
ningún especificador de alcance, pero puedes definir un constructor como público o
protegido.
Ejercicios
Ejercicio 1)
Crea una clase llamada Salwarpe con un método llamado hello que muestre la cadena
“hello”. En el método main de la clase crea una instancia de sí misma llamada s1 y
llama al método hello desde la instancia. Compila y ejecuta el programa para que
puedas ver el resultado.
Ejercicio 2)
Usando todavía el archivo Salwarpe.java comenta las líneas que crean la instancia y
llaman al método hello. Crea un constructor publico para la clase que tome un
parámetro entero y muestre el valor del entero. Crea una instancia de la clase llamada s2
proporciónale el valor de 99 al constructor. Compila y ejecuta el programa para que
puedas ver mostrado el resultado.
Ejercicio 3)
Descomenta las líneas que crean la instancia s1 y modifica el programa para que
compile, ejecute y muestre ambos la cadena Hello y el numero 99.
37
Tutorial para el examen de certificación: SCJP 1.2
Observa como fue necesario crear el constructor con cero parámetros para este último
ejercicio. Una vez que has creado algún constructor para una clase, Java ya no te
proporciona “tras escena” el constructor con cero parámetros que estaba disponible en el
ejercicio 1.
38
javaHispano. Tu comunidad, tu lenguaje.
Preguntas
Pregunta 1)
Dada la siguiente definición de clase:
class Base{
Base(int i){}
}
class DefCon extends Base{
DefCon(int i){
//XX
}
}
¿Cuál se las líneas siguientes será individualmente valida si se sustituye por la línea
marcada con //XX?
1) super();
2) this();
3) this(99);
4)super(99);
Pregunta 2)
Dada la siguiente definición de clase:
1) null
2) integer
3) String
4) no es retornado algún tipo de dato
Pregunta 3)
39
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 4)
¿Qué pasara cuando intentes compilar y ejecutar el siguiente código?
class Base{
Base(int i){
System.out.println("Base");
}
}
class Severn extends Base{
public static void main(String argv[]){
Severn s = new Severn();
}
void Severn(){
System.out.println("Severn");
}
}
Pregunta 5)
40
javaHispano. Tu comunidad, tu lenguaje.
Respuestas
Respuesta 1)
4)super (99)
Respuesta 2)
Debe ser bastante obvio de que ningún tipo de dato se retorna, así como por definición
los constructores no tienen tipos de datos
Respuesta 3)
Respuesta 4)
Ocurre un error cuando la clase Severn intenta llamar al constructor con cero parámetros
en la clase Base.
Respuesta 5)
41
Tutorial para el examen de certificación: SCJP 1.2
42
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 4
Establecer los tipos de datos validos de retorno para cualquier método, dada las
declaraciones de todos lo métodos relacionados con este o con la clase padre.
Para aprovechar mejor este objetivo necesitas una comprensión básica sobre la
sobrecarga y sobrescritura de métodos. Esto se ve en la:
Es el orden de los parámetros y los tipos de los mismos los que distinguen entre
cualquiera de dos versiones de un método sobrecargado a uno en especial. El tipo de dato
de retorno no contribuye a la distinción entre métodos.
class Same{
public static void main(String argv[]){
Over o = new Over();
int iBase=0;
o.amethod(iBase);
}
//Las siguientes definiciones generan un error al
compilar
public void amethod(int iOver){
System.out.println("Over.amethod");
}
public int amethod(int iOver){
System.out.println("Over int return method");
return 0;
}
43
Tutorial para el examen de certificación: SCJP 1.2
Puedes sobrecargar un método en una subclase. Todo lo que se requiere es que la nueva
versión debe tener parámetros de diferente tipo y en diferente orden. Los nombres de los
parámetros o el tipo de dato retornado por el método no se toman en cuenta para la
sobrecarga de métodos.
Preguntas
Pregunta 1)
44
javaHispano. Tu comunidad, tu lenguaje.
}
public void amethod(int i){}
//Here
}
¿Cuáles de las líneas siguientes son válidas para ser colocadas después del comentario
//Here?
Pregunta 2)
class Base{
public void amethod(){
System.out.println("Base");
}
}
public class Hay extends Base{
public static void main(String argv[]){
Hay h = new Hay();
h.amethod();
}
¿Cuál de los siguientes método puede ser de la clase Hay para que compile y provoque
que el programa muestre la cadena “Hay” ?
Respuestas
Respuesta 1)
45
Tutorial para el examen de certificación: SCJP 1.2
La opción 1 no compilara por dos razones. La primera es que obviamente exige que un
entero sea retornado- y como podemos ver hace falta un return -. La otra es que es
evidente un intento por redefinir un método dentro de la misma clase. El cambio de
nombre del parámetro de i a z no tiene efecto y un método no puede ser sobrescrito
dentro de la misma clase.
Respuesta 2)
La opción 3 es una sobrescritura del método de la clase Base, para alguna invocación de
esta versión se utilizarán cero parámetros
La opción 1 generará un error que indicará que se está intentando redefinir un método
con un diferente tipo de dato de retorno. Aunque la opción 2 compilará, la llamada a
amethod invocará el método de la clase Base y la salida sea la cadena “Base”. La
opción 4 fue diseñada para sorprender a aquellos con una cabeza llena de C/C++, en Java
no hay tal cosa: la utilización de void para indicar que no hay parámetros.
Jyothi Krishnan
http://www.geocities.com/SiliconValley/Network/3693/obj_sec1.html#obj4
46
javaHispano. Tu comunidad, tu lenguaje.
La sentencia if/else.
Ls sentencia if/else funciona en Java tal como podrías esperar que funcione en otros
lenguajes. las sentencias switch/case tienen unas peculiaridades.
if(condicion tipo_boolean){
//si el boolean es verdadero se hace esto
}else {
//sino, se hace esto
}
Las llaves son un indicador general en Java de una declaración compuesta que permite
ejecutar múltiples líneas de código como resultado de alguna evaluación. Esto se conoce
como bloque de código. La parte del "else" siempre es opcional.
Una idiosincrasia de Java es que la sentencia if debe tomar un valor del tipo boolean.
No puedes usar la convención de C/C++ donde cualquier valor distinto de cero es
verdadero y 0 es falso.
int k =-1;
if(k){//no se compilará!
System.out.println("do something");
}
Esto debido a que debes efectuar explícitamente una pregunta sobre la variable k que
devuelva un valor tipo boolean, como en el ejemplo siguiente:
if(k == -1){
System.out.println("do something"); //compilación OK!
}
47
Tutorial para el examen de certificación: SCJP 1.2
boolean k=true;
if(k)
System.out.println("do something");
if(k)
System.out.println("do something");
System.out.println("also do this");
La Sentencia switch
La opinión de Peter van der Lindens sobre la sentencia switch se resume cuando dice:
Este es un asunto al que le debes prestar atención extra. El argumento de una sentencia
switch debe ser un byte, char, short o un int. Puedes encontrar un ejercicio en
el examen que use un float o un long como argumento en una sentencia switch. Una
pregunta bastante común parece estar sobre el uso de la sentencia break en el proceso
descendente a través de una sentencia switch. Aquí hay un ejemplo de este tipo de
pregunta.
int k=10;
switch(k){
case 10:
System.out.println("ten");
case 20:
System.out.println("twenty");
}
El sentido común nos indicaría que después de ejecutar las instrucciones que siguen la
primera sentencia case, y habiéndose encontrado con otra sentencia case, el compilador
terminaría su descenso a través de la sentencia switch. Sin embargo, por razones mejor
conocidas solo por los diseñadores del lenguaje, una sentencia case solo se detiene
cuando se encuentran con una sentencia break. Como resultado, en el ejemplo anterior
las cadenas: "ten" y "twenty" son mostradas.
Otra pequeña peculiaridad que puede surgir en las preguntas es donde colocar la
sentencia default.
48
javaHispano. Tu comunidad, tu lenguaje.
El lugar convencional para la sentencia default está al final de las opciones case. Así
normalmente el código se escribirá como sigue:
int k=10;
switch(k){
case 10:
System.out.println("ten");
break;
case 20:
System.out.println("twenty");
break;
default:
System.out.println("This is the default output");
}
Esta aproximación refleja la manera en que piensa la mayoría de las personas. Una vez
que se han probado todas las posibilidades, se realiza la sentencia default. Sin
embargo, el código de una sentencia switch con la sentencia default hasta arriba es
sintácticamente correcto, pero no aconsejable.
int k=10;
switch(k){
default: //Coloca default hasta abajo y no acá
System.out.println("This is the default output");
break;
case 10:
System.out.println("ten");
break;
case 20:
System.out.println("twenty");
break;
}
El operador ternario ?
49
Tutorial para el examen de certificación: SCJP 1.2
Algunos programadores dicen que el operador ternario es útil. Yo no considero para que.
No se menciona específicamente en los objetivos así que por favor háganme saber si
aparece en su examen.
Pregunta 1)
¿Qué pasará cuando intentes compilar y ejecutar el siguiente código?
Pregunta 2)
¿Qué pasará cuando intentes compilar y ejecutar este código?
50
javaHispano. Tu comunidad, tu lenguaje.
if(b=false){
System.out.println("The value of b is"+b);
}
}
}
Pregunta 3)
¿Qué pasará cuando intentes compilar y ejecutar este código?
char k=10;
switch(k){
default:
System.out.println("This is the default output");
break;
case 10:
System.out.println("ten");
break;
case 20:
System.out.println("twenty");
break;
}
}
}
51
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 4)
¿Qué pasará cuando intentes compilar y ejecutar el siguiente código?
int k=10;
switch(k){
default: //Put the default at the bottom, not here
System.out.println("This is the default output");
break;
case 10:
System.out.println("ten");
case 20:
System.out.println("twenty");
break;
}
}
}
Pregunta 5)
¿ De las siguientes líneas, cual podría usarse como parámetro para una declaración
switch?
1) byte b=1;
2) int i=1;
3) boolean b=false;
4) char c='c';
Respuestas
Respuesta 1)
52
javaHispano. Tu comunidad, tu lenguaje.
Debido a que la variable boolean b se creó al nivel de clase, no necesita ser inicializada
explícitamente y en cambio toma el valor predefinido de un boolean que es falso. Una
sentencia if debe evaluar un valor boolean y así la variable b cumple este criterio.
Respuesta 2)
Debido a que la variable b es un boolean no habrá ningún error causado por la sentencia
if. Si b fuera de cualquier otro tipo de dato hubiera ocurrido un error cuando intentaras
realizar una asignación en lugar de una comparación. La expresión:
if(b=false)
if (b==false)
Si el tipo de dato de b hubiera sido cualquiera menos boolean habría ocurrido un error
al compilarse. El requisito para la sentencia if es que devuelva un boolean y debido a
que:
if (b=false)
Respuesta 3)
Respuesta 4)
System.out.println("ten");
Respuesta 5)
53
Tutorial para el examen de certificación: SCJP 1.2
1) byte b=1;
2) int i=1;
4) char c='c';
Una sentencia switch puede tomar únicamente a un byte, char short o a un int
como parámetro.
54
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 2.
Escribir código que use todas las formas de ciclos incluyendo el etiquetado y
desetiquetado, el uso de break y continue y conocer los valores tomados por las
variables contadoras de los ciclos durante y después de la ejecución de cada ciclo.
La sentencia for
El método más común para enciclar es usar la sentencia for. Como en C++ y a
diferencia de C, la variable que controla el ciclo puede crearse e inicializarse dentro de la
sentencia for. Así
Este código iterara 5 veces en el ciclo interno por cada iteración del ciclo externo. Así la
salida será:
Outer 0
Inner 0
Inner 1
Inner 2
Inner 3
inner 4
Outer 1
Inner 0
Inner 2
Etc, etc.
El sentencia for es el equivalente del ciclo for/next en Visual Basic. Debes tomar en
cuanta que la sintaxis es:
55
Tutorial para el examen de certificación: SCJP 1.2
La expresión condicional debe ser una expresión tipo boolean de una manera similar a
la sentencia if. En el código ejemplo sobre la sentencia for, esta fue seguida por un
bloque del código señalado por llaves. De la misma manera que un sentencia if no exige
un bloque de código, puedes tener una sentencia for que simplemente maneje una línea,
de esta manera:
for(int i=0;i<5;i++)
System.out.println(i);
Nota que en ninguna de las versiones se termina la línea del for con punto y coma. Si lo
haces, el ciclo for solo iterara en esa línea hasta que la condición se cumpla y entonces
el programa continuará en "línea recta". No tienes que crear variable de
inicialización(como en este caso) dentro del ciclo for, pero si lo haces significará que la
variable saldrá del alcance en cuanto se termine el ciclo. Esto puede ser considerado una
ventaja por lo que se refiere a mantener el alcance de las variables tan pequeño como sea
posible.
Así un while se ejecutará cero o más veces según la condición y el do se ejecutará una o
más veces. La sintaxis ara el ciclo while es:
while(condición){
cuerpodelciclo;
}
La condición es una expresión tipo boolean parecida al de una sentencia if. De nuevo
no puedes usar la convención de C/C++ donde 0 es verdadero y cualquier otro valor es
falso.
while(i<4){
i++;
System.out.println("Loop value is :"i);
}
56
javaHispano. Tu comunidad, tu lenguaje.
Así con el código siguiente siempre conseguirás por lo menos una ejecución del cuerpo
del ciclo no importando el valor de la variable i al entrar en el ciclo.
do{
System.out.println("value of : "+i);
} while (i <4);
Muchos programadores intentan usar el ciclo for en lugar del ciclo while cuando
pueden concentrar en una sola línea la creación, inicialización, prueba e incremento del
contador.
Los diseñadores de Java decidieron que ellos estaban de acuerdo con el gurú de la
programación Edsger Dijkstra quien escribió un artículo famoso titulado "Goto
considered harmful". Debido a que el uso indistinto de sentencias goto pueden dar como
resultado un código, cual espagueti, difícil de mantener, su uso se ha reducido y es
considerado como un mal estilo de programación. Hay situaciones donde sería útil y para
ayudar en esas situaciones Java ofrece las versiones etiquetadas y desetiquetadas de las
palabras clave break y continue.
Break y Continue
57
Tutorial para el examen de certificación: SCJP 1.2
}//End of if
for(int j=0; j <4 && i<3; j++){
System.out.println("j"+j);
}//End of for
}//End of for
}//end of Br method
Tienes que elegir que combinación de letras se mostrará con la ejecución del código. A
propósito el código “\n” (en caso de que aún no lo sepas) significa que se mostrará una
línea en blanco.
Es deseable a menudo, saltar de un ciclo interno a un ciclo externo dada una condición.
Puedes hacer esto etiquetando las sentencias break y continue.
Una etiqueta es simplemente una palabra no reservada seguida de dos puntos. Poniendo
el nombre de la etiqueta después del break o continue tu código saltará hasta la
etiqueta. Esto es conveniente para hacer condicional una parte de un ciclo. Por supuesto,
puedes hacer lo mismo con una sentencia if, pero una sentencia break es más
conveniente. No puedes saltar a otro ciclo o a otro método pero una vez terminado el
ciclo actual es muchas veces muy útil.
58
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 1)
¿Que pasará cuando intentes compilar y ejecutar el siguiente código en un método?
for(int i=0;i<5;){
System.out.println(i);
i++;
continue;
}
Pregunta 2)
¿Qué pasará cuando intentes compilar y ejecutar el siguiente código?
59
Tutorial para el examen de certificación: SCJP 1.2
1)
i 0 j 0
i 0 j 1
Continuando
2)
i 0 j 0
i 0 j 1
i 1 j 0
i 1 j 1
Continuando
3)
Error en tiempo de Compilación.
4)
i 0 j 0
i 0 j 1
i 1 j 0
i 1 j 1
i 2 j 1
Continuando
Pregunta 3)
¿Qué pasará cuando intentes compilar y ejecutar el siguiente código?
60
javaHispano. Tu comunidad, tu lenguaje.
for(int j=0;j<2;j++){
System.out.println("i="+i + " j= "+j);
if(i >0)
break outer;
}
}
System.out.println("Continuing with i set to ="+i);
}
2)
i=0 j= 0
i=0 j= 1
i=1 j= 0
3)
i=0 j= 0
i=0 j= 1
i=1 j= 0
i=2 j= 0
4)
i=0 j= 0
i=0 j= 1
Pregunta 4)
¿Qué pasará cuando intentes compilar y ejecutar el siguiente código?
int i=0;
while(i>0){
System.out.println("Value of i: "+i);
}
do{
System.out.println(i);
} while (i <2);
1)
Value of i: 0
Seguido de
0
1
2
2)
0
1
2
61
Tutorial para el examen de certificación: SCJP 1.2
3)
Value of i: 0
Seguido de una secuencia de 0’s
Respuestas
Respuesta 1)
Esta es una versión un tanto extraña de la sentencia for, pero es totalmente valida.
Respuesta 2)
3)
Error en tiempo de Compilación.
No puede saltar arbitrariamente a otro método, esto traerían consigo todo los males ya
manifestados sobre la sentencia goto.
Respuesta 3)
Respuesta 4)
Jyothi Krishnan
http://www.geocities.com/SiliconValley/Network/3693/obj sec2.html#obj6
62
javaHispano. Tu comunidad, tu lenguaje.
Richard Baldwin
http://www.Geocities.com/Athens/Acropolis/3797/Java026.htm#flow of control
Bruce Eckel
http://codeguru.earthweb.com/java/tij/tij0045.shtml#Heading131
63
Tutorial para el examen de certificación: SCJP 1.2
Objetivo 3.
Escribir código que haga un uso apropiado de las excepciones y las cláusulas del manejo
de excepciones (try, catch y finally), declarar métodos y sobreescribir métodos que
lanzen excepciones.
Las sentencias try y catch son parte del manejo de excepciones construido en Java. Ni
C/C++ " ni Visual Basic tienen un equivalente directo a las excepciones construidas en
Java. C++ soporta excepciones pero es de manera opcional, y Visual Basic soporta la
captura de errores con On Error/Goto.
Las excepciones en Java son construidas como parte del lenguaje. Por ejemplo si estas
realizando instrucciones de Entrada y Salida (I/O) debes manipular excepciones. Puedes
colocar por supuesto un manejador nulo que no haga nada. Lo siguiente es una pequeña
parte del código que he acostumbrado a usar con Borland/Inprise JBuilder para detener
temporalmente la salida de la consola y esperar que cualquier tecla sea presionada
import java.io.*;
public class Try{
En este caso no se hace nada cuando ocurre un error, pero el programador aun reconoce
que puede ocurrir un error. Si quitas las cláusulas try y catch el código simplemente no
compilará. El compilador sabe que los métodos de I/O pueden causar excepciones y exige
código para manejar esas posibles excepciones.
Esto es un poco más riguroso que en Visual Basic o en C/C++ que te permite lanzar
"sucia y rápidamente" programas que fingen que están en un mundo donde los errores no
64
javaHispano. Tu comunidad, tu lenguaje.
La Cláusula finally
Uno de las pocas ocasiones donde la cláusula finally no se ejecutará es si hay una
llamada a:
System.exit(0);
El examen es más propenso a dar ejemplos que incluyan declaraciones de retorno para
engañarte y hacerte pensar que el código retornará sin ejecutar la sentencia finally. No
te despistes, la cláusula finally casi siempre se ejecutará.
La cláusula try/catch debe capturar los errores en el orden natural de su jerarquía. Así,
no puedes intentar capturar la excepción Exception, que es mas general, antes de
intentar capturar la excepción IOException que es más específica.(NT: en otras
palabras, debes de intentar capturar primero las más especificas y luego las más
generales)
try{
DataInputStream dis = new DataInputStream(System.in);
dis.read();
}catch (Exception ioe) {
}catch (IOException e) { //error en tiempo de compilación
}finally{}
65
Tutorial para el examen de certificación: SCJP 1.2
import java.io.*;
class Base{
public static void amethod()throws FileNotFoundException{}
}
Pregunta 1)
66
javaHispano. Tu comunidad, tu lenguaje.
import java.io.*;
class Base{
public static void amethod()throws FileNotFoundException{}
}
protected ExcepDemo(){
try{
DataInputStream din = new DataInputStream(System.in);
System.out.println("Pausing");
din.readChar();
System.out.println("Continuing");
this.amethod();
}catch(IOException ioe) {}
}
Pregunta 2)
import java.io.*;
class Base{
public static void amethod()throws FileNotFoundException{}
}
67
Tutorial para el examen de certificación: SCJP 1.2
private ExcepDemo(){
try{
DataInputStream din = new DataInputStream(System.in);
System.out.println("Pausing");
din.readChar();
System.out.println("Continuing");
this.amethod();
}catch(IOException ioe) {}
}
Pregunta 3)
class Base{
public static void amethod()throws FileNotFoundException{}
}
68
javaHispano. Tu comunidad, tu lenguaje.
return false;
}
Pregunta 4)
import java.io.*;
class Base{
public static void amethod()throws FileNotFoundException{}
}
ExcepDemo(){
amethod(99);
}
}
69
Tutorial para el examen de certificación: SCJP 1.2
Respuestas
Respuesta 1)
Respuesta 2)
Respuesta 3)
OK, aquí me he salido un poco fuera del tema. Observa que lo que antes era un
constructor ahora tiene un valor del retorno. Esto lo convierte en un método ordinario y
por lo tanto no se llama cuando se crea una instancia de la clase.
Respuesta 4)
70
javaHispano. Tu comunidad, tu lenguaje.
y
http://www.geocities.com/Athens/Acropolis/3797/Java056.htm
Jyothi Krishnan en
http://www.geocities.com/SiliconValley/Network/3693/obj_sec2.html#obj7
71
Tutorial para el examen de certificación: SCJP 1.2
Puedes ser un programador de Java muy experimentado y nunca haber tenido que
familiarizarte con los detalles del recolector de basura. Incluso la expresión
recolección de basura es un poco rara. En este contexto significa la liberación de
memoria que se ha asignado y que ya ha sido usada por el programa. Cuando ya no se
necesita una parte de la memoria asignada ésta puede considerarse como basura, es decir
algo que ya no se necesita; y que simplemente está desordenando espacio útil.
Una de las grandes cualidades aclamadas de Java es que no tienes que preocuparte por la
recolección de basura. Si vienes de programar con Visual Basic puede parecerte absurdo
que algún sistema, por si mismo, no cuide este detalle. En C/C++ el programador tiene
que seguir, de forma manual, el rastro la asignación y desasignación de la memoria.
Como resultado de esto, las "fugas de memoria" son una gran fuente de errores difíciles
de rastrear. Ésta es una de las razones por las que algunas versiones de aplicaciones de
Microsoft como Word o Excel, se detienen apenas comienzan a ejecutarse. Las fugas de
memoria a la larga, finalmente hacen que el sistema entero se cuelgue y que te veas en la
necesidad de pulsar ese gran interruptor luminoso. En alguna parte, en esos centenares de
miles de líneas de código en C++, un programador asignó un bloque de memoria pero se
le olvido asegurarse de liberarla.
Por ejemplo, si escribes código que genere números muy grandes de objetos o de
variables te puede ser útil saber cuando se liberan las referencias.
Si lees algún newsgroups verás a personas informando en ocasiones de ciertas
aplicaciones Java que agotan los recursos y hacen que todo se caiga. Esto no estaba en el
folleto del SUN cuando lanzaron Java.
72
javaHispano. Tu comunidad, tu lenguaje.
A primera vista el termino finalización me suena un poco como a los destructores en C++
usados para limpiar los recursos antes de que se destruya un objeto. La diferencia es qué
en Java los recursos internos no necesitan ser liberados durante la finalización porque el
recolector de basura cuida la asignación de memoria. Sin embargo si tienes
recursos externos como un archivo de información, puedes usar la finalización para
liberarlos.
Una vez que una variable no es referenciada en mucho tiempo está disponible para ser
recolectada por el recolector de basura.
Las variables locales en los métodos pierden su alcance cuando el método que las ocupa
termina. A partir de ese momento esos métodos son elegibles para el recolector de
basura. Cada vez que el método vuelve a estar en el alcance del programa las variables
locales se vuelven a crear.
73
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 1)
¿Cual de las siguientes líneas tiene la sintaxis correcta para sugerir que la JVM ejecute la
recolección de basura?
1) System.free();
2) System.setGarbageCollection();
3) System.out.gc();
4) System.gc();
Pregunta 2)
¿Qué código puedes escribir para asegurarte que las variables tipo int son recolectadas en
un punto particular en este código?
1) System.gc();
2) System.free();
3) Fijar el valor de cada variable int a null.
4) Ninguno de los anteriores.
Respuestas
Respuesta 1)
4) System.gc();
Respuesta 2)
74
javaHispano. Tu comunidad, tu lenguaje.
75
Tutorial para el examen de certificación: SCJP 1.2
La sentencia package
La palabra package implica una colección de clases, algo parecido a una librería. En el
uso, un paquete es un poco semejante a un directorio. Si pones una declaración de un
paquete en un archivo éste será sólo visible a otras clases en el mismo paquete. Puedes
poner un comentario antes de la declaración del paquete pero nada más. Puedes encontrar
preguntas del examen en donde pongan una sentencia import antes de la declaración del
paquete.
import java.awt.*;
//Error: colocar una sentencia import antes de la declaración
//del paquete causará un error al compilar.
package MyPack;
public class MyPack{}
Si un archivo fuente tiene una sentencia package, ésta debe ponerse antes de
cualquier otra declaración aparte de los comentarios.
La sentencia package puede incluir la anotación punto para indicar la jerarquía del
paquete. Así el siguiente código compilará sin el error:
package myprogs.MyPack;
76
javaHispano. Tu comunidad, tu lenguaje.
Recuerda que si no pones una sentencia package al inicio del archivo fuente, se
considerará que éste forma parte del paquete predefinido que corresponde al directorio
actual.
La sentencia import
La sentencia import te permite usar una clase directamente con su nombre en lugar de
especificarla totalmente incluyendo el nombre completo del paquete al que pertenece. Un
ejemplo de esto es que a la clase java.awt.Button normalmente se le referencia
simplemente como Button, pero para ello requieres haber puesto al inicio del archivo
fuente la siguiente línea:
import java.awt.*;
Un archivo puede tener únicamente una clase con modificador public. Si intentas crear
un archivo con más de una clase pública el compilador te indicará un error específico. Un
archivo puede contener múltiples clases no públicas, pero ten presente que esto generara
distintos archivos .class separados por cada clase.
Las clases internas se introdujeron con el JDK 1.1 La idea es permitir la definición de una
clase dentro de otra, para que ésta pueda ser definida dentro de un método y para la
creación de clases internas anónimas. Esto tiene algunos efectos interesantes,
particularmente en la visibilidad.
class Outer{
class inner{}
}
77
Tutorial para el examen de certificación: SCJP 1.2
Outer.class
Outer$Inner.class
La definición de la clase interna es sólo visible dentro del contexto de la existente clase
Exterior. Así el siguiente código causará un error cuando se compile:
class Outer{
class Inner{}
}
class Another{
public void amethod(){
De modo que la clase Another no se podría crear, ya que, en ese contexto la clase
inner no existe. Ésta sólo puede existir en el contexto de una instancia de la clase
Outer. Así, el siguiente código se compilará sin problemas ya que sé esta instanciando la
clase Inner dentro del ámbito de la clase Outer.
class Outer{
public void mymethod(){
Inner i = new Inner();
}
public class Inner{}
}
Pero que pasa si el contexto de la instancia Outer no existe. Para entender mejor como
conseguir lo anterior, pensemos como podemos lograr el efecto anterior utilizando la
palabra clave this.
Así, si necesitas crear una instancia de la clase Inner en un método estático o en alguna
otra parte donde no tenga ámbito el objeto, puedes usar la palabra clave new como un
método que pertenece a una clase exterior.
class Outer{
public class Inner{}
}
78
javaHispano. Tu comunidad, tu lenguaje.
class another{
public void amethod(){
Outer.Inner i = new Outer().new Inner();
}
A pesar de mis locas explicaciones, encuentro poco intuitiva esta sintaxis y hasta yo me
olvido de ella cinco minutos después de aprendérmela. Es muy probable que encuentres
preguntas referentes a esto en el examen, así que préstale bastante atención.
Uno de los beneficios de las clases internas es que una clase interna generalmente
consigue acceso a los campos la clase que lo contiene(o una externa)
Al contrario de una clase externa, una clase interna puede ser privada o estática. Los
examinadores pueden hacer preguntas molestas como "¿Puede una clase interna ser
estática o privada?". Haciendo estática una clase interna, ésta tiene algunos efectos
interesantes con la manera en que se tienen acceso a los campos o miembros de la clase
que la contiene. El efecto de hacer estáticos los recursos se refleja en que sólo hay una
instancia de cualquier variable, no importa cuántas instancias se creen de la clase externa.
En esta situación ¿Cómo puede la clase interna estática saber qué variables puede acceder
de su clase externa no estática?. Por supuesto la respuesta es que no lo puede saber, y así
una clase interna estática no puede acceder variables de instancia de la clase que la
contiene.
Por supuesto, los métodos de una clase interna estática pueden acceder a cualquier campo
o miembro estático de la clase que lo contiene pero siempre será únicamente a una sola
instancia de cualquiera de esos campos.
Las clases internas se pueden crear dentro de los métodos. Esto es algo que las
herramientas de desarrollo de aplicaciones como JBuilder de Borland hacen
constantemente cuando generan un manejador de Eventos.
79
Tutorial para el examen de certificación: SCJP 1.2
buttonControl1.addMouseListener(new java.awt.event.MouseAdapter()
{
public void mouseClicked(MouseEvent e) {
buttonControl1_mouseClicked(e);
}
});
Fíjate en la palabra clave new que se encuentra justo después del primer paréntesis. Esta
indica que una clase interna anónima(sin nombre) está definiéndose dentro del método
addMouseListener. Esta clase normalmente podría definirse con un nombre que
podría hacerla más fácil de leer, pero cuando ese fragmento de código no se utiliza para
algún otro proceso en cualquier otra parte, darle un nombre no ayuda mucho.
Si creas tal código de manera manual, es fácil confundirte por el número de niveles de las
llaves y paréntesis. Observa cómo la estructura completa finaliza con punto y coma, ya
que es realmente ahí en donde finaliza la llamada al método.
Como podrías suponer una clase anónima no puede tener un constructor. Míralo de esa
manera, un constructor es un método sin valor de retorno y con el mismo nombre de la
clase. ¡Upss! Nosotros estamos hablando de clases sin nombres. Una clase anónima
puede heredar otra clase o implementar una única interface. Este límite peculiar no parece
ser tomado en cuenta en el examen.
Una clase definida dentro de un método puede acceder sólo a campos o miembros del
método que la contiene si éstos se han definido con el modificador final. Esto se debe a
que las variables definidas dentro de un método normalmente se consideran variables
automáticas; es decir, sólo existen mientras el método se está ejecutando. Los Campos o
miembros definidos dentro de una clase creada dentro de un método duran mas que el
método que la contiene.
Una clase definida dentro de un método solo puede acceder a campos con el
modificador final del método que la contiene
Debido que una variable con modificador final no puede ser cambiada por la JVM puedes
estar seguro que el valor permanecerá constante aun después de que el método exterior ha
dejado de ejecutarse. Es muy probable que encuentres preguntas referentes a esto en el
examen, incluso preguntas que cuestionen el estado de las variables pasadas como
parámetros al método.
80
javaHispano. Tu comunidad, tu lenguaje.
Las interfaces son la manera en que Java maneja la ausencia de la herencia múltiple.
Curiosamente Visual Basic tiene la palabra reservada interface y maneja el concepto
de manera similar a Java. El tema de las interfaces es conocido en ocasiones como
programación por contacto. Una interface se utiliza a través de la palabra clave
implements. Así, una clase puede declararse de la siguiente manera:
Pregunta 1)
}
public void amethod(){
final int i = 99;
int j = 6;
class CInMet{
public void mymethod(int q){
//Here
}//fin de mymethod
}//fin de CInMet
81
Tutorial para el examen de certificación: SCJP 1.2
}//fin de amthod
}
¿Cuales de las siguientes variables son visibles en la línea marcada con el comentario
//Here?
1)l
2)k
3)i
4)j
Pregunta 2)
1)
//A Comment
import java.awt.*;
class Base{};
2)
import java.awt.*;
package Spot;
class Base();
3)
//Another comment
package myprogs.MyPack;
public class MyPack{}
4)
class Base{}
import java.awt.*;
public class Tiny{}
Pregunta 3)
82
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 4)
Desde código que no tenga activa la referencia this, ¿Como puedes crear una instancia
de una clase interna?
Respuesta 1)
1) l
2) k
3) i
Una clase definida dentro de un método solo puede ver campos con el modificador
final desde el método que la contiene. Sin embargo, también puede ver los campos de
la clase que contiene al método que la contiene a ella, incluyendo campos privados. El
campo j no se definió como final.
Respuesta 2)
1)
//A Comment
import java.awt.*;
class Base{};
3)
//Another comment
package myprogs.MyPack;
public class MyPack{}
Respuesta 3)
Las clases anónimas no pueden tener un constructor. Las clases internas pueden definirse
como privadas.
Respuesta 4)
83
Tutorial para el examen de certificación: SCJP 1.2
Richard Baldwin
http://www.Geocities.com/Athens/7077/Java094.htm
y también
http://www.Geocities.com/Athens/7077/Java095.htm
Jyothi Krishnan
http://www.geocities.com/SiliconValley/Network/3693/obj_sec4.html#obj9
84
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 2.
Declarar la correspondencia entre los valores del arreglo pasado como argumento al
método main y los argumentos de la línea de comandos.
Nota: Este tema por sí solo difícilmente amerita ser tomado como un objetivo.
Pregunta 1)
85
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 1)
¿Cómo puedes recuperar los valores pasados desde la línea comandos al método main?
Respuestas
Respuesta 1)
3) one
Respuesta 2)
86
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 3.
Nota en este objetivo: Puedes asimilar fácilmente este objetivo en base a aprender las
palabras reservadas frecuentemente menos utilizadas y asegurándote no tomar en cuenta
a "falsos friendsπ" de otros lenguajes que puedes llegar a saber, particularmente C/C++.
El examen pone énfasis especial en el reconocimiento de las palabras reservadas.
• volatile
• transient
• native
Palabras reservadas
abstract boolean break byte case catch
char class const * continue default do
double else extends final finally float
for goto * if implements import instanceof
int interface long native new null
package private protected public return short
static super switch synchronized this throw
throws transient try void volatile while
Las palabras con asteriscos son reservadas y actualmente no son utilizadas. Observa que
todas las palabras reservadas están en minúsculas, así for es una palabra reservada pero
FOR no la es. Hay un debate acerca de que si null es una palabra reservada, pero
sugiero que para los propósitos del examen asumas que si la es.
π
NT: El autor utiliza esa expresión para referirse a la confusión que en ocasiones produce la palabra friend,
la cual es palabra reservada en C++, pero no en Java.
87
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 1)
1) double
2) Switch
3) then
4) instanceof
Pregunta 2)
1)volatile
2)sizeOf
3)goto
4)try
Respuestas
Respuesta 1)
1) double
4) instanceof
Nota que la letra mayúscula S en switch hace que ésta no sea una palabra reservada y la
palabra then es parte de Visual Basic pero no de Java.
Respuesta 2)
2)sizeOf
88
javaHispano. Tu comunidad, tu lenguaje.
Esta es una palabra reservada en C/C++ para determinar el tamaño de un dato primitivo
para una plataforma en particular. Debido a que los datos primitivos tienen el mismo
tamaño en todas las plataformas en Java ésta palabra reservada no se necesita.
89
Tutorial para el examen de certificación: SCJP 1.2
Objetivo 4.
Conocer el efecto de usar una variable o un elemento de un arreglo de cualquier tipo
cuando no se le ha hecho alguna asignación explicita.
Variables
class MyClass{
public static void main(String argv[]){
int p;
int j = 10;
j=p;
}
}
Esto puede verse como un cambio bienvenido de la tendencia de C/C++ de darle bastante
cuerda a una variable sin asignar dejando un valor arbitrario en p. Si p se hubiera
definido al nivel de clase se le habría asignado su valor predefinido y no se habría
generado algún error.
class MyClass{
static int p;
public static void main(String argv[]){
int j = 10;
j=p; System.out.println(j);
}
}
El valor predefinido para los tipos de datos numéricos es cero, para un boolean es
false y una referencia a un objeto es el único tipo de datos que tiene como valor
predefinido null.
90
javaHispano. Tu comunidad, tu lenguaje.
Arreglos
Aprender esta parte del objetivo requiere comprender una sencilla regla. El valor de los
elementos de un arreglo de cualquier tipo base siempre se inicializará con un valor
predefinido, dondequiera que se defina el arreglo. No importa si el arreglo se define
a nivel de clase o método, a los valores del arreglo siempre se le pondrán sus valores
predefinidos. Una pregunta que puedes hacerte es ¿Qué contendrá un elemento en
particular de un arreglo sin asignar?. A menos que el arreglo sea de objetos, la
respuesta será distinta de null.
Pregunta 1)
Dado el siguiente código, ¿Qué contendrá el elemento b[5]?
1) 0
2) null
91
Tutorial para el examen de certificación: SCJP 1.2
3) ""
4) Ninguna de estas opciones
Pregunta 2)
MyCon(){
int[] mycon= new int[5];
}
1) 0
2) null
3) ""
4) Ninguna de estas opciones
Pregunta 3)
1)Se mostrará 99
2)Se mostrará 0
3)Se generará un error al compilar
4)Se generará un error al ejecutar
Pregunta 4)
92
javaHispano. Tu comunidad, tu lenguaje.
String s;
public static void main(String argv[]){
MyField m = new MyField();
m.amethod();
}
void amethod(){
System.out.println(s);
}
}
Respuestas
Respuesta 1)
System.out.println(b[5])
Respuesta 2)
1)0
Respuesta 3)
Respuesta 4)
93
Tutorial para el examen de certificación: SCJP 1.2
Una variable creada en el nivel de clase siempre tendrá un valor por omisión. El valor por
omisión para una referencia a un objeto es null y el método toString implícitamente
llamado con System.out.println mostrará null.
94
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 5.
Definir el rango de todos los tipos de datos primitivosφ, declarar valores literales para
Strings y todos los tipos primitivos usando todos los formatos permitidos, conocer las
bases numéricas y sus representaciones.
Éste es uno de los ligeramente molestos, pero bastante fácil, objetivos a cubrir. Puedes
escribir una gran cantidad de código Java sin conocer el rango de los tipos primitivos
pero familiarizarte con ellos no debe tomarte mucho tiempo. Ten cuidado con este tema
para que puedas usar todos los formatos, y no pases por alto el formato octal.
Cuando este objetivo pide el rango de los tipos de datos primitivos asumo que para
representarlo sólo se requiere el número 2 elevado a la potencia apropiada en lugar del
número que representa. En mi mente hay sólo tres tipos enteros a aprender ya que, en mi
experiencia basada en PC. El tamaño de un byte es intuitivo: 8 bits.
Hay tres maneras de declarar un literal entero. Como esperabas, por defecto, es un valor
decimal. Aquí están las opciones
φ
NT: Algunos documentos utilizan el termino “sencillos” o “básicos” en lugar de “primitivos”.
95
Tutorial para el examen de certificación: SCJP 1.2
Si compilas y ejecutas esta pequeña clase obtendrás en cada ocasión el valor 18.
Roberts y Heller describen 6 maneras de declarar literales enteros, ya que para Java la
letra X para la declaración de un hexadecimal extraordinariamente no es sensible a
mayúsculas, observa que no se utilizan las letras de la A a la F para la notación
hexadecimal. A mí me es mas más fácil recordar únicamente las tres maneras descritas
anteriormente y que las letras no son sensibles a mayúsculas.
96
javaHispano. Tu comunidad, tu lenguaje.
Ten presente que el tipo de dato predefinido para un literal con un componente decimal
es un double y no un long. Esto es ligeramente confuso puesto que podrías pensar que
el tipo predefinido para un número de coma flotante debería ser un float. Puedes
encontrar preguntas en el examen similares a la siguiente:
float i = 1.0;
Tu intuición debería decirte que esto debe compilarse sin problemas. Desgraciadamente
el examen no esta diseñado para probar su intuición. Esto causará un error en tiempo de
compilación ya que estas intentando asignar un double a un float. Puedes arreglar este
código de la manera siguiente:
float i = 1.0F;
o incluso:
Los tipos de datos primitivos boolean y char son un poco curiosos. Si tienes
experiencia programando con C/C++ presta atención particularmente al tipo boolean y a
asegúrate de no traer contigo "falsos friends" de cualquiera de estos lenguajes. A un tipo
boolean no se le puede asignarse otro valor distinto de true o false. Los valores
true o false no corresponden al 0, al -1 o a algún otro número.
97
Tutorial para el examen de certificación: SCJP 1.2
Un dato de tipo boolean únicamente puede recibir los valores de true o false,
y no se le puede asignar un número como –1 o 0.
El tipo de dato primitivo char es el único tipo de dato primitivo sin signo. El tipo char
se usa para denotar un carácter Unicode. Unicode es un código alternativo al ASCII
que almacena caracteres en 2 bytes en lugar de 1 byte como lo hace el código ASCII.
Esto te permite representar 65K caracteres, qué aunque no es una cantidad
suficientemente grande para cubrir todas las escrituras del mundo, es mejor que los 255
caracteres que nos proporciona el código ASCII. La internacionalización es un tema
completo por si mismo, y el hecho de que puedas representar caracteres en chino o
Vietnamés, no significa que se desplegarán correctamente si tienes un sistema operativo
en inglés normal.
char a = 'z';
Todo esto es funcional en mi pequeño mundo basado en el Ingles pero como Java es un
sistema mundial un char puede contener cualquiera de los caracteres disponible en el
sistema Unicode. Esto se hace usando cuatro dígitos hexadecimales precedidos por \u,
con la expresión completa encerrada con comillas simples.
char c = ‘\u0020’;
Si asignas un número sencillo a un char, éste será tomado como un carácter alfabético.
Así que el siguiente código mostrará la letra A(valor 65 del código ASCII) seguido de
una espacio en blanco.
98
javaHispano. Tu comunidad, tu lenguaje.
El tipo String no es un tipo de dato primitivo pero es tan importante que en ciertas
áreas Java lo trata como si lo fuera. Uno de estos rasgos es la habilidad de declarar
literales String en lugar de usar new para instanciar una copia de la clase.
Las literales String son bastante sinceras. Asegúrate de recordar que las literales
String son encerradas con comillas dobles mientras que un literal char utiliza comillas
simples.
Así:
Pregunta 1)
1) float f=10f;
2) float f=10.1;
3) float f=10.1f;
4) byte b=10b;
Pregunta 2)
1) short myshort=99S;
2) String name='Excellent tutorial Mr Green';
3) char c=17c;
4) int z=015;
Pregunta 3)
99
Tutorial para el examen de certificación: SCJP 1.2
1) boolean b=-1;
2) boolean b2=false;
3)int i=019;
4) char c=99;
Respuestas
Respuesta 1)
1) float f=10f;
3) float f=10.1f;
Respuesta 2)
4)int z=015;
Las letras c y s no existen como indicadores literales y un String debe estar encerrado
por comillas dobles y no por comillas simples como en el ejemplo.
Respuesta 3)
2) boolean b2=false;
4) char c=99;
100
javaHispano. Tu comunidad, tu lenguaje.
101
Tutorial para el examen de certificación: SCJP 1.2
Objetivo 1
El operador instanceof
El operador instanceof es una bestia extraña, desde mi punto de vista debería ser un
método en lugar de un operador. Probablemente has escrito bastante código con Java y no
has tenido la necesidad de usarlo, pero para propósitos del examen necesitas conocerlo.
Este operador retorna un valor booleano como resultado a una prueba sobre un tipo de
clase en tiempo de ejecución. Y efectivamente, como estas pensando, se usa para
preguntar:
Sin embargo, pueden surgir situaciones donde únicamente tienes acceso a una referencia
de un objeto, el cual se refiere a algo que esta más arriba o más abajo en la jerarquía de
clases del programa. Así puedes tener un método que tome como parámetro un
componente que puede referirse a un botón, a una etiqueta o a cualquier otra cosa. En
estas circunstancias, el operador instanceof se usa para examinar el tipo del objeto,
realizar una comparación y una conversión y así llamar al método más apropiado. El
siguiente código ilustra un ejemplo de esto:
import java.awt.*;
102
javaHispano. Tu comunidad, tu lenguaje.
}//End of main
El operador +
Como esperabas, el operador + adiciona 2 números entre si. Así la siguiente línea de
código
mostrará 10:
int p=5;
int q=5;
System.out.println(p+q);
String s = "One";
String s2 = "Two"
String s3 = "";
s3 = s+s2;
System.out.println(s3);
103
Tutorial para el examen de certificación: SCJP 1.2
El resultado será "OneTwo", observa que no hay espacios entre las dos cadenas unidas.
Bajo ciertas circunstancias Java realiza una llamada implícita el método toString.
Este
método, como su nombre lo dice, intenta convertir a un String a el objeto que lo llama.
Para un entero con valor 10, la llamada a toString retornara la cadena "10".
int p = 10;
String s = "Two";
String s2 = "";
s2 = s + p;
System.out.printlns(s2);
el resultado será:
Two10
Un booleano única y exclusivamente puede recibir otro valor de tipo booleano. Para los
programadores C/C++, recuerden que esto significa que a un booleano no se le puede
asignar -1 o 0, ya que en Java un booleano no es substituible por el numero cero o un
valor
distinto de cero.
Con esta principal excepción en el tipo de datos boolean, el principio general para
entender este objetivo esta en saber que las conversiones por "ensanchamiento" están
permitidas en Java, siempre y cuando no impliquen exactitud. Por ensanchamiento quiero
decir que una variable como un byte que ocupa 1 byte (ocho bits) puede asignarse a una
variable que ocupa más bits como por ejemplo un int.
byte b= 10;
int i = 0;
b = i;
104
javaHispano. Tu comunidad, tu lenguaje.
int j=0;
Integer k = new Integer(99);
j=k; //Asignacion ilegal de un objeto un tipo primitivo.
Por supuesto, puedes realizar una conversión forzada para hacer que una variable
se ajuste a un tipo de datos mas estrecho, Esto a menudo no es aconsejable ya que el
resultado perderá precisión, pero es valido si realmente lo quieres hacer. Java utiliza la
convención de C/C++ encerrando entre paréntesis () el tipo de datos al que se quiere
convertir. Por lo tanto el siguiente código se compilara y ejecutara sin problemas:
el resultado es
-120
Cuando asignamos referencias de objetos, otra regla general es que puedes realizar la
asignación de abajo hacia arriba en la jerarquía de clases, pero no de arriba hacia abajo.
Puedes ver esto de la siguiente manera. Si tu asignas una instancia de una clase hija a la
105
Tutorial para el examen de certificación: SCJP 1.2
clase Base, Java sabrá qué métodos están en la clase hija. Sin embargo una clase hija
puede tener métodos adicionales de los que le proporciona la clase Base. Puedes
solucionar este problema usando la conversión forzada.
El siguiente ejemplo muestra que ocurre cuando fuerzas la asignación de una referencia
de un objeto hacia una clase de jerarquía superior:
class Base{}
}
}
Odio un poco esto de trabajar con desplazamientos de bits. Ya que implica que llenes tu
mente con una capacidad no intuitiva que es trabajar con números infinitamente
pequeños, números que un programador quizá nunca utilizara. Pero debido a que todas
las razones para aprenderlo son por que pueden aparecer en el examen, es mejor tratar el
tema, pues es poco probable que lo aprendas de otra manera. El resultado de usar estos
operadores puede sorprenderte.
Para entenderlos tienes que tener un pensamiento binario bastante fluido, por ejemplo
conocer el valor de un bit en cada posición:
32, 16, 8, 4, 2, 1
Los programadores C/C++, pueden estar tranquilos ya que la manera de trabajar del
operador de desplazamiento de bits en Java es menos ambigua que en C/C++. En C/C++
el desplazamiento hacia la derecha puede ser con signo o sin signo dependiendo de la
implementación del compilador. Si vienes de programar con Visual Basic, bienvenido a
la programación de bajo nivel.
106
javaHispano. Tu comunidad, tu lenguaje.
Observa que el objetivo únicamente pide que comprendas el resultado de aplicar estos
operadores sobre valores de tipo int. Esto es también aplicable a un byte o a un
short, particularmente si el valor es negativo, ya que se puede tener algunos resultados
demasiado inesperados.
Para números positivos los resultados son bastante predecibles. Así el desplazamiento
con signo para números positivos da los siguientes resultados:
int x = 14;
int y = 0;
y = x >>2;
System.out.println(y);
El resultado será 3,se pierde un bit y el resto del patrón de bits se inclina a la derecha
int x = 14;
int y = 0;
y = x <<2;
System.out.println(y);
El resultado será 56
107
Tutorial para el examen de certificación: SCJP 1.2
Si toda esta charla sobre patrones de bits y representación en complemento a dos "hace
que tu cabeza heche humo", podrías preferir pensar el desplazamiento de bits como un
proceso repetitivo de multiplicación o división por dos. Esta aproximación funciona bien
hasta que empiezas a desplazar un numero negativo a la derecha, de modo que pierde bits
del lado derecho.
System.out.println(-1 >>>1);
El resultado es el siguiente:
2147483647
El examen probablemente no te pedirá que des el resultado exacto pero podría darle
algunas alternativas como 0, -1, etc. y tendrás que elegir el resultado mas aproximado.
Si acabas de leer que el deslazamiento sin signo no toma en cuenta el bit del signo, el
resultado de la línea anterior, que es -1, puede ser una sorpresa. La razón es que el
modulo 32 se realiza sobre el operando antes del desplazamiento. Así, si divides 32 entre
32 obtienes 0 y si realizas un desplazamiento sin signo de cero lugares hacia la derecha
tendrás todavía como valor -1. No deseches esto como si fuera una peculiaridad
irrelevante ya que puede venir en el examen.
http://www.jchq.net/applets/BitShift/BitShiftAr.html
Applet BitShift
108
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 1)
interface IFace{}
class CFace implements IFace{}
class Base{}
1) o1=o2;
2) b=ob;
109
Tutorial para el examen de certificación: SCJP 1.2
3) ob=b;
4) o1=b;
Pregunta 2)
Dadas las siguientes declaraciones:
String s = "Hello";
long l = 99;
double d = 1.11;
int i = 1;
int j = 0;
1) j=i <<s;
2) j=i<<j;
3) j=i<<d;
4) j=i<<l;
Pregunta 3)
char c = 'c';
int i = 10;
double d = 10;
long l = 1;
String s = "Hello";
1) c=c+i;
2) s+=i;
3) i+=s;
4) c+=s;
Pregunta 4)
System.out.println(-1 >>>1);
1) 0
2) -1
3) 1
110
javaHispano. Tu comunidad, tu lenguaje.
4) 2147483647
Pregunta 5)
System.out.println(1 <<32);
1) 1
2) -1
3) 32
4)-2147483648
Pregunta 6)
1) System.out.println(1+1);
2) int i= 2+'2';
3) String s= "on"+'one';
4) byte b=255;
Respuestas
Respuesta 1)
1)o1=o2;
2)b=ob;
4)o1=b;
Respuesta 2)
2)j= i<<j;
4)j=i<<l;
Respuesta 3)
2)s+=i;
Respuesta 4)
4) 2147483647
Respuesta 5)
111
Tutorial para el examen de certificación: SCJP 1.2
1) 1
Con el desplazamiento a la izquierda, los bits son "envueltos alrededor" del patrón de
bits.
Así, el resultado de:
System.out.println(1 <<31);
Será:
-2147483648
Respuesta 6)
1) System.out.println(1+1);
2) int i= 2+'2';
La opción 3 no es valida, ya que las comillas simples sirven para indicar un solo caracter
constante y no a una cadena. La opción 4 no compilara ya que el valor 255 esta fuera del
rango de un byte.
Richard Baldwin
http://home.att.net/~baldwin.dick/Intro/Java022.htm#bitwiseoperations
No encontré nada relacionado con el operador instanceof
112
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 2.
El método equals puede verse como la realización de una comparación profunda del
valor de un objeto, por el contrario el operador = = realiza una comparación poco
profunda. El método equals compara lo que un objeto apunta en lugar del apuntador en
si (esto si consideramos que java tiene punteros ).
El método equals retorna un valor primitivo de tipo boolean. Esto significa que se
puede usar para manejar sentencias if, while u otra sentencia de enciclamiento. Puede
usarse también en lugar del operador = = con una primitiva. La utilización del método
equals y el operador = = tiene extraños efectos laterales cuando se usa para comparar
Strings. Esta es una de las ocasiones en donde la naturaleza inmutable de los Strings,
y la manera en que java maneja esta característica, puede crearte confusión.
Existen 2 maneras para crear un String en Java. Una de ellas implica la utilización del
operador new. Así, normalmente un String se crea de la siguiente manera:
String s = "GoodBye";
Generalmente la diferencia entre estas dos maneras de crear un String es mínima, pero
en el examen pueden haber preguntas que te exijan reconocer muy bien esta diferencia.
La creación de 2 cadenas con la misma secuencia de letras sin ocupar la palabra clave
new creara 2 apuntadores a la misma cadena en el pool de Strings de Java. El pool
de Strings es la manera en que Java mantiene los recursos. Veamos lo siguiente para
comprender mejor lo anterior:
String s = "Hello";
String s2 = "Hello";
if (s = = s2){
113
Tutorial para el examen de certificación: SCJP 1.2
Tomando en cuenta lo que vimos en el objetivo anterior, esperarías que el primer mensaje
"Equal without new operator", nunca se mostrara ya que s y s2 son objetos
distintos, y además el operador = = examina lo que apunta a un objeto, no su valor. Sin
embargo, debido a la manera en que Java maneja los recursos con la re-utilización de
cadenas idénticas que son creadas sin el operador new, s y s2 tiene la misma "direccion"
y en consecuencia el código mostrará el mensaje:
Por otro lado, en el segundo par de Strings t y u, el operador new fuerza a Java a crear
cadenas separadas, es decir, dos objetos distintos. Y debido a que el operador = =
únicamente compara la dirección del objeto, y no su valor, t y u tienen diferentes
direcciones y así el mensaje "Equal with new operator" nunca se mostrará.
114
javaHispano. Tu comunidad, tu lenguaje.
Ejemplo:
Como un tema aparte sobre el uso de boolean y Boolean, una vez que te familiarices
con la sentencia if en Java te darás cuenta que no puedes realizar la conversión implícita
tan apreciada por los programadores C/C++. Esa conversión es del tipo:
int x =1;
if(x){
//realiza algo, pero no en Java
}
Esto no funcionara en Java porque el parámetro para la sentencia if debe ser una
evaluación booleana, ya que Java no tiene el concepto de C/C++ en donde cualquier valor
no nulo se considera verdadero. Sin embargo puedes realizar lo siguiente en Java :
boolean b1=true;
if(b1){
//do something in java
}
Debido al diseño fundamental de Java una instancia de cualquier clase es también una
instancia de la clase java.lang.Object. Examinaremos esto utilizando el método
toString. Para la clase Object, el método toString simplemente retorna la dirección
de memoria. Así el resultado es el equivalente de ejecutar una comparación con el
operador = =. Como Java no esta diseñado para manipular direcciones de memoria o
apuntadores, ésta no es una operación particularmente útil.
115
Tutorial para el examen de certificación: SCJP 1.2
System.out.println(m2);
if (m1.equals(m2)){
System.out.println("Equals");
}else{
System.out.println("Not Equals");
}
}
java.lang.Object@16c80b
java.lang.Object@16c80a
Not Equals
Estos valores son direcciones de memoria , y probablemente no tienen nada que ver con
lo que tu necesitas.
Pregunta 1)
¿Que pasará cuando intentes compilar y ejecutar el siguiente código?
116
javaHispano. Tu comunidad, tu lenguaje.
1)Error al compilar
2)No se mostrará ningún mensaje
3)Se mostrará únicamente el mensaje "String equals"
4)Se mostrará el mensaje "String equals", seguido de "true"
Pregunta 2)
¿Que pasará cuando intentes compilar y ejecutar el siguiente código?
1)Error al compilar
2)Se mostrará únicamente "String equals"
3)Se mostrará "String equals" seguido de "Boolean Equals"
4)Se mostrará únicamente "Boolean Equals"
Pregunta 3)
¿Cuál es el resultado de intentar compilar y ejecutar el siguiente código?
1)Error al compilar
2)Mostrará "Equals"
3)No mostrará nada
4)Error al ejecutarse
117
Tutorial para el examen de certificación: SCJP 1.2
Respuestas
Respuesta 1)
1)Error al compilar
la línea b1.equals causará un error debido a que b1 es un valor primitivo y los valores
primitivos no tienen métodos. Si b1 hubiera sido creado son la clase Boolean entonces
si podrías ocupar el método equals.
Respuesta 2)
Respuesta 3)
2)Mostrará "Equals"
o1=o2
Michael Thomas
http://www.michael-thomas.com/java/JCP_Operators.htm#equals()
118
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 3.
En una expresión que involucre a los operadores &,|,&&,||, y variables, conocer el estado
de los valores que son evaluados con estos operadores y el valor de la expresión.
Es fácil olvidarse cuales son los símbolos que significan una operación lógica y cuales
significan operaciones a nivel de bits, asegúrate de reconocer la diferencia para el
examen.
Si eres nuevo con el uso de estos operadores vale la pena que te asegures no confundirte
con los operadores a nivel de bits y los operadores lógicos.
Los operadores lógicos (&&, ||) tienen un ligero efecto peculiar en una operación lógica
llamado "corto circuito”, como ocurre de manera similar, en C/C++. Esto quizá te pueda
sorprender si vienes de programar con Visual Basic ya que Visual Basic evalúa todos los
operandos. En Java esto tiene sentido si consideras que en una operación AND, si el
primer operando es falso ya no es necesario evaluar el segundo operando, el resultado
final será, con certeza, falso. Lo mismo ocurre con el operador lógico OR, si el primer
operando ha resultado verdadero, el cálculo global será verdadero ya que sólo un
operando del OR debe retorna verdadero para que el resultado final sea verdadero. Esto
puede traer código un efecto especial con esos cálculos reducidos que dependen de
efectos laterales.
El resultado de este código será "Not equal 10". Esto muestra que la operación
Ouput+=10 jamás será realizada debido a que el proceso se detiene después de que se
evalúa la primera operación, debido a que retorna falso, y al estar aplicando el operador
119
Tutorial para el examen de certificación: SCJP 1.2
Esto a veces puede ser conveniente cuando realmente no quieras procesar otras
operaciones si una de ellas retorna falso, pero puede tener un efecto lateral inesperado si
no estás completamente familiarizado con el uso de estos operadores.
Los operadores | y & se aplican para realizar operaciones AND y OR a nivel de bits.
Puedes encontrarte preguntas en el examen que te den números en decimal y te pidan que
realices operaciones AND o OR a nivel de bits. Para hacer esto, necesitas familiarizarte
con la conversión de números decimales a binarios y conocer que ocurre con el patrón de
bits.
3|4
El patrón binario para el decimal 3 es 11, el patrón binario para 4 es 100, para realizar
una operación OR a nivel de bits, cada bit es comparado con el bit que se encuentra en la
misma posición del otro número. Si alguno de los bits es 1 el bit del numero resultante,
en la posición que se esta comparando, es también 1. Así para esta operación el resultado
será:
011
100
------
111
y 111 es 7 en decimal.
Los objetivos no especifican que conozcas la operación XOR a nivel de bits. realizada
con el operador ˆ.
Pensando en binario
Si no te siente muy cómodo pensando en binario (yo me siento mucho mas cómodo
pensando en decimal), puedes querer hacer algunos ejercicios para ayudarte a dominar
este tema y también el relacionado con los operadores de desplazamiento de bits. Si estás
120
javaHispano. Tu comunidad, tu lenguaje.
ejecutando Windows puedes encontrar útil usar la calculadora que proporciona este
sistema operativo en modo científico. Para hacer esto solo elige la opción Ver y cambiar
del modo Estándar predefinido al modo científico. En modo científico puedes cambiar
entre ver los números en formato decimal y binario, esto despliega el patrón de bits de los
números.
4
1000000
Pregunta 1)
¿Que pasará cuando intentes compilar y ejecutar el siguiente código?
int Output=10;
boolean b1 = false;
if((b1= =true) && ((Output+=10)==20)){
System.out.println("We are equal "+Output);
}else{
System.out.println("Not equal! "+Output);
}
1)Error al compilar, por intentar realizar una comparación binaria sobre tipos de datos
lógicos
2)Se compilara y mostrará la cadena "We are equal 10"
121
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 2)
Qué mostrará la siguiente línea de código
System.out.println(010|4);
1) 14
2) 0
3) 6
4) 12
Pregunta 3)
1)
int i=10;
int j = 4;
System.out.println(i||j);
2)
int i=10;
int j = 4;
System.out.println(i|j);
3)
boolean b1=true;
boolean b2=true;
System.out.println(b1|b2);
4)
boolean b1=true;
boolean b2=true;
System.out.println(b1||b2);
Respuestas)
Respuesta 1
4)Se compilara y mostrará la cadena "Not equal! 10"
Respuesta 2)
122
javaHispano. Tu comunidad, tu lenguaje.
4)12
La respuesta a esta pregunta requiere que conozcas la notación octal, el cero que antecede
al primer numero indica que dicho número esta en notación octal, 010 es la notación octal
para el numero 8 decimal.
Así, la instrucción:
System.out.println(010|4)
es equivalente a:
System.out.println(8|4);
1000
0100
-----
1100
y 1100 en decimal es 12
Repuesta 3)
2,3,4
Richard Baldwin
http://home.att.net/~baldwin.dick/Intro/Java022f.htm
123
Tutorial para el examen de certificación: SCJP 1.2
Objetivo 4
Determinar los efectos sobre los objetos y los valores primitivos al pasarlos como
variables en métodos al aplicarles asignaciones u otras modificaciones dentro del método.
El objetivo parece estarte pidiendo que entiendas lo que ocurre cuando pasas un valor a
un método. Si el código dentro del método modifica el valor de la variable, ¿El cambio es
visible aun fuera del método?
class ValHold{
public int i = 10;
}
public class ObParm{
public static void main(String argv[]){
ObParm o = new ObParm();
o.amethod();
}
public void amethod(){
ValHold v = new ValHold();
v.i=10;
System.out.println("Before another = "+ v.i);
another(v);
System.out.println("After another = "+ v.i);
}//End of amethod
public void another(ValHold v){
v.i = 20;
System.out.println("In another = "+ v.i);
}//End of another
124
javaHispano. Tu comunidad, tu lenguaje.
El resultado será:
Before another = 10
In another = 20
After another = 20
Observa como el valor de la variable i ha sido modificado. Si java siempre pasa por
valor, ¿Cómo se ha modificado? Bueno, el método recibió una copia del manejador o
referencia del objeto pero esa referencia actúa como un apuntador al valor real del objeto
y las modificaciones se reflejan en los campos a los que apunta. Esto es parecido a la des-
referenciación automática de punteros en C/C++.
Cuando pasas valores primitivos a métodos, estos pasan por valor. El método obtiene su
propia copia para utilizarla y en consecuencia, cualquier modificación no se refleja fuera
del método. Veamos el siguiente ejemplo:
La salida será:
Before another i= 10
In another i= 20
After another i= 10
125
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 1)
Dado el siguiente código:
class ValHold{
public int i = 10;
}
public class ObParm{
public static void main(String argv[]){
ObParm o = new ObParm();
o.amethod();
}
public void amethod(){
int i = 99;
ValHold v = new ValHold();
v.i=30;
another(v,i);
System.out.println(v.i);
}//End of amethod
public void another(ValHold v, int i){
i=0;
v.i = 20;
ValHold vh = new ValHold();
v = vh;
System.out.println(v.i+ " "+i);
}//End of another
}
1)10,0, 30
2)20,0,30
3)20,99,30
4)10,0,20
Respuestas
Respuesta 1
4)10,0,20
126
javaHispano. Tu comunidad, tu lenguaje.
127
Tutorial para el examen de certificación: SCJP 1.2
Objetivo 1)
Así, un gato ES UN tipo de animal y un gato TIENE UNA cola. Desde luego la
distinción puede ser difusa. Si fueras un zoólogo y conocieras los nombres correctos para
los grupos de tipos de animales podrías decir que un gato ES UN:
Largapalabraenlatínparagrupodeanimalesconcolas
Las preguntas del examen tienden a ser del tipo en las que se te da un texto que describe
una jerarquía potencial y te hace preguntas como: qué debería ser un campo y qué debería
ser un nuevo tipo de clase como hijo. A primera vista estas cuestiones pueden parecer
complejas, pero son bastante obvias si las lees con cuidado
Encapsulamiento
128
javaHispano. Tu comunidad, tu lenguaje.
Por ejemplo, si cambiaras el color de una figura podrías crear un par de métodos de la siguiente
manera
El enfoque estándar al usar el ejemplo de arriba de color sería hacer privado el campo
CBack de Color. Un campo privado sólo es visible desde la clase en cuestión. Esto
significa que un programador no puede accidentalmente escribir código que cambie el
valor desde otra clase. Esto puede ayudar a reducir la introducción de errores.
La separación de la interfaz y la implementación hace más fácil modificar el código de
una clase sin afectar a otro código que lo pueda usar.
Para el diseñador de clases esto lleva a la posibilidad de modificar una clase, sabiendo
que no estropeará programas que la usen. Un diseñador de clases puede añadir rutinas de
comprobación adicionales para realizar “chequeos de cordura” relacionados con
modificaciones de campos. He trabajado en proyectos de seguros en los que era posible
que el cliente tuviera una edad menor de cero. Si un valor así se guarda en un campo
simple como un entero, no hay un lugar obvio en el que se puedan guardar rutinas de
comprobación. Si la edad es accesible sólo vía métodos set y get será posible insertar
comprobaciones de edades cero o negativas de forma que no quede afectado código
existente. Desde luego a medida que el desarrollo continúa se pueden descubrir más
situaciones que necesiten chequeo.
Para el usuario final de la clase esto significa que no tiene que comprender el
funcionamiento interno y que se le presenta una interfaz claramente definida para
manejar los datos. El usuario final puede tener la confianza de que las actualizaciones en
el código de la clase no romperán su código existente.
129
Tutorial para el examen de certificación: SCJP 1.2
}
Nótese cómo el tipo de la referencia es la variable b es la clase Base pero el tipo de la
clase de hecho es RType. La llamada a amethod invocará la versión en RType pero la
salida b.i referenciará el campo i en la clase Base.
Pregunta 1)
Supón que te han entregado el siguiente diseño:
“Una persona tiene nombre, edad, dirección y sexo. Estás diseñando una clase para
representar un tipo de persona llamada paciente. Este tipo de persona puede recibir un
diagnóstico, tener cónyuge y está vivo". Dado que la clase persona ya ha sido creada, qué
de entre lo siguiente sería apropiado incluir cuando se diseñe la clase paciente?
130
javaHispano. Tu comunidad, tu lenguaje.
1)fecha de registro
2)edad
3)sexo
4)diagnóstico
Pregunta 2)
¿Qué sucederá cuando intentes compilar y ejecutar el siguiente código?
class Base {
int i=99;
public void amethod(){
System.out.println("Base.amethod()");
}
Base(){
amethod();
}
}
public class RType extends Base{
int i=-1;
public static void main(String argv[]){
Base b = new RType();
System.out.println(b.i);
b.amethod();
}
public void amethod(){
System.out.println("RType.amethod()");
}
1)
RType.amethod
-1
RType.amethod
2)
RType.amethod
99
RType.amethod
3)
99
RType.amethod
131
Tutorial para el examen de certificación: SCJP 1.2
4)
Error en tiempo de compilación
Pregunta 3)
Tu jefe diseñador de software te ha mostrado un esquema del nuevo sistema de partes de
ordenador que está a punto de crear. En lo alto de la jerarquía está una clase llamada
Ordenador y bajo ella hay dos clases hijas. Una se llama LinuxPC y la otra WindowsPC.
La principal diferencia entre las dos es que una ejecuta el Sistema Operativo Linux y la
otra ejecuta el sistema Windows (desde luego otra diferencia es que una necesita ser
rearrancada constantemente y la otra funciona fiablemente). Bajo WindowsPC hay dos
subclases, una llamada Server y la otra llamada Workstation. ¿Cómo valorarías el
trabajo de tu diseñador?
Pregunta 4)
Dada la siguiente clase
class Base{
int Edad=33;
}
Pregunta 5)
¿Cuáles de los siguientes son beneficios de la encapsulación?
1)Todas las variables pueden manipularse como objetos en vez de con primitivas
2)Haciendo todas las variables protegidas están protegidas de una corrupción accidental
3)Se puede cambiar la implementación de una clase sin estropear el código que la usa
4)Hacer todos los métodos protegidos previene la corrupción accidental de datos.
132
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 6)
Nombre tres características principales de la Programación Orientada a Objetos:
1)Encapsulación, ligadura dinámica, polimorfismo
2)Polimorfismo, sobrecarga, redefinición
3)Encapsulación, herencia, ligadura dinámica
4)Encapsulación, herencia, polimorfismo
Pregunta 7)
¿Como implementas la encapsulación en una clase?
1)Haciendo todas las variables protegidas y sólo permitiendo el acceso vía métodos
2)Haciendo todas las variables privadas y sólo permitiendo el acceso vía métodos
3)Asegurando que todas las variables son representadas por clases envolventes
4)Asegurando que todas las variables son accedidas a través de métodos de una clase ancestra.
Respuestas
Respuesta 1)
1) fecha de registro
4) diagnóstico
Respuesta 2)
2)
RType.amethod
99
RType.amethod
Respuesta 3)
2) Pedir un rediseño de la jerarquía cambiando el Sistema Operativo a un campo de la
clase antes que a un tipo de clase
Respuesta 4)
133
Tutorial para el examen de certificación: SCJP 1.2
3) Definir la variable Edad como privada y crear un método get que la devuelva y un
método set que la actualice.
Respuesta 5)
3) Se puede cambiar la implementación de una clase sin estropear el código que la usa.
Respuesta 6)
4) encapsulación, herencia, polimorfismo
Me hicieron esta pregunta en una entrevista de trabajo una vez. Conseguí el trabajo. No
puedes tener la seguridad de encontrar algo así en el examen, pero bien viene saberlo.
Respuesta 7)
2)Haciendo todas las variables privadas y sólo permitiendo el acceso vía métodos
134
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 2)
Sobrecarga de métodos
La sobrecarga de métodos es un truco del compilador para permitirte usar el mismo
nombre para realizar acciones distintas dependiendo de los parámetros.
Entonces, imagina que estás diseñando la interfaz para un sistema que haga exámenes de
certificación de Java falsos (¿quién podría saber?). Una respuesta podría venir como un
entero, un booleano o una cadena de texto. Podrías crear una versión del método para
cada tipo de parámetro y darle el nombre correspondiente como:
marcarespuestaboolean(boolean respuesta){
}
marcarespuestaint(int respuesta){
}
marcarespuestaString(String respuesta){
}
Esto funcionaría pero supone que los futuros usuarios de tus clases tendrán que saber más
nombres de métodos de lo estrictamente necesario. Sería más útil si pudieras usar un solo
nombre de método y el compilador resolviera a qué código llamar según el tipo y el
número de parámetros de la llamada.
No hay palabras claves que recordar para sobrecargar métodos, sólo se crean múltiples
métodos con el mismo nombre pero distinto número y/o tipo de parámetros. Los nombres
135
Tutorial para el examen de certificación: SCJP 1.2
de los parámetros no son importantes pero el número y los tipos sí deben ser diferentes.
Así, el siguiente es un ejemplo de un método marcarespuesta sobrecargado
Por tanto, cambiárselo a uno de los métodos de arriba por int aún producirá un error en
tiempo de compilación, pero esta vez indicando que no se puede redefinir un método con
un tipo de retorno distinto.
Sobrescritura de métodos
Java proporciona un ejemplo de redefinición en el caso del método equals que cada
clase hereda de la gran clase antecesora Object. La versión heredada de equals
136
javaHispano. Tu comunidad, tu lenguaje.
• Button()
• Button(String label)
Así, puedes crear un botón sin etiqueta y dársela después, o usar la opción más común y
asignarle la etiqueta en el momento de la creación.
Sin embargo, los constructores no se heredan, así que si quieres sacar un constructor útil
de una clase ancestro no está disponible por defecto. Así, el siguiente código no
compilará
class Base{
public Base(){}
public Base(int i){}
}
137
Tutorial para el examen de certificación: SCJP 1.2
class Base{
public Base(){}
public Base(int i){}
}
public class MiRedef extends Base{
public static void main(String arg[]){
MiRedef m = new MiRedef(10);
}
MiRedef(int i){
super(i);
}
De la misma forma que se puede llamar al constructor de una clase base usando super()
se puede llamar a otro constructor de la clase en cuestión usando this como si fuera un
método. Así en el ejemplo anterior se podría definir otro constructor de la siguiente
manera
Como habrás adivinado esto llamará al otro constructor de la clase actual que toma un
solo entero como parámetro. Si usas super() o this() en un constructor debe ser la
primera llamada a un método. Como sólo uno de los dos puede ser el primer método
llamado, no puedes usar a la vez super() y this() en un constructor.
138
javaHispano. Tu comunidad, tu lenguaje.
class Base{}
class Base extends Base{} // ¡Error en tiempo de compilación!
Los constructores siempre se llaman hacia abajo desde lo alto de la jerarquía. Es muy
probable que en el examen te hagan preguntas relativas a una jerarquía de clases con
varias llamadas a this y super y tengas que elegir cuál será el resultado. Ten cuidado
con las preguntas en las que tienes una jerarquía compleja que resulta irrelevante a causa
de un constructor que hace una llamada tanto a this como a super y por tanto se
produce un error en tiempo de compilación.
class Mamífero{
Mamífero (){
System.out.println("Creando Mamífero ");
}
}
139
Tutorial para el examen de certificación: SCJP 1.2
Cuando se ejecute este código la cadena “Creando Mamífero” aparece primero debido a
la llamada implícita al constructor sin argumentos de la base de la jerarquía.
Pregunta 1)
Dada la siguiente definición de clase, ¿cuál de los siguientes métodos podría colocarse
legalmente después del comentario con la palabra comentada “//Aquí”?
Pregunta 2)
Dada la siguiente definición de clase, ¿cuál de los siguientes métodos podría colocarse
legalmente después del comentario con la palabra comentada “//Aquí”?
140
javaHispano. Tu comunidad, tu lenguaje.
}
}
Pregunta 3)
class Mamífero{
Mamífero (){
System.out.println("Mamífero ");
}
}
class Perro extends Mamífero {
Perro(){
System.out.println("Perro");
}
}
141
Tutorial para el examen de certificación: SCJP 1.2
}
Collie(String s){
System.out.println(s);
}
1)Error al compilar
2)Mamífero, Perro, Buen Perro, Collie
3)Buen Perro, Collie, Perro, Mamífero
4)Buen Perro Collie
Pregunta 4)
Pregunta 5)
class Base{
public void amethod(int i, String s){
System.out.println("Base amethod");
}
Base(){
System.out.println("Base Constructor");
}
142
javaHispano. Tu comunidad, tu lenguaje.
super.amethod(i,Parm);
}
public void amethod(){}
}
1)Error al compilar
2)Error causado por la sintaxis ilegal en: super.amethod(i,Parm);
3)Mostrará “Base Constructor”
4)Error causado por los nombres incorrectos de los parámetros en la llamada a;
super.amethod
Pregunta 6)
class Mammal{
Mammal(){
System.out.println("Four");
}
public void ears(){
System.out.println("Two");
}
}
class Dog extends Mammal{
Dog(){
super.ears();
System.out.println("Three");
}
}
Respuestas
Respuesta 1)
143
Tutorial para el examen de certificación: SCJP 1.2
Respuesta 2)
Cualquier llamada a this o super debe estar en la primera línea del constructor. Como
en el método ya se utilizó this, ninguna otra opción puede ser utilizada
Respuesta 3)
Respuesta 4)
Repuesta 5)
1)Error al compilar
Esto causa un error que indica algo como lo siguiente: “no puedes sobrescribir métodos
para hacerlos privados”, amethod en la clase Base esta definido como privado, y en
Child al no ponerle modificador de acceso antes de void, estas intentando alterar el
modificador public.
Respuesta 6)
Las clases son creadas desde la raíz del la jerarquía de herencia hacia abajo.
144
javaHispano. Tu comunidad, tu lenguaje.
145
Tutorial para el examen de certificación: SCJP 1.2
Objetivo 3)
Escribir código que construya instancias de una clase en concreto, incluyendo clases de
nivel superior, clases internas, clases internas estáticas y clases anónimas.
Concretamente, las clases pueden ser instanciadas como una referencia a un objeto
(también llamada simplemente objeto). De esta manera, una clase abstracta no puede ser
instanciada y por lo tanto no se puede crear una referencia a un objeto. Recuerda que una
clase que contiene un método abstracto es abstracta por si misma y no puede ser
instanciada.
La manera para instanciar una clase es usando la palabra clave new. Típicamente se
utiliza de la siguiente manera:
La sintaxis indica que la variable name es del tipo Button y contiene una referencia a
una instancia de Button. Sin embargo aunque el tipo de la referencia es frecuentemente
el mismo que el tipo de la clase instanciada, esto no necesariamente tiene que se así. El
siguiente código es valido:
La declaración e instanciación puede no ocurrir en la misma línea, Así, puedes construir una
instancia de una clase de la siguiente manera:
Button b;
b=new Button();
Clases internas
146
javaHispano. Tu comunidad, tu lenguaje.
Las clases internas fueron introducidas con la liberación del JDK 1.1. Las clases internas
permiten definir clases dentro de otras clases, en ocasiones estas clases son conocidas
como clases anidadas. Son usadas extensivamente a partir del modelo de eventos de JDK
1.1. Con certeza encontraras en el examen preguntas acerca de las clases anidadas y del
alcance de ellas.
class Nest {
class NestIn{}
}
La salida cuando este código se compile serán dos archivos .class. El primero, que es el
que esperas es:
Nest.class
el otro es
Nest$NestIn.class
Esto ilustra que el anidamiento de clases es generalmente una convención para nombrar
clases en lugar de una nueva clasificación de archivos .class. Las clases internas te
permite hacer una agrupación lógica de clases. También tienen beneficios para controlar
el alcance de las variables.
Una clase anidada de nivel superior es un miembro estático contenido dentro de una clase
de nivel superior.
class Nest{
static class NestIn{}
}
Este tipo de anidamiento es usado frecuentemente para agrupar de una manera sencilla
clases que guardan una relación entre si. Debido a que la clase es estática no requiere una
instancia de la clase externa para existir.
Clases Miembro
Veo una clase miembro como una “clase interna ordinaria”. Una clase miembro es
semejante a otros miembros de una clase, debes instanciar la clase exterior antes de crear
una instancia de la clase interna. Debido a la necesidad que tiene la clase interna de ser
asociada con una instancia de la clase externa, Sun introduce una nueva sintaxis para
147
Tutorial para el examen de certificación: SCJP 1.2
Para darle sentido a esta nueva sintaxis, intenta pensar que la primera aparición de la
palabra clave new es usada en el ejemplo anterior para designar la pertenencia a la
instancia actual this.
Así, podrías cambiar la línea que crea la instancia de ésta clase y leer lo siguiente:
Debido a que una clase miembro no puede existir sin un instancia de la clase exterior,
ésta puede tener acceso a las variables de la clase exterior.
Una clase local es visible únicamente dentro del bloque de código del método. El código
dentro de la clase local puede usar únicamente variables locales que tengan el
modificador final en el bloque del método o parámetros del método. Es muy probable
que te encuentres con preguntas de este tipo en el examen.
Clases anónimas
Tu primera reacción con la idea de una clase anónima debe ser "¿por qué querría yo tener
una clase sin nombre? y ¿cómo podría referirme a una clase si no tiene nombre?"
Para contestar estas preguntas, considera lo siguiente. Podrías estar en una situación en
donde constantemente tienes que pensar en nombres para instancias de clases en donde el
nombre es por si mismo evidente. Por ejemplo en el manejo de eventos las dos cosas mas
importantes que necesitas saber para manejar el evento son: el evento que se va a manejar
y el nombre del componente que esta utilizando dicho manejador. Tener el nombre de la
instancia la clase que maneja el evento no aporta mucho valor.
148
javaHispano. Tu comunidad, tu lenguaje.
class Nest{
public static void main(String argv[]){
Nest n = new Nest();
n.mymethod(new anon(){});
}
public void mymethod(anon i){}
}
class anon{}
Pregunta 1)
1)Una clase definida dentro de un método puede únicamente acceder métodos estáticos
del método que la contiene
2)Una clase definida dentro de un método puede únicamente acceder variables finales del
método que la contiene
3)Una clase definida dentro de un método no puede acceder a algún campo del método
que la contiene
149
Tutorial para el examen de certificación: SCJP 1.2
4)Una clase definida dentro de un método puede acceder cualquier campo accesible del
método que la contiene
Pregunta 2)
Pregunta 3)
Respuestas
Respuesta 1)
2)Una clase definida dentro de un método puede únicamente acceder variables finales del
método que la contiene
Respuesta 2)
1)Una clase anónima no puede tener un constructor
Respuesta 3)
2) Una instancia de una clase anidada de nivel superior puede crearse sin necesidad de
crear una instancia de la clase que la contiene
4) Para crear una instancia de una clase miembro se requiere crear una instancia de la
clase que la contiene
150
javaHispano. Tu comunidad, tu lenguaje.
Una clase anidada genera por si misma un archivo .class, usando el formato:
Outer$Inner.class
Una clase anidada de nivel superior es como una clase estática así que no requiere una
instancia de la clase que la contiene. Una clase miembro es como una clase no estática,
por consiguiente se requiere una instancia de la clase que la contiene,.
Richard Baldwin
http://www.geocities.com/Athens/7077/Java094.htm
151
Tutorial para el examen de certificación: SCJP 1.2
Sección 7. Threads
Objetivo 1)
Escribir código para definir, instanciar y comenzar nuevos threads usando
java.lang.Thread y java.lang.Runnable.
¿Qué es un Thread ?
Los Threads son procesos ligeros que aparentan correr en paralelo con tu programa
principal. A diferencia de los procesos un thread comparte memoria y datos con el resto
del programa. La Palabra Thread es una contracción de “Thread de ejecución” (Hilo de
ejecución), puedes imaginar una cuerda, a la cual le has deshilachado el final y has
tomado un hilo. El hilo todavía es parte de la misma cuerda, pero puede ser separado de
la principal y ser manipulado por si solo. Un ejemplo de donde pueden ser útiles los
threads, es en la impresión. Cuando das un click en el botón imprimir, probablemente no
quieras que el programa principal se detenga hasta que finalice la impresión. Lo deseable,
seria que el proceso de impresión comenzara a ejecutarse en segundo plano y te
permitiera continuar usando la parte principal del programa.
De las dos maneras de crear un Hilo (algunos documentos ocupan la palabra hebra en
lugar de hilo) el uso de Runnable es probablemente el mas común, pero debes de
conocer las dos para propósitos del examen. El siguiente es un ejemplo de una clase
creada con la interface Runnable.
152
javaHispano. Tu comunidad, tu lenguaje.
Cualquier clase que implemente una interfase debe crear un método correspondiente por
cada uno de los que se encuentren en la interfase. No es necesario que los métodos
realicen algo, pueden tener el cuerpo del método en blanco, pero deben estar ahí. De esta
manera incluí el método run incluso en este pequeño ejemplo, ya que si implementas
Runnable debes incluir el método run No incluir el método run causaría un error en
tiempo de compilación.
Para hacer algo útil cuando se crea un hilo de ejecución de una clase deberías de, por
supuesto, colocar algo de código donde puse :
//Blank body
La otra manera de crear un hilo es crear una clase que descienda de Thread. Esto es fácil
de hacer pero significa que no puedes heredar de ninguna otra clase, debido a que Java
solo soporta herencia simple. De esta manera, si estas creando un botón no le puedes
agregar threading a de esta manera porque un botón hereda de la clase AWT Button y
eso utiliza tu única opción de herencia. Existe debate sobre cual de las dos formas de
crear un hilo es verdaderamente más orientada a objetos, pero no necesitas llegar a esa
conclusión para propósitos del examen.
De este modo para hacer que el hilo se ejecute desde una clase que implemente
Runnable deberás llamar lo siguiente:
De nuevo observa que fue una llamada al método start, no una llamada al método run,
aunque es el código en el método run en tu clase el que actualmente se ejecuta.
153
Tutorial para el examen de certificación: SCJP 1.2
Preguntas
Pregunta 1)
¿Qué ocurrirá cuando intentes compilar y ejecutar el siguiente código?
Pregunta 2)
¿Cuáles de las siguientes frases es cierta?
154
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 3)
¿Qué ocurrirá cuando intentes compilar y ejecutar el siguiente código?
Pregunta 4)
¿Cuáles de las siguientes frases es cierta?
Respuestas
Respuesta 1)
3) Error en tiempo de compilación: La clase Runt es una clase abstracta. No puede ser
instanciada
155
Tutorial para el examen de certificación: SCJP 1.2
Respuesta 2)
3) Usar la interfase Runnable significa que no tienes que crear una instancia de la clase
Thread y llamar al método run directamente.
4) La interfase Runnable requiere únicamente implementar un método, que es llamado
run
Respuesta 3)
1)Compila y tiene como salida una cuenta de 1 a 99
Sin embargo, observa que este código no inicia la ejecución del hilo y el método run no
debe ser llamado de esta forma.
Respuesta 4)
2)El código que se ejecuta cuando inicias un hilo es colocado en el método run
3)Los Threads pueden compartir datos entre unos y otros
4)Para comenzar la ejecución de un Thread, llamas al método start y no al método
run.
No necesitas importar ninguna clase ya que el Threading es una parte integral de Java.
156
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 2)
Para propósitos del examen sleep(), y wait/notify son probablemente las más
importantes de las situaciones por las que un hilo pueda ser bloqueado.
157
Tutorial para el examen de certificación: SCJP 1.2
Con la salida de Java 2, los métodos de la clase Thread : stop, suspend y resume han
quedado obsoletos (depracated, no se recomienda que se usen y al utilizarlos se envía una
advertencia en tiempo de compilación). Las notas del JDK indican lo siguiente:
//Quote
Obsoleto. Este método ha sido censurado, ya que es inherentemente propenso a crear deadlocks.
Si el hilo objetivo mantiene un bloqueo sobre el monitor protegiendo un recurso de sistema
crítico cuando queda suspendido, ningún otro hilo puede acceder a este recurso hasta que el hilo
objetivo es reiniciado. Si el Hilo que intenta resumir al hilo objetivo intenta realizar un bloqueo
antes de llamar a resume(), ocurre un deadlock. Tales deadlocks típicamente se manifiestan como
procesos “congelados”. Para mas información vea ¿Por que son Obsoletos los métodos:
Thread.stop, Thread.suspend y Thread.resumen?
//End Quote
Una fuente generalmente confiable (Kathy Kozel) ha indicado que tienes que estar
conciente de esto para propósitos del examen. Yo asumiré que actualmente no necesitas
conocer como usarlos.
Pregunta 1)
¿Qué ocurrirá cuando intentes compilar y ejecutar el siguiente código?
158
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 2)
¿Cuál de las siguientes formas es una manera recomendada para que un Thread pueda
ser bloqueado?
1)sleep()
2)wait/notify
3)suspend
4)pause
Pregunta 3)
¿Cuáles de las siguientes frases son verdaderas?
1)El método sleep toma parámetros del Hilo y el número de segundos que debe dormir
2)El método sleep toma un solo parámetro que indica el número de segundos que debe
dormir
3)El método sleep toma un solo parámetro que indica el número de milisegundos que
debe dormir
4)El método sleep es un método estático de la clase Thread
Respuestas
Respuesta 1)
Respuesta 2)
1)sleep()
2)wait/notify
Respuesta 3)
159
Tutorial para el examen de certificación: SCJP 1.2
3)El método sleep toma un solo parámetro que indica el número de milisegundos que
debe dormir
4)El método sleep es un método estático de la clase Thread
160
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 3)
Así un usuario podría obtener los datos, realizar un cálculo y escribir los datos. Si en el
entretanto alguien más ha recuperado los datos, ha realizado un cálculo y lo ha escrito,
los segundos cálculos de los usuarios se perderán cuando la primera persona escriba en la
base de datos.
synchronized
La palabra clave synchronized se utiliza para marcar una sentencia o bloque de código
e indicar que únicamente un hilo a la vez puede ejecutar una instancia del código. La
entrada al código esta protegida por un supervisor o monitor de bloqueos. Este proceso es
implementado por un sistema de bloqueos. Se asigna un bloqueo al objeto y así se
asegura que únicamente un hilo a la vez pueda acceder al código. Así cuando un hilo
empieza a ejecutar un bloque sincronizado este adopta el bloqueo. Cualquier otro hilo no
podrá ejecutar el código hasta que el primer hilo haya finalizado y liberado el bloqueo.
Nota que el bloqueo esta basado en el objeto y no en el método.
El valor entre paréntesis indica el objeto o clase que necesita obtener el supervisor. Es
generalmente más común sincronizar un método que un bloque de código.
161
Tutorial para el examen de certificación: SCJP 1.2
wait/notify
Una llamada a wait dentro del código sincronizado causa que el hilo active su bloqueo
y se ponga a dormir. Esto normalmente ocurre para permitir a otro hilo obtener el
bloqueo y continuar algún proceso. El método wait es incoherente sin el uso de notify
o notifyAll los cuales permiten que el código que está esperando ser notificado pueda
despertarse y continuar ejecutándose. Un ejemplo típico del uso del protocolo
wait/notify es para permitir la comunicación entre los Hilos que aparentemente
involucran un ciclo infinito, como el siguiente:
//codigo producto
while(true){
try{
wait();
}catch (InterruptedException e) {}
}
// alguna otra accion va aqui
notifyAll();
162
javaHispano. Tu comunidad, tu lenguaje.
efectivamente significa activa el bloqueo sobre el objeto y espera hasta que el método
notify o notifyAll sea llamado para liberarlo.
El método notify despertará un hilo que espera ser reactivado por el supervisor de
hilos para el objeto. No puedes estar seguro de qué hilo se levantara. Si tienes sólo un
hilo en espera entonces no tendrás ningún problema. . Si tienes en espera múltiples hilos
entonces se levantara el hilo que lleva más tiempo esperando. Sin embargo no puedes
asegurarlo, ya que las prioridades de los hilos influirán en el resultado. Como resultado
generalmente se te aconseja que uses notifyAll en lugar de notify para no hacer
suposiciones con la planificación o las prioridades. Por supuesto esto no siempre es
posible y tendrás que intentar probar tu código en tantas plataformas como te sea posible.
Preguntas
Pregunta 1)
¿Cuales de las siguientes palabras claves indican a un hilo que libere el objeto que esta
bloqueando?
163
Tutorial para el examen de certificación: SCJP 1.2
1) release
2) wait
3) continue
4) notifyAll
Pregunta 2)
¿Cuál de las siguientes frases define mejor la función de la palabra clave synchronized?
Pregunta 3)
}//End of class
1)Error en tiempo de compilación; no hay una llamada a notify() dentro del método
2)Se compila y ejecuta, pero se crea un ciclo infinito dentro del ciclo while
3)Se compila y ejecuta
4)Se genera un error en tiempo de Ejecución: “IllegalMonitorStatException”
Pregunta 4)
164
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 5)
Respuestas
Respuesta 1)
2) wait
Respuesta 2)
Respuesta 3)
Respuesta 4)
165
Tutorial para el examen de certificación: SCJP 1.2
Respuesta 5)
3)La planificación de hilos en Java es dependiente de plataforma y puede variar de una
implementación a otra
4)Tu puedes fijar la prioridad de un hilo en el código
166
javaHispano. Tu comunidad, tu lenguaje.
Escribir código que use las clases administradoras de disposición (Layout Manager) y
los contenedores (Container) de componentes del paquete java.awt para presentar
interfaces graficas de usuario (GUI) con una apariencia especifica, redimensionar su
comportamiento y distinguir las responsabilidades entre los administradores de
disposición y los contenedores.
Comparada con herramientas como Visual Basic o Delphi, Java usa una filosofía distinta
para la disposición de componentes. La mayoría de las herramientas de diseño usan una
filosofía basada en la posición XY de píxeles para colocar un componente. Así en Visual
Basic puedes tomar una caja de texto de la paleta de componentes y colocarla en una
posición especifica en la forma o área de diseño, y esa posición será fija. En contraste
Java usa clases de disposición para controlar donde será colocado un componente de
acuerdo a la pantalla actual.
El siguiente código crea una aplicación sencilla y agrega una serie de botones.
167
Tutorial para el examen de certificación: SCJP 1.2
import java.awt.*;
public class FlowAp extends Frame{
public static void main(String argv[]){
FlowAp fa=new FlowAp();
//Change from BorderLayout default
fa.setLayout(new FlowLayout());
fa.setSize(400,300);
fa.setVisible(true);
}
FlowAp(){
add(new Button("One"));
add(new Button("Two"));
add(new Button("Three"));
add(new Button("Four"));
add(new Button("Five"));
add(new Button("Six"));
add(new Button("Seven"));
add(new Button("Eight"));
add(new Button("Nine"));
add(new Button("Ten"));
}//End of constructor
}//End of Application
La siguiente imagen tiene la apariencia por defecto que tendrá la aplicación cuando la
ejecutes desde la línea de comandos:
168
javaHispano. Tu comunidad, tu lenguaje.
Ten presente que ambas imágenes visualizan exactamente el mismo código Java. Lo
único que ha cambiado es la anchura del Frame. El administrador de disposición
FlowLayout automáticamente cambia la disposición de los componentes cuando el
Frame se redimensiona. Si haces el Frame más pequeño FlowLayout cambiaría la
disposición para que los botones se envuelvan alrededor en varias filas.
Cuando te encuentras por primera vez con estos administradores de componentes pueden
parecerte un poco arbitrarios. Algunas herramientas de desarrollo de aplicaciones como
Symantec Visual Café o Borland/Inprise Jbuilder ofrecen maneras para especificar la
posición de los componentes. Para los propósitos del examen por lo menos debes
familiarizarte con el manejo de los administradores de disposición para la creación de
GUI.
• FlowLayout
• BorderLayout
• GridLayout
• GridBagLayout
169
Tutorial para el examen de certificación: SCJP 1.2
import java.awt.*;
public class FlowAp extends Frame{
public static void main(String argv[]){
FlowAp fa=new FlowAp();
// fa.setLayout(new FlowLayout());
fa.setSize(400,300);
fa.setVisible(true);
}
FlowAp(){
add(new Button("One"));
add(new Button("Two"));
add(new Button("Three"));
add(new Button("Four"));
add(new Button("Five"));
add(new Button("Six"));
add(new Button("Seven"));
add(new Button("Eight"));
add(new Button("Nine"));
add(new Button("Ten"));
}//End of constructor
}//End of Application
170
javaHispano. Tu comunidad, tu lenguaje.
La razón por la que obtienes este botón grande en el centro es que el administrador de
disposición BorderLayout usa un conjunto de coordenadas al colocar los componentes.
Divide el área de la superficie en:
• North (Norte)
• South (Sur)
• East (Este)
• West (Oeste)
• Center (Centro)
Podrías suponer que el valor por defecto para los componentes cuando los vas colocando
es irse colocando en el sentido de las agujas del reloj alrededor de los puntos de su
circunferencia o en algún otro orden similar. En cambio los diseñadores decidieron hacer
a el centro del área del esquema el valor por defecto. Así en el ejemplo anterior cada
botón se ha colocado encima del botón anterior y ha ocupado enteramente el área
disponible. Como resultado la apariencia es que sólo tienes un botón, el último agregado.
import java.awt.*;
public class GridAp extends Frame{
public static void main(String argv[]){
GridAp fa=new GridAp();
//definimos el GridLayout con 2 filas y 5 columnas
fa.setLayout(new GridLayout(2,5));
fa.setSize(400,300);
171
Tutorial para el examen de certificación: SCJP 1.2
fa.setVisible(true);
}
GridAp(){
add(new Button("One"));
add(new Button("Two"));
add(new Button("Three"));
add(new Button("Four"));
add(new Button("Five"));
add(new Button("Six"));
add(new Button("Seven"));
add(new Button("Eight"));
add(new Button("Nine"));
add(new Button("Ten"));
}//fin del constructor
}//fin de la Aplicacion
Observa como los botones son alargados para ocupar todo el espacio disponible del
Frame.
GridBagLayout
Peter van der Linden en su libro Just Java and Beyond describe al administrador de
disposición GridBagLayout como “excesivamente complicado”. Core Java solo dice:
“usar GidBagLayout puede ser increíblemente complicado”. Aunque es complejo
manejarlo manualmente, varias herramientas de desarrollo como Visual Café, Visual
Age, JBuilder, etc. Lo hacen más fácil de usar, sin tener que entenderlo. JBuilder
172
javaHispano. Tu comunidad, tu lenguaje.
modifica fácilmente el método add para incluir los detalles siguientes en una instancia de
la clase GridBagLayout.
Pero cuando creas tu código manualmente no necesita parecer tan complejo como este.
Comentarios de las personas que han realizado el examen indican que las preguntas sobre
GridBagLayout no son muy profundas y una comprensión básica de los distintos
campos de la clase GridBagConstraints puede ser adecuada para realizar el examen.
• add(component, GridBagConstraint);
setFooParam()
Donde FooParam podría ser el valor X/Y o un relleno entre los componentes.
173
Tutorial para el examen de certificación: SCJP 1.2
He creado un applet de demostración sencillo con su código fuente que muestra cómo
no cambia la apariencia a menos que juegues con los valores de la clase
GridBagConstraints
http://www.software.u-net.com/applets/GridBagDemo/GridBagTest.htm
Recuerda que aunque necesitas entender esto para los propósitos del examen, podría ser
más fácil que cuando estés programando en el mundo real una combinación de controles
de contenedores con otros administradores de disposición. Un ejemplo de cuando esto
no es una buena opción es cuando necesita redimensionar dinámicamente componentes.
Ésta es una situación en donde herramientas de desarrollo como Visual Cafe o JBuilder
no son de mucha ayuda y una buena comprensión del GridBagLayout puede ser
esencial.
• gridx gridy
• gridwidth y gridheight
• fill
• ipadx e ipady
• insets
• anchor
• weightx y weighty
Hojeando el excelente libro de Bill Brogdens Java2 Exam Cram, encontré una
demostración comprensiva del GridBagLayout en:
http://www.austria.eu.net/java/programs/applets/missgable/index.htm
174
javaHispano. Tu comunidad, tu lenguaje.
Para este ejemplo supondremos que estas escribiendo el código necesario para diseñar el
programa de una agenda. Mostrarás la hora de la cita abajo a la izquierda y los detalles de
la cita abajo a la derecha. Las unidades de tiempo serán de media hora.
Debido que una cita puede cubrir más de una unidad de tiempo; por ejemplo puede durar
una hora y media, necesitaras poder cambiar la altura de los detalles de la cita
dinámicamente para cubrir más de una unidad de tiempo. Debido a este requerimiento, de
tener una altura variante para los detalles de las citas, utilizar GridLayout no es muy
conveniente.
import java.awt.*;
import java.awt.event.*;
public class GBCal extends Frame{
Panel pTimes=new Panel();
Panel pAps=new Panel();
TextField txTimes=new TextField("09.00");
TextField txAps=new TextField("Meet the boss");
GridBagLayout gbl=new GridBagLayout();
GridBagConstraints gbc=new GridBagConstraints();
public static void main(String argv[]){
GBCal gbc=new GBCal();
gbc.setLayout(new FlowLayout());
}
public GBCal() {
pTimes.add(txTimes);
pAps.add(txAps);
setLayout(gbl);
gbc.gridx=0;
gbc.gridy=0;
pTimes.setBackground(Color.pink);
add(pTimes,gbc);
gbc.gridx=1;
gbc.gridy=0;
pAps.setBackground(Color.lightGray);
add(pAps,gbc);
setSize(300,300);
setVisible(true);
}
}
175
Tutorial para el examen de certificación: SCJP 1.2
Este es el resultado:
El código ha puesto un color del fondo distinto para que puedas ver la magnitud de cada
panel en lugar de ver simplemente la anchura de los campos de texto. Esto está bien, pero
pensemos que ahora quieres que los campos de texto se estiren y abarquen de izquierda a
derecha todo el Frame de la aplicación principal. Esto se puede realizar modificando el
campo ipadx de la clase GridBagConstraints. Esto puede ejecutarse poniendo:
gbc.ipadx=30;
para las horas y
gbc.ipadx=100;
para los detalles
El código queda:
import java.awt.*;
import java.awt.event.*;
176
javaHispano. Tu comunidad, tu lenguaje.
y este es el resultado:
177
Tutorial para el examen de certificación: SCJP 1.2
Para hacer esto crearé una nueva instancia de la clase GridBagLayout llamada gbBut y
la usare para preparar la cuadrícula para el panel pTimes para colocar las hendiduras de
las unidades de tiempo una encima de otra verticalmente.
import java.awt.*;
import java.awt.event.*;
public class GBCal extends Frame{
Panel pTimes=new Panel();
Panel pAps=new Panel();
TextField txTimes9=new TextField("09.00");
TextField txTimes930=new TextField("09.30");
TextField txAps=new TextField("Meet the boss");
GridBagLayout gbl=new GridBagLayout();
GridBagLayout gbBut=new GridBagLayout();
GridBagConstraints gbc=new GridBagConstraints();
public static void main(String argv[]){
GBCal gbc=new GBCal();
gbc.setLayout(new FlowLayout());
}
public GBCal() {
setLayout(gbl);
//Controlar el panel de tiempo con
//GridBagLayout
pTimes.setLayout(gbBut);
178
javaHispano. Tu comunidad, tu lenguaje.
gbc.gridx=0;
gbc.gridy=0;
pTimes.add(txTimes9,gbc);
gbc.gridx=0;
gbc.gridy=1;
pTimes.add(txTimes930,gbc);
pTimes.setBackground(Color.pink);
//Reutilizamos gbc para la disposición del panel principal
gbc.gridx=0;
gbc.gridy=0;
gbc.ipadx=30;
add(pTimes,gbc);
pAps.setLayout(gbBut);
gbc.gridx=0;
gbc.gridy=1;
pAps.add(txAps,gbc);
gbc.gridx=1;
gbc.gridy=0;
gbc.ipadx=100;
pAps.setBackground(Color.lightGray);
add(pAps,gbc);
setSize(300,300);
setVisible(true);
}
}// fin de la clase
El resultado es el siguiente:
Esto esta trabajando bien hasta cierto punto. Tenemos ahora dos hendiduras para las
unidades de tiempo, pero desafortunadamente el espacio para el detalle de la cita tiene
179
Tutorial para el examen de certificación: SCJP 1.2
como valor predefinido el centro del campo de las citas y obtenemos una fila gruesa. Lo
que quiero ahora es fijarla hasta arriba y estirarla para que cubra las dos hendiduras de
tiempo.
Si un componente no-llena el área completa, puedes especificar en que parte del área lo
quieres usando el campo anchor de la clase GridBagConstraints. Los posibles
valores son:
GridBagconstraints.CENTER
GridBagconstraints.NORTH
GridBagconstraints.NORTHEAST
GridBagconstraints.EAST
GridBagconstraints.SOUTHEAST
GridBagconstraints.SOUTH
GridBagconstraints.SOUTHWEST
GridBagconstraints.WEST
GridBagconstraints.NORTHWEST
En este caso quiero posicionar los campos en la parte superior (North) de los paneles
que los contienen. He aumentado el espesor del campo del detalle de la cita aumentando
el valor de ipady para la dirección del campo.
import java.awt.*;
import java.awt.event.*;
public class GBCal extends Frame{
Panel pTimes=new Panel();
Panel pAps=new Panel();
TextField txTimes9=new TextField("09.00");
TextField txTimes930=new TextField("09.30");
TextField txAps=new TextField("Meet the boss");
GridBagLayout gbl=new GridBagLayout();
GridBagLayout gbBut=new GridBagLayout();
GridBagConstraints gbc=new GridBagConstraints();
public static void main(String argv[]){
GBCal gbc=new GBCal();
gbc.setLayout(new FlowLayout());
}
public GBCal() {
setLayout(gbl);
//Controlamos el panel de tiempos con GridBagLayout
pTimes.setLayout(gbBut);
180
javaHispano. Tu comunidad, tu lenguaje.
Y este es el resultado:
181
Tutorial para el examen de certificación: SCJP 1.2
• ipadx/y
• gridx/y
• anchor
• weightx/y
• fill
• gridwidth/height
• insets
Los campos weightx/y controlan cómo un área crece o se contrae más allá de su
tamaño inicial. Así que si pones el campo weighty a cero el campo seguirá manteniendo
su altura constante aun cuando redimensiones la ventana.
El campo fill controla cómo un componente se estira para llenar el área. Al igual que el
campo anchor puedes definir los valores del campo fill usando constantes ya
definidas de la clase GridBagConstraints. Éstas son:
GridBagConstraints.NONE
GridBagConstraints.HORIZONTAL
GridBagConstraints.VERTICAL
GridBagConstraints.BOTH
El campo insets indica el relleno "externo" que tendrá a lo largo de los límites de la
celda de la cuadrícula.
182
javaHispano. Tu comunidad, tu lenguaje.
Preguntas
Pregunta 1)
import java.awt.*;
public class FlowAp extends Frame{
public static void main(String argv[]){
FlowAp fa=new FlowAp();
fa.setSize(400,300);
fa.setVisible(true);
}
FlowAp(){
add(new Button("One"));
add(new Button("Two"));
add(new Button("Three"));
add(new Button("Four"));
}//fin del constructor
}//fin de la Application
1)Un Frame con botones etiquetados con "One", "Two", "Three","Four" colocados
encada esquina
2)Un Frame con botones etiquetados con "One", "Two", "Three","Four" colocados de
arriba hacia abajo
3)Un Frame con un botón grande etiquetado con "Four" en el Centro
4)Se generará un error al momento de la ejecución indicando que no has puesto un
LayoutManager
Pregunta 2)
183
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 3)
Pregunta 4)
1)El Frame se agrandará para permitir que el Scrollbar ocupe su tamaño predefinido.
2)El Scrollbar se colocará en la parte Norte del Frame, será muy ancho, muy grueso y
no muy útil
3)No puedes agregar un Scrollbar en la parte Norte de un Frame, sólo al Este o al
Oeste
4)El Scrollbar se estirará desde arriba hasta abajo del Frame
Pregunta 5)
¿Qué pasa si agregas más botones de los que definiste en un GridLayout y las etiquetas
de cada botón son demasiado largas?
1)El tamaño del contenedor se aumentara para permitir que las etiquetas de cada botón se
desplieguen completamente
2)El GridLayout ignorará el largo de cada etiqueta y éstas se truncarán
3)Se generará un error al compilar indicando que los botones no pueden alcanza su
tamaño predefinido
4)Se generará un error al ejecutarse indicando que los botones no puede alcanzar su
tamaño predefinido
Pregunta 6)
184
javaHispano. Tu comunidad, tu lenguaje.
Pregunta 7)
1) ipadx
2) fill
3) insets
4) width
Pregunta 8)
¿Cual será la apariencia mas probable del siguiente código después de ejecutarse?
import java.awt.*;
public class CompLay extends Frame{
public static void main(String argv[]){
CompLay cl = new CompLay();
}
CompLay(){
Panel p = new Panel();
p.setBackground(Color.pink);
p.add(new Button("One"));
p.add(new Button("Two"));
p.add(new Button("Three"));
add("South",p);
setLayout(new FlowLayout());
setSize(300,300);
setVisible(true);
}
}
185
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 9)
Pregunta 10)
Al usar el administrador de disposición GridBagLayout, cada nuevo componente
agregado requiere una nueva instancia de la clase GridBagConstraints. Es esto :
1)Verdadero
2)Falso
Respuestas
Respuesta 1
Respuesta 2
Respuesta 3
Respuesta 4
186
javaHispano. Tu comunidad, tu lenguaje.
2)El Scrollbar se colocará en la parte Norte del Frame, será muy ancho, muy grueso y
no muy útil
Respuesta 5
Respuesta 6
Respuesta 7
1) ipadx
2) fill
3) insets
Respuesta 8
Respuesta 9
Respuesta 10
2)Falso
187
Tutorial para el examen de certificación: SCJP 1.2
http://www.geocities.com/Athens/7077/Java118.htm
Richard parece no cubrir el GridBagLayout
Jyothi Krishnan en
http://www.geocities.com/SiliconValley/Network/3693/obj_sec8.html#obj25
188
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 2.
Escribir código que implemente clases oyentes (Listener) y en métodos oyentes extraer
información del evento para determinar el componente afectado ya sea para conocer la
posición actual del ratón o el número de veces que se llama a un evento. Determinar el
nombre de clase de un evento para cualquier interface oyente especificada en el paquete
java.awt.event.
Para escribir cualquier aplicación útil con interfaz gráfica de usuario (GUI) utilizando
Java necesitas entender el funcionamiento las clases oyentes y la manera de extraer
información de los eventos que ellas procesan. El sistema de manejo o gestión de eventos
en Java cambió significativamente entre las versiones 1.0x y 1.1. En la versión 1.0x el
código para manejar eventos se parecía bastante al código C llano para Windows, es decir
bastante horrible. Requería la creación de grandes sentencias case donde colocabas el
código para procesar un evento en particular de acuerdo con los parámetros pasados. Este
sistema es bastante sencillo de entender para ejemplos triviales pero no es recomendable
para programas más grandes.
Tengo la impresión de que lo más relevante que necesita saber para el examen es que la
gestión de eventos de la versión 1.1 no es compatible con versiones anteriores. En teoría,
el código escrito con el estilo de código de la versión 1.0x para el manejo de eventos debe
trabajar bien en versiones posteriores del JDK.
El sistema de gestión de eventos de Java 1.1 involucra el uso de clases oyentes -Listener-
que son eficazmente "ligadas" a los componentes para procesar eventos específicosσ.
Esto favorece a las herramientas de desarrollo de aplicaciones GUI para que generen
automáticamente código que maneje los eventos. Si examinas el código generado por una
de estas herramientas puede que te parezca confuso, esto es en parte debido a que tienden
a involucrar clases internas creadas dentro de los métodos. Con el propósito de
aprenderlo puedes manejar las clases de gestión de eventos como si fueran clases de alto
nivel.
Uno de los factores complicados para la gestión de eventos es que ésta se basa en
Interfaces, pero es mucho más fácil de usar utilizando una serie de clases conocidas como
las clases Adaptadoras -Adapter- , qué simplemente implementan las interfaces del
evento. Cuando usas una interface necesitas implementar todos sus métodos, así el uso
directo de la interface EventListener requiere la creación de métodos con cuerpos
σ
NT. El modelo de la versión 1.1 se conoce en algunos documentos como gestión de eventos delegados.
189
Tutorial para el examen de certificación: SCJP 1.2
vacíos para cualquier evento de la interface que no se utilice. Usando las clases
Adaptadoras sólo necesitas crear los cuerpos de los métodos de los eventos que
realmente utilizas.
Las clases Adaptadoras -Adapter- te permiten usar las Interfaces oyentes sin
tener que crear un cuerpo para cada uno de los método de la interface.
Uno de los eventos esenciales más manejados para una aplicación sencilla es la habilidad
de cerrar la aplicación como respuesta a seleccionar la opción cerrar proporcionada por el
sistema operativoγ. Te puede sorprender que el manejo de este evento no venga ya
implementado por omisión en un Frame. Si crea una aplicación que herede un Frame,
pero no creas código para cerrarlo, tendrás qué o bien terminar el proceso desde el gestor
de tareas o, en Windows, ir a la línea de comandos y pulsar CTRL-C.
Los métodos para manejar los eventos de las ventanas (WindowEvent) no son tan
intuitivos como los métodos de otros eventos. Así al principio no es obvio a cual de los
métodos siguientes necesitas responder para cerrar el Frame:
windowClosed o windowClosing
System.exit(0);
Aquí un ejemplo de una aplicación sencilla que muestra un Frame que responderá
desapareciéndose cuando se accione la opción cerrar proporcionada por el sistema
operativo:
γ
NT: en Windows es la x que aparece en la esquina superior derecha o la pulsación de las teclas ALT-F4
190
javaHispano. Tu comunidad, tu lenguaje.
La segundo mitad del objetivo pide que conozcas el nombre de clase por cada evento de
cada interface oyente. La tabla que aparece mas adelante lista todas las interfaces oyentes
junto con sus métodos.
• clicked
• pressed
• released
• entered
• exited
Si comparas estos con los eventos manejados en Visual Basic 5 la única área significante
que no se cubre es un conjunto de métodos para manejar los eventos de arrastre con el
ratón(Drag&Drop)
El nombre de la clase del Evento pasado a cada método es bastante intuitivo y basado en
el nombre de la clase Oyente. Así todos los métodos de ActionListener toman un
parámetro de tipo ActionEvent, los métodos de ComponentListener toman un tipo
de ComponentEvent, un ContainerListener toma un ComponentEvent, etc, etc,
etc.
Existen 11 interfaces oyentes en total, pero sólo 7 de ellas tienen múltiples métodos.
Como lo relevante de los adaptadores es eliminar la necesidad de implementar métodos
en blanco, sólo se implementan las clases Adaptadoras para estas 7 Interfaces
• ContainerAdapter
191
Tutorial para el examen de certificación: SCJP 1.2
• FocusAdapter
• KeyAdapter
• MouseAdapter
• MouseMotionAdapter
• WindowAdapter
192
javaHispano. Tu comunidad, tu lenguaje.
Preguntas
Pregunta 1)
1)Para un componente dado sus eventos se procesará en el orden en que los oyentes
fueron agregados.
2)Usar las clases Adaptadoras para el manejo de eventos significa crear cuerpos vacíos
para todos los métodos que no se utilicen.
3)Un componente puede tener múltiples oyentes asociados a él
4)Pueden quitarse oyentes una vez agregados.
Pregunta 2)
¿Cuáles de las siguientes líneas son métodos validos para el manejo de eventos?
1) mousePressed(MouseEvent e){}
2) MousePressed(MouseClick e){}
3) functionKey(KeyPress k){}
4) componentAdded(ContainerEvent e){}
Pregunta 3)
import java.awt.*;
import java.awt.event.*;
public class MClick extends Frame implements MouseListener{
}
MClick(){
this.addMouseListener(this);
}
public void mouseClicked(MouseEvent e){
System.out.println(e.getWhen());
}
}
193
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 4)
Respuestas
Respuesta 1)
Respuesta 2)
1)mousePressed(MouseEvent e){}
4)componentAdded(ContainerEvent e){}
Respuesta 3)
Debido a que este código utiliza una interface oyente de eventos, se deben crear cuerpos
vacíos para cada uno de los métodos de la interface.
Este código causará errores que advierten que MClick es una clase abstracta.
Respuesta 4)
2)El código escrito para el manejo de eventos en la versión 1.0x se ejecutará sin
problemas sobre la versión 1.1 de la JVM.
3)El modelo de Eventos de la versión 1.1 está particularmente ajustado a las
herramientas para la construcción de aplicaciones GUI.
194
javaHispano. Tu comunidad, tu lenguaje.
Richard Baldwin
http://www.Geocities.com/Athens/7077/Java080.htm#design goals of the jdk 1.1 delegation
Jyothi Krishnan
http://www.geocities.com/SiliconValley/Network/3693/obj_sec8.html#obj25
David Reilly
http://www.davidreilly.com/jcb/java107/java107.html
195
Tutorial para el examen de certificación: SCJP 1.2
Escribir código que utilice los siguientes métodos de la clase java.lang.Math: abs,
ceil, floor, max, min, random, round, sin, cos, tan y sqrt.
abs
Hasta que comencé ha estudiar para el examen de certificación no tenía ni idea de lo que
hace el método abs. Elimina el signo de un número y retorna el numero simplemente.
Así la siguiente línea de código mostrará simplemente 99. Si el número es positivo
obtendrás como resultado el mismo número.
System.out.println(Math.abs(-99));
ceil
Este método retorna el próximo número entero hacia arriba. Si tienes lo siguiente:
ceil(1.1)
ceil(-1.1)
el resultado será -1
196
javaHispano. Tu comunidad, tu lenguaje.
floor
El valor double más grande que no sea mayor que el argumento pasado y que sea igual a
un entero.
Si tienes aun dudas de lo que significa lo anterior, aquí hay un pequeño programa y sus
resultados:
-100.0
-99.0
99.0
-1.0
0.0
max y min
Toma nota de lo siguiente: los siguientes dos métodos toman dos parámetros. Puedes
encontrar preguntas con ejemplos incorrectos que les pasan sólo un parámetro. Como
podrías esperar estos métodos son el equivalente de decir:
197
Tutorial para el examen de certificación: SCJP 1.2
-1
2
1
-10
1
random
A diferencia de algunos sistemas que generan números aleatorios Java no parece ofrecer
la funcionalidad de pasar un número como semilla para aumentar la aleatoriedad.
Para propósitos del examen uno de los aspectos importantes a considerar de este método
es que el valor de retorno está entre 0.0 y 1.0. Así los resultados de una típica secuencia
de ejecuciones podrían ser:
0.9151633320773057
0.25135231957619386
0.10070205341831895
System.out.println(Math.round(Math.random()*100));
round
Redondea al entero más cercano. Para qué, si el valor tiende más de la mitad hacia el
entero más alto, el valor es redondeado al entero siguiente. En caso contrario el valor
retornado es el entero anterior. Si por ejemplo el valor a redondear es x entonces:
System.out.println(Math.round(1.01));
System.out.println(Math.round(-2.1));
System.out.println(Math.round(20));
198
javaHispano. Tu comunidad, tu lenguaje.
1
-2
20
Estos métodos elegantes toman un parámetro de tipo double y hacen justo las mismas
funciones elegantes que realizarían en cualquier otro lenguaje que hayas usado. En mi
caso, que son 12 años de programación, nunca he usado una de estas funciones. Así
quizás lo único que debemos recordar es que el parámetro que recibe es de tipo double.
sqrt
Retorna un valor tipo double que es la raíz cuadrada del valor pasado como parámetro.
Resumen
Pregunta 1)
1) System.out.println(Math.max(x));
2) System.out.println(Math.random(10,3));
3) System.out.println(Math.round(20));
4) System.out.println(Math.sqrt(10));
199
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 2)
¿Cuál de las siguientes líneas mostrara un valor aleatorio con valor entre 1 y10?
1) System.out.println(Math.round(Math.random()* 10));
2) System.out.println(Math.round(Math.random() % 10));
3) System.out.println(Math.random() *10);
4) Ninguna de las anteriores
Pregunta 3)
System.out.println(Math.floor(-2.1));
1) -2
2) 2.0
3) -3
4) -3.0
Pregunta 4)
System.out.println(Math.abs(-2.1));
1) -2.0
2) -2.1
3) 2.1
4) 1.0
Pregunta 5)
System.out.println(Math.ceil(-2.1));
1) -2.0
2) -2.1
200
javaHispano. Tu comunidad, tu lenguaje.
3) 2.1
3) 1.0
Pregunta 6)
Respuestas
Respuesta 1)
3) System.out.println(Math.round(20));
4) System.out.println(Math.sqrt(10));
Respuesta 2)
La opción más cercana a la correcta es la 1 pero el detalle esta en recordar que el método
random incluye el 0 y la pregunta pide valores entre 1 y 10.
201
Tutorial para el examen de certificación: SCJP 1.2
Respuesta 3)
4) -3.0
Respuesta 4)
3) 2.1
Respuesta 5)
1) -2.0
Respuesta 6)
La clase Math tiene el modificador final y por eso no puede ser heredada.
202
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 2
La teoría de la inmutabilidad de la clase String dice que una vez creado, un String
nunca puede modificarse. En nuestra experiencia programando con Java en la vida real
nos damos cuenta que esto no es del todo cierto.
¿Si un String no puede cambiarse entonces s1 debería mostrar siempre "Hello" , pero
si pruebas el código te darás cuenta que en la segunda ejecución del println se muestra
la cadena "There". Entonces ¿Que pasa?
Debido a que la concatenación de Strings causa que un nuevo String sea instanciado
"fuera de escena", puede haber un desempeño poco eficiente si estás manipulando
grandes cantidades de Strings, como sucede al leer un archivo con gran cantidad de
texto. Generalmente la inmutabilidad de la clase String no altera nuestra programación
diaria, pero se cuestionará en el examen. Recuerda que de cualquier manera que te hagan
la pregunta, una vez creado un String no puede cambiarse aún cuando la referencia a él
se cambie para apuntar a algún otro String. Aunque ni los objetivos específicos del
203
Tutorial para el examen de certificación: SCJP 1.2
examen para Java2 ni para Java 1.1 lo mencionan, estoy bastante seguro que algunas
preguntas requieren conocimiento sobre la clase StringBuffer.
Preguntas
Pregunta 1)
String fname="John";
String lname="String"
¿Cómo puedes cambiar estos Strings para que tomen nuevos valores dentro del mismo
bloque de código?
1)
fname="Fred";
lname="Jones";
2)
String fname=new String("Fred");
String lname=new String("Jones");
3)
StringBuffer fname=new StringBuffer(fname);
StringBuffer lname=new StringBuffer(lname);
Pregunta 2)
Estás creando un programa para leer en archivo del texto de 8 MB. Cada nueva línea
leída se agrega a un objeto String pero te estás dando cuenta que, tristemente, le falta
desempeño. ¿Cuál es probablemente la explicación?
204
javaHispano. Tu comunidad, tu lenguaje.
3)Debido a que los Strings son inmutables un nuevo String se crea con cada línea
leída, Cambiándolo por un StringBuffer puedes aumentar el desempeño.
Respuestas
Respuesta 1)
Respuesta 2)
3)Debido a que los Strings son inmutables un nuevo String se crea con cada línea
leída, Cambiándolo por un StringBuffer puedes aumentar el desempeño.
205
Tutorial para el examen de certificación: SCJP 1.2
La API Java 2 incluye nuevas interfaces y clases para reforzar las colecciones ya
disponibles. Las primeras versiones de Java incluyeron:
vector
hashtable
array
BitSet
De éstos, sólo el array era incluido en los objetivos para el examen de certificación de la
versión 1.1. Una de las omisiones notables de Java 1.1 era el soporte para ordenar, un
requisito muy común en cualquier situación de programación.
Sets
Maps
206
javaHispano. Tu comunidad, tu lenguaje.
Las clases que implementan la interface Collection más que almacenar tipos de datos
primitivos, almacenan objetos. Todo esto tiene inconvenientes ya que la creación de
objetos reduce el rendimiento y a los elementos antes de usarse se les aplica un cast, al
tipo apropiado, para que puedan ser utilizarlos. Esto también significa que las colecciones
no verifican que los elementos sean todos el mismo tipo, ya que un objeto puede ser casi
cualquier cosa.
Set
Set es una interface de colecciones que no puede contener elementos duplicados. De esta
manera se presta para manejar conceptos como el de un conjunto de registros retornados
de una base de datos relacional. Parte de la magia de la interface Set esta en el método
add.
add(Object o)
Cualquier objeto pasado al método add puede implementar el método equals para que
el valor pueda compararse con objetos existentes en la clase. Si la clase ya contiene éste
objeto la llamada al método add no modifica el contenido y retorna false. La idea de
retornar false cuando intentas agregar un elemento que ya existe se parece más a la
manera en que trabaja C/C++ que la manera en que trabaja Java. La mayoría de los
métodos similares en Java lanzan una Excepción en este tipo de situaciones.
List
add
remove
clear
La documentación de JDK da como ejemplo usar List para manejar una GUI que
controle una lista que contiene todos los nombres de los Planetas.
Map
Map es una interface, las clases que la implementen no pueden tener llaves duplicadas y
es similar a Hashtables.
207
Tutorial para el examen de certificación: SCJP 1.2
La gran ventaja de las colecciones sobre los arreglos es que las colecciones son
desarrollables , es decir, no tienes que asignarles un tamaño al momento de crearlas. El
inconveniente de las colecciones es que sólo guardan objetos y no tipos primitivos e
inevitablemente afectan el rendimiento de la aplicación. Los arreglos no soportan
directamente el ordenamiento, pero esto puede ser superado usando los métodos estáticos
de las colecciones. Aquí hay un ejemplo:
import java.util.*;
public class Sort{
public static void main(String argv[]){
Sort s = new Sort();
}
Sort(){
String s[] = new String[4];
s[0]="z";
s[1]="b";
s[2]="c";
s[3]="a";
Arrays.sort(s);
for(int i=0;i< s.length;i++)
System.out.println(s[i]);
}
}
Usando Vectores
import java.awt.*;
import java.util.*;
public class Vec{
public static void main(String argv[]){
Vec v = new Vec();
v.amethod();
}//fin de main
public void amethod(){
208
javaHispano. Tu comunidad, tu lenguaje.
Antes de Java2 el uso de la clase del Vector era la manera principal de crear una
estructura de datos re-dimensionable. Los elementos de esta clase pueden quitarse con el
método remove .
Usando Hashtables
Las Hashtables son parecidas al concepto en Visual Basic de una colección que usa
una llave. Actúa como un Vector, sólo que en lugar de referirte a los elementos por un
número, te refieres a ellos por una llave. La palabra hash de su nombre se refiere a un
término matemático que hace referencia al manejo de índices. Una Hashtable puede
ofrecer un beneficio superior sobre un Vector, su rapidez
BitSet
Sólo es eficaz desde el punto de vista del tamaño; si estás buscando un acceso eficaz, es
ligeramente más lento que el uso de un arreglo de algún tipo primitivo.
209
Tutorial para el examen de certificación: SCJP 1.2
Un BitSet es un poco una clase novedosa de la que nunca puedes llegar a necesitar.
Sospecho que podría ser conveniente para propósitos criptográficos o para el
procesamiento de imágenes. Por favor avísame si te encuentras con alguna pregunta
relacionada con esta clase en el examen.
Pregunta 1)
1) Collection
2) Iterator
3) HashSet
4) Vector
Pregunta 2)
Pregunta 3)
1)La interface Set se diseño para asegurar que la implementación de clases tengan
miembros únicos
2)Las clases que implementan la interface List no pueden contener elementos
duplicados
210
javaHispano. Tu comunidad, tu lenguaje.
3) la interface Set se diseño para almacenar registros retornados de una consulta a una
base de datos
4) la Interface Map no es parte del marco de trabajo de las colecciones
Pregunta 4)
1) los elementos de clase de colecciones pueden ser ordenados usando el método sort de
la interface Collection
2)Puedes crear una colección ordenada instanciando una clase que implemente la
interface List
3)El método sort de la interface Collection toma como parámetros una A o una D
para indicar el orden, Ascendente/Descendente
4)Los elementos de una clase de colecciones pueden ser ordenados usando el método
order de la interface Collection
Pregunta 5)
Deseas almacenar una cantidad pequeña de datos y hacerlos disponibles para un acceso
rápido. No necesitaras que los datos sean ordenados, la singularidad no es un problema y
los datos permanecerán bastante estáticos ¿Qué estructura de datos podría ser la mas
conveniente para este requisito?
1)TreeSet
2)HashMap
3)LinkedList
4)Un arreglo
Pregunta 6)
1) ListBag
2) HashMap
3) Vector
4) SetList
211
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 7)
Respuestas
Respuesta 1)
3) HashSet
4) Vector
Respuesta 2)
Las clases de colecciones son nuevas en Java 2. Con excepción de las clases que han sido
actualizadas como Vector y BitSet, si ejecutas cualquiera de las Colecciones a través
de un JDK antiguo, conseguirás un error en tiempo de compilación.
Respuesta 3)
1)La interface Set se diseño para asegurar que la implementación de clases tengan
miembros únicos
Los elementos de una clase que implementa la interface List pueden contener elementos
duplicados. Aunque una clase que implementa la interface Set podría usarse para
guardar archivos retornados por una consulta a una base de datos, no se diseño
particularmente para ese propósito.
Respuesta 4)
2)Puedes crear una colección ordenada instanciando una clase que implemente la
interface List
Respuesta 5)
212
javaHispano. Tu comunidad, tu lenguaje.
4)Un arreglo
Respuesta 6)
2) HashMap
3) Vector
A partir de Java 2 la clase Vector fue actualizado para ser parte del marco de trabajo de
las colecciones.
Respuesta 7)
213
Tutorial para el examen de certificación: SCJP 1.2
Escribir código que utilice objetos de la clase File para navegar dentro del sistema de
archivos.
En su excelente libro "Just Java and Beyond" Peter van der Linden comienza su capítulo
sobre I/O de ficheros diciendo:
"No es justo remarcar, como han hecho algunos, que el soporte para I/O en Java es un
punto muy importante".
Yo creo que él estaba indicando que es levemente importante, y así, es un área en la que
hay que redoblar la comprobación de tu conocimiento antes de ir al examen. Cuando lo
estas aprendiendo te queda al menos la compensación de que comprenderás un área útil
del lenguaje.
Los nombres de las clases de flujos de I/O no son intuitivos y las cosas no siempre
funcionan como las podrías imaginar.
La clase File
La clase File no es del todo descriptiva, puesto que una instancia de la clase File
representa el nombre de un archivo o directorio más que el archivo en si mismo.
Así el examen podría hacerte preguntas sobre la habilidad de crear y eliminar archivos y
directorios, qué podría ser considerado bajo la cabecera de "navegación por el sistema de
ficheros".
214
javaHispano. Tu comunidad, tu lenguaje.
delete()
mkdir() y mkdirs()
import java.io.*;
public class FileNav{
public static void main(String argv[]){
String[] filenames;
File f = new File(".");
filenames = f.list();
for(int i=0; i< filenames.length; i++)
System.out.println(filenames[i]);
}
}
Esto sencillamente muestra una lista de todos los archivos en el directorio actual ("*.*")
Independencia de plataforma
La clase File esta escrita en Java puro. Esto significa que no incluye código nativo, pero
también significa que esta escrito para funcionar independientemente de la plataforma
sobre la cual se ejecute. Debido a las diferencias en la manera en que trabajan los
distintos sistemas de archivos es importante estar consciente de particularidades de la
plataforma como el carácter separador de los directorios. En Win/DOS es la barra
invertida “\” , en UNÍX es la barra normal “/” y sobre MAC es otro. Puedes saber cual es
este carácter dependiente de la plataforma utilizando la constante File.separator en
lugar de obtenerlo con alguna codificación compleja.
El siguiente archivo es bastante largo (más de 90 líneas) pero para entenderlo, necesitaras
conocer la mayoría de los objetivos que se explican en esta sección. El programa te
permite navegar entre los archivos de un directorio y cambiar de directorio. Esta
inspirado en parte en código del libro "Java in a Nutshell" de O´reilly. Un libro que
recomiendo ampliamente. Aquí una muestra del programa en funcionamiento.
215
Tutorial para el examen de certificación: SCJP 1.2
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class Filer extends Frame implements ActionListener{
/**************************************************************
Marcus Green October 2000 Part of the Java Programmer Certification
tutorial available at http://www.jchq.net. Addressing the objective to
be able to use the File class to navigate the File system.This program
will show a list of files in a directory .Clicking on a directory will
change to the directory and show the contentsNote the use of
File.separator to allow this to work on Unix or PC (and maybe even the
Mac)
****************************************************************/
List lstFiles;
File currentDir;
String[] safiles;
int iEntryType = 6;
int iRootElement = 0;
int iElementCount = 20;
216
javaHispano. Tu comunidad, tu lenguaje.
Filer(){
setLayout(new FlowLayout());
lstFiles = new List(iElementCount);
lstFiles.addActionListener(this);
//set the current directory
File dir = new File(System.getProperty("user.dir"));
currentDir = dir;
listDirectory(dir);
add(lstFiles);
addWindowListener(
new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
} );
}
public void upDir(File currentDir){
File fullPath = new File(currentDir.getAbsolutePath());
String sparent = fullPath.getAbsoluteFile().getParent();
if(sparent == null) {
//At the root so put in the dir separator to indicate this
lstFiles.remove(iRootElement);
lstFiles.add(" "+File.separator+" ",iRootElement);
return;
}else{
File fparent = new File(sparent);
listDirectory(fparent);
}
}
public void listDirectory(File dir){
String sCurPath = dir.getAbsolutePath()+File.separator ;
//Get the directorie entries
safiles = dir.list();
//remove the previous lis and add in the entry
//for moving up a directory
217
Tutorial para el examen de certificación: SCJP 1.2
lstFiles.removeAll();
lstFiles.addItem("[ .. ]");
String sFileName = new String();
//loop through the file names and
//add them to the list control
for(int i=0; i< safiles.length; i++){
File curFile = new File(sCurPath + safiles[i]);
if(curFile.isDirectory()){
sFileName = "[dir ]" + safiles[i];
}else{
sFileName = "[file]"+safiles[i];
}
lstFiles.addItem(sFileName);
}
add(lstFiles);
currentDir=dir;
}
Preguntas
Pregunta 1)
¿Cuál de los métodos siguientes sirve para distinguir entre un directorio y un archivo?
1) FileType()
2) isDir()
3) isDirectory()
4) getDirectory()
Pregunta 2)
¿Cuál de los siguientes métodos de la clase File borrará un directorio o un archivo al
ejecutarse?
Pregunta 3)
218
javaHispano. Tu comunidad, tu lenguaje.
Cómo puedes obtener los nombres de los archivos contenidos dentro de una instancia de
la clase File con el contenido del directorio actual
1) dir.list()
2) dir.list
3) dir.files()
4) dir.FileNames()
Pregunta 4)
¿Cuál de las siguientes líneas llenará una instancia de la clase File con el contenido del
directorio actual?
Pregunta 5)
1) f.write();
2) f.close();
3) f.flush();
4) Ninguno de los anteriores
Pregunta 6)
¿Cuál de las siguientes líneas cambiará el directorio actual al que se encuentra en un nivel
superior?
1) chDir("..");
2) cd(".");
3) up();
4) Ninguno de los anteriores
Pregunta 7)
219
Tutorial para el examen de certificación: SCJP 1.2
1) getParent()
2) separator
3) dirname
4) getName();
Respuestas
Respuesta 1)
3) isDirectory()
Respuesta 2)
3) delete()
Respuesta 3)
1) dir.list()
El método list retorna un arreglo de String´s que contendrá el contenido del directorio
actual.
Respuesta 4)
Este constructor para la clase File obtendrá el contenido del directorio actual sobre
sistemas de archivos como DOS o UNIX, pero no estoy seguro que ocurrirá sobre otros
sistemas con una estructura de archivos exótica como Mac OS.
Respuesta 5)
La clase File principalmente describe un archivo que debe de existir. Para crear un
archivo en el sistema operativo subyacente necesitas pasar una instancia de la clase File
a una instancia de una de las clases OutputStream.
Respuesta 6)
220
javaHispano. Tu comunidad, tu lenguaje.
Java no tiene una manera directa para cambiar el directorio actual. Una manera indirecta
es crear una nueva instancia de la clase File apuntando al directorio deseado.
Respuesta 7)
1) getParent()
2) separator
4) getName();
221
Tutorial para el examen de certificación: SCJP 1.2
Objetivo 2
Me sorprendió que este objetivo no se enfatizara en el examen de JDK 1.2 puesto que se
había introducido la internacionalización y ésta es una de las grandes características de
Java. Es bonito vender software a mil millones de europeos y americanos pero mil
millones de chinos serían un agradable mercado adicional (incluso si sólo el 10% lo
compran) Éste es el tipo de objetivo con el que ni siquiera los programadores de Java
experimentados pueden tener poca experiencia, ¡Así qué toma nota!.
Java utiliza dos sistemas muy parecidos de codificación UTF y UNICODE. Java fue
diseñado desde abajo para tenérselas que ver con caracteres multibyte y puede tratar con
inmensos números de caracteres que pueden guardarse usando el sistema de codificación
UNICODE. Los caracteres UNICODE son almacenados en 2 bytes permitiendo
almacenar arriba de 65K caracteres. Esto le permite ser usado con alfabetos no
occidentales. Esto significa que puede manipular chino y japonés, y casi cualquier otro
conjunto de caracteres conocido. Estarás agradecido de saber que no tienes que dar
ejemplos de nada de esto en el examen.
Aunque UNICODE puede representar casi cualquier carácter que llegues a usar en tu vida,
no es un método eficiente de codificación para programar. La mayoría del texto dentro de
un programa usa el código ASCII, la mayoría de este puede guardarse fácilmente dentro
de un byte. Por razones de tamaño, Java utiliza un sistema de codificación llamado UTF-
8 para las literales de cadena, identificadores y otro texto dentro del programa. Esto
puede dar como resultado un ahorro considerable de espacio comparándolo con el uso de
UNICODE donde cada carácter requiere 2bytes.
Si solo te las tienes que ver con conjuntos de caracteres de tipo ASCII, probablemente
solo usarás clases Reader en la forma de:
InputStreamReader(InputStream in)
222
javaHispano. Tu comunidad, tu lenguaje.
Esta versión usa el código de caracteres nativo de la plataforma. En el JDK1.1 este valor
por defecto se identifica por medio de la propiedad del sistema file.encoding. La
codificación predeterminada generalmente es ISO-Latin 1 excepto en Mac donde es
MacRoman. Si esta propiedad del sistema no esta definida, el identificador del código
estándar es 8859_1 (ISO-LATIN-1). La suposición parece ser: si todo lo demás falla,
debes volver al inglés. Experimentar con otros juegos de caracteres es problemático,
debido que los caracteres no pueden mostrarse correctamente si el entorno no se
configura apropiadamente. Así si intentas mostrar un carácter del conjunto de caracteres
chinos tu sistema quizá no lo soportará
Si te las tienes que ver con otros conjuntos de caracteres puedes usar
Ejemplo. GreekWriter
El código para esta clase escribe un archivo de salida contiene algunas letras en alfabeto
griego.
Si intentas abrir el archivo Out.txt con un editor, veras algo parecido a basura.
import java.io.*;
class GreekWriter {
public static void main(String[] args) {
String str = "\u03B1\u03C1\u03B5\u03C4\u03B7";
try {
Writer out = new OutputStreamWriter(
223
Tutorial para el examen de certificación: SCJP 1.2
Ejemplo. GreekReader
import java.io.*;
import java.awt.*;
try {
FileInputStream fis = new FileInputStream("out.txt");
InputStreamReader isr = new InputStreamReader(fis,"8859_7");
Reader in = new BufferedReader(isr);
} catch (IOException e) {
e.printStackTrace();
}
224
javaHispano. Tu comunidad, tu lenguaje.
GreekReader en ejecución.
Preguntas
Pregunta 1)
¿Cuales de las siguientes sentencias son verdaderas?
Pregunta 2)
¿Cuales de las siguiente sentencias son verdaderas?
225
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 3)
¿Cuales de las siguientes son firmas validas para la clase InputStreamReder?
Pregunta 4)
¿Cuales de los siguientes son métodos de la clase InputStreamReader?
1) read()
2) write()
3) getBuffer()
4) getString()
Pregunta 5)
¿Cuales de las siguientes son sentencias son verdaderas?
Respuestas
Respuesta 1)
2) La codificación predefinida para la clase OutputStreamWriter es ASCII
4) La clase InputStreanReader puede tomar un stream como de sus constructores.
Respuesta 2)
226
javaHispano. Tu comunidad, tu lenguaje.
Respuesta 3)
Respuesta 4)
1) read()
Respuesta 5)
JavaCaps:
http://www.javacaps.com/sjpc_io_obj2.html
227
Tutorial para el examen de certificación: SCJP 1.2
Objetivo 3
Distinguir entre las condiciones bajo las cuales se usaría conversión al código nativo de
plataforma y las condiciones bajo las cuales se usaría una conversión específica.
Este podría ser un objetivo de "bondad y disciplina". Con esto quiero decir que algunos
puritanos podrían tomar la actitud de que siempre deberías especificar el código de
conversión de caracteres porque nunca sabes donde, cuando y como se usará tu
programa. Esto es porque muchos programadores asumieron que su código nunca tendría
que vérselas con el problema del año 2000 por el que hubo tanto lío. Bien, es un buen
pago para algunos programadores.
Si tomas un punto de vista más benigno, este objetivo te pide identificar si tu código esta
preparado para enfrentarse a un código de caracteres no estándar. Si tu código de
caracteres por defecto no es ISO-LATIN-1 y consideras que el inglés es el lenguaje
estándar para los negocios, o si necesitas manipular distintos códigos de caracteres,
entonces aprovéchate de la posibilidad de hacer conversiones específicas.
Si algo de esto no significa nada para ti, vuelve a leer la sección anterior sobre las clases
de lectura y escritura de archivos.
228
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 4
Seleccionar los argumentos validos para los constructores de una lista de clases
contenidas en el paquete java.io.
El énfasis en este objetivo es que conozcas los argumentos validos para los constructores
de estas clases. Lo mas relevante que se puede mencionar es que la clase RandomFile
no toma algún stream como argumento para alguno de sus constructores.
Estas clases toman instancias de otros streams como argumentos. Así en el examen te
pueden preguntar si alguna de ellas puede tomar una instancia de la clase File, un
String con el nombre del archivo o la ruta del archivo, para ver si realmente conoces los
argumentos válidos para sus constructores. Un constructor valido será algún tipo de
stream más otros posibles parámetros.
import java.io.*;
public class Fis{
public static void main(String argv[]){
try{
FileInputStream in = new FileInputStream("Fis.java");
InputStreamReader isr = new InputStreamReader(in);
int ch=0;
while((ch = in.read())> -1){
StringBuffer buf = new StringBuffer();
buf.append((char)ch);
System.out.print(buf.toString());
}
} catch (IOException e){System.out.println(e.getMessage());}
}
}
229
Tutorial para el examen de certificación: SCJP 1.2
BufferedInputStream y BufferedOutputStream
Estas clases descienden directamente de las clases FilterInputStream y
FilterOutputStream respectivamente. Permiten leer más información de manera
inmediata colocándola en un buffer. Esto incrementa la eficiencia, ya que es mucho más
rápido leer desde la memoria que desde el disco. Este tipo de lectura es particularmente
útil si tienes que estar leyendo una gran cantidad de datos. Un ejemplo puede ser cuando
estés procesando varias decenas de Megabytes de texto. Las clases
BufferedInputStream y BufferedOutputStream toman una instancia de las clases
InputStream y OutputStream respectivamente como parámetro para alguno de sus
constructores, pero también pueden tomar un parámetro adicional que defina el tamaño
del buffer. Así, puedes ajustar el tamaño del buffer que vas a utilizar.
import java.io.*;
public class BufIn{
public static void main(String argv[]){
try{
FileInputStream fin = new FileInputStream("BufIn.java");
BufferedInputStream bin = new BufferedInputStream(fin);
int ch=0;
while((ch=bin.read())> -1){
StringBuffer buf = new StringBuffer();
buf.append((char)ch);
System.out.print(buf.toString());
}
}catch(IOException e){System.out.println(e.getMessage());};
}
}
DataInputStream y DataOutputStream
230
javaHispano. Tu comunidad, tu lenguaje.
La clase File
La clase File tiene tres versiones de constructores. Estos son:
File(String path);
File(String path, String name)
File(File dir, String name);
Los tres son muy similares y realizan la misma función. El primer constructor que toma
un String recibe el nombre de un archivo, incluyendo su ruta, en forma de cadena.
Esta ruta puede ser absoluta o relativa. El segundo toma por separado la ruta y el nombre
del archivo y el tercer constructor es casi igual al primero excepto que el primer
parámetro que indica el directorio del archivo es del tipo File en lugar del tipo String.
RandomAccesFile
Lo más importante que debes saber sobre los constructores de esta clase, es que toman 2
parámetros para sus constructores y que el segundo parámetro es un String que
contiene el modo de apertura del archivo. Más adelante se explica con detalle.
231
Tutorial para el examen de certificación: SCJP 1.2
Preguntas
Pregunta 1)
¿Cuáles de las siguientes clases con parámetros validos para los constructores de la clase
FileInputStream?
1) File
2) String
3) FileDescriptor
4) RadomAccessFile
Pregunta 2)
Pregunta 3)
Pregunta 4)
232
javaHispano. Tu comunidad, tu lenguaje.
dos.write('8');
}
}
1) El código no se compilará
2) No compilará debido a que la clase BufferedOutputStream no tiene un constructor
que tome como parámetro una instancia de la clase DataOutputStream
3) Se compilara y escribirá el byte 8 en el archivo
4) Se compilara y escribirá la cadena “8” en el archivo
Pregunta 5)
1) File(String path);
2) File(String path, String name)
3) RandomAccessFile(File)
4) File(RandomAccesFile name)
Pregunta 6)
import java.io.*;
public class Ppvg{
public static void main(String argv[]){
Ppvg p = new Ppvg();
p.go();
}
Respuestas
233
Tutorial para el examen de certificación: SCJP 1.2
Respuesta 1)
1) File
2) String
3) FileDescriptor
Respuesta 2)
Respuesta 3)
2) DataInputStream(FileInputStream in)
Respuesta 4)
1) El código no se compilará
Respuesta 5)
1) File(String path);
2) File(String path, String name)
Respuesta 6)
Data I/O
http://java.sun.com/products/jdk/1.2/docs/api/java/io/DataInputStream.html
http://java.sun.com/products/jdk/1.2/docs/api/java/io/DataOutputStream.html
234
javaHispano. Tu comunidad, tu lenguaje.
Objetivo 5
Escribir el código adecuado para leer, escribir o actualizar ficheros usando objetos
FileInputStream, FileOutputStream y RandomAccessFile.
El siguiente ejemplo crea un fichero de texto llamado Out.txt y escribe el texto "Hello" en
él. Si abres el fichero resultante verás que contiene el texto "H e l l o" (con un espacio en
blanco entre cada letra). Sospecho que es porque un carácter en Java es de 16 bits y uno
en ASCII son 8 bits, los 8 bits de más peso dan como resultado un carácter en blanco.
import java.io.*;
public class Fos{
String s = new String("Hello");
public static void main(String argv[]){
Fos f = new Fos();
f.amethod();
}
import java.io.*;
public class Fis{
235
Tutorial para el examen de certificación: SCJP 1.2
RandomAccessFile
Este ejemplo leerá el fichero Out.txt creado por el ejemplo anterior Fos.java.
Por culpa del byte superior en blanco (byte, no bit), el resultado muestra un signo de
interrogación con cada letra.
236
javaHispano. Tu comunidad, tu lenguaje.
import java.io.*;
public class Raf{
public static void main(String argv[]){
Raf r = new Raf();
r.amethod();
}
Pregunta 1)
Pregunta 2)
237
Tutorial para el examen de certificación: SCJP 1.2
Pregunta 3)
¿Cuales de las siguientes sentencias son verdaderas?
Pregunta 4)
import java.io.*;
public class Fos{
String s = new String("Hello");
public static void main(String argv[]){
Fos f = new Fos();
f.amethod();
}
1) Error al compilar
2) Error al ejecutar
3) Se creará un archivo llamado Out.txt conteniendo el texto "10"
4) Se creará un archivo llamado Out.txt
Pregunta 5)
¿Cuales de las siguientes sentencias son verdaderas?
238
javaHispano. Tu comunidad, tu lenguaje.
Respuestas
Respuesta 1)
Respuesta 2)
Respuesta 3)
Respuesta 4)
1) Error al compilar
Respuesta 5)
239
Tutorial para el examen de certificación: SCJP 1.2
O’reilly ha publicado un libro específico sobre Java I/O. Probablemente entra en más
detalle que el necesario para el examen de certificación pero navegar por los ejemplos
online te puede ayudar. El libro tiene generalmente buenas críticas en www.amazon.com
http://www.oreilly.com/catalog/javaio/
240