Slides de la tercera clase del curso de Java SCJP dictado en la Universidad Nacional de Centro de La Provincia de Buenos Aires.
Contenido:
1. Unidad 3: Asignaciones
2. Disclaimer & Acknowledgments
> Even though Ezequiel Aranda is a full-time employee of Sun
Microsystems, the contents here are created as his own
personal endeavor and thus does not reflect any official
stance of Sun Microsystems.
> Sun Microsystems is not responsible for any inaccuracies in
the contents.
> Acknowledgments – The slides of this presentation are made
from “SCJP Unit 1” by Warit Wanwithu and Thanisa
Kruawaisayawan and SCJP Workshop by P. Srikanth.
> This slides are Licensed under a Creative Commons
Attribution – Noncommercial – Share Alike 3.0
> http://creativecommons.org/licenses/by-nc-sa/3.0/
3. AGENDA
> iterales
L
> eferencias
R
> rrays
A
> rappers
W
> oxing y Widening
B
> obrecarga con boxing, widening y var-args
S
> arbage Collection
G
4. Stack y Heap
> as variables de instancia y los objetos se
L
almeacenan en el heap.
> as variables locales, en el stack.
L
5. Literales Octales
> Los enteros octales sólo
utilizan los dígitos del 0 al 7.
> En Java, se puede
representar un entero en
forma octal colocando un
cero delante del número.
int six = 06; // Equivale a 6
int seven = 07; // Equivale a 7
int eight = 010; // Equivale a 8
int nine = 011; // Equivale a 9
6. Literales Hexadecimales
> n valor hexadecimal comienza con 0x u OX.
U
> or Ejemplo:
P
int x = 0X0001;
int y = 0x7fffffff;
int z = 0xDeadCafe;
x= 1 y = 2147483647 z = -559035650
> XCAFE y 0xcafe son validos y tienen el mismo
0
valor.
7. Literales de punto flotante
> os literales de punto flotante están definidos
L
como double (64 bits) por defecto, por lo que
al asignar un literal a una variable float (32
bits), debemos colocarle el sufijo F (o f).
float f = 23.467890;
// falla la compilación
float g = 49837849.029847F;
8. Literales de caracter
> s posible escribirlos como el valor Unicode
E
del caracter, usando el prefijo u.
char letraN= 'u004E'; // la letra
'N'
> os caracteres son enteros sin signo de 16
L
bits.
char e = -29; // necesitará un cast
char f = 70000 // necesitará un cast
9. Primitivos vs. Referencias
> sto se llama Referencia:
E
Button b = new Button();
String s = new String();
> utton b = null;
B
Esto significa que “Button no refiere a ningún
objeto”
10. Asignaciones sobre primitivos
> e puede asignar un valor a una variable
S
primitiva usando un literal o el resultado de
una expresión.
int x = 7;
int y = x + 2;
int z = x * y;
byte b = 300;¿Esto compila?
11. Asignaciones sobre primitivos (II)
> yte b = 3; // 3 entra en un
b
byte
> yte c = 8; // 8 entra en un
b
byte
> yte d = b + c; //No debería
b
haber problema al sumar dos
bytes, pero ¿funciona? ¿Por
qué?
12. Casts en primitivos
> os casts (conversiones) pueden ser implícitos
L
o explícitos. Que sea implícito significa que
sucede automáticamente.
> os casts implícitos se dan al poner un tipo
L
más “pequeño” en un contenedor “más
grande”
> nt a = 100;
i
> ong b = a;//cast implícito: un int
l
simpre entra en un long.
13. Casts en primitivos (II)
> n valor que no cabe en un contenedor más
U
pequeño debe convertirse explícitamente,
indicando que conocemos la posibilidad de
perdida de información.
> float a = 100.001f;
> intb = (int) a; //cast explícito, el float
podría perder información.
14. Asignar un literal demasiado grande a
una variable
> i intentamos asignar un literal demasiado
S
grande a una variable obtendremos un error
de compilación.
float f = 32.3;
byte a = 128;
// byte llega hasta 127
> Qué pasa si hacemos esto?
¿
byte a = (byte) 128;
15. Asignando una variable primitiva a otra
class ValueTest{
public static void main (String [] args) {
int a = 25; // asignamos un valor a ‘a’
System.out.println(“first a = quot; + a);
int x = a;
x = 30;
System.out.println(“second a = quot; + a);
}
}
16. Asignación de variables de referencia
public class Foo{
public void doFooStuff() { }
}
public class Bar extends Foo{
public void doBarStuff() { }
}
class Test {
public static void main (String [] args{
Foo reallyABar= new Bar(); // Legal
Bar reallyAFoo= new Foo(); // Ilegal
}
}
17. Tiempo de vida de las variables
> Las variables estáticas se crean cuando se carga la clase
y sobreviven mientras la clase se mantenga cargada en
la JVM.
> Las variables de instancia se crean con cada instancia y
sobreviven hasta que la instancia es removida por el
garbage collector.
> Las variables locales viven mientras el método al que
pertenecen este en el stack. Más adelante veremos que
pueden estar vivas pero fuera de alcance.
> Las variables de bloque sólo viven mientras el bloque se
este ejecutando.
18. class Layout {
static int s = 343;
int x1;
{ x1 = 7; int x2 = 5; }
Layout(){
x1 += 8; int x3 = 6;
}
void doStuff() {
int y = 0;
for(int z = 0; z < 4; z++) {
y += z + x1;
}
System.out.println(quot;y =quot;+y);
}
}
19. Variables de instancia – tipos primitivos
public class BirthDate {
int year; // variable de instancia
public static void main(String [] args) {
BirthDate bd= new BirthDate();
bd.showYear();
}
public void showYear() {
System.out.println(quot;The year is quot; + year);
}
}
20. Variables de instancia – referencias a objetos
public class Book {
private String title;
public String getTitle() {
return title;
}
public static void main(String [] args){
Book b = new Book();
System.out.println(quot;The title is quot;+
b.getTitle());
}
}
21. Variables de instancia – referencias a objetos (II)
> null no es lo mismo que un string vacio. Significa
que la variable no hace referencia a ningún objeto
en el heap.
public class Book {
private String title;
// variable de instancia de referencia
public static void main(String[] args) {
Book b = new Book();
System.out.println(b.title);
String s = b.title.toLowerCase();
// Null pointer Exception
}
}
22. Primitivos Locales
> as variables locales,
L
incluyendo
primitivos, siempre
deben ser
inicializados antes de
utilizarlos.
> i intentamos utilizar un primitivo sin
S
inicializar, obtendremos un error de
compilación.
23. Referencias a objetos locales
> A las referencias locales no se les asigna un valor
por defecto (es decir, no son null por defecto). El
siguiente código no compila:
import java.util.Date;
public class TimeTravel{
public static void main(String[] args) {
Date date; // falla la compilación.
if (date == null)
System.out.println(quot;date es nullquot;);
}
}
24. Asignar una variable de referencia a otra
import java.awt.Dimension;
class ReferenceTest{
public static void main (String [] args){
Dimension a = new Dimension(5,10);
System.out.println(quot;a.height = quot; +
a.height);
Dimension b = a;
b.height = 30;
System.out.println(quot;a.height = quot; +
a.height +quot; after change to bquot;);
}
}
25. Asignar una variable de referencia
a otra (II)
> e declara b, y se le asignan el valor de a. En
S
este punto ambas variables contienen valores
identicos, porque los contenidos de a se
copiaron en b. Aún hay solo un objeto
Dimension, al que tanto a como b hacen
referencia.
> i asignamos la variable a a b, el patrón de
S
bits en a es copiado, y la nueva copia se
coloca en b.
26. String
> na excepción a la forma en la que se
U
asignan las referencias a objetos es String.
> os objetos String son inmutables, no se
L
puede cambiar el valor de un objeto String.
> iempre que hagamos un cambio en un
S
String, la VM actualizará la variable de
referencia para apuntar a un nuevo objeto.
27. String (II)
> e crea un nuevo String se crea (o se
S
encuentra uno nuevo en el String Pool),
dejando el original sin modificar.
> a referencia utilizada para modificar el
L
String se asigna al nuevo objeto.
28. Pasando referencias
> uando pasamos una variable
C
(referencia a objeto) a un método,
debemos tener en cuenta que estamos
pasando una referencia y no el objeto en
sí mismo.
29. import java.awt.Dimension;
class ReferenceTest{
public static void main (String [] args) {
Dimension d = new Dimension(5,10);
ReferenceTest rt= new ReferenceTest();
System.out.println(quot;Before modify()
d.height = quot;+ d.height);
rt.modify(d);
System.out.println(quot;After modify()
d.height = quot;+ d.height);
}
void modify(Dimension dim) {
dim.height = dim.height + 1;
System.out.println(quot;dim = quot; + dim.height);
}
}
30. class ReferenceTest {
public static void main (String [] args) {
int a = 1;
ReferenceTest rt = new ReferenceTest();
System.out.println(quot;Before = quot; +a);
rt.modify(a);
System.out.println(quot;After = quot; + a);
}
void modify(int number) {
number = number + 1;
System.out.println(quot;number = quot; + number);
}
}
31. Variables de instancia – Arrays
> n Array es un objeto, por lo tanto una
U
variable de instancia declarada pero no
inicializada explícitamente, tendrá un valor
null.
> ero… si el Array es inicializado, a todos los
P
elementos que lo componen se les asigna su
valor por defecto.
32. Pregunta
> qué imprime este código?
¿
public class NewClass{
static int x[];
static int y[] = new int[3];
public int z;
public static void main(String[] args){
System.out.println(x);
System.out.println(y);
System.out.println(y[0]);
System.out.println(x[1]);
System.out.println(z);
}
}
34. Arrays (II)
> nt[][] scores = {{5,2,4,7}, {9,2}, {3,4}};
i
> cores[0] // un array de cuatro ints
s
> cores[1] // un array de dos ints
s
> cores[2] // un array de dos ints
s
> cores[0][1] // valor entero 2
s
> cores[2][1] // valor entero 4
s
35. Arrays (III) – JIT Arrays
public class Foof{
void takesAnArray(int[] someArray) {
// usa el parámetro
}
public static void main (String [] args) {
Foof f = new Foof();
f.takesAnArray(new int[] {7,7,8,2,5});
}
}
36. Arrays de tipos primitivos
> nt[] weightList= new int[5];
i
> yte b = 4;
b
> har c = 'c';
c
> hort s = 7;
s
> eightList[0] = b; // OK, byte < int
w
> eightlist[1] = c; // OK, char < int
w
> eightList[2] = s; // OK, short < int
w
37. Arrays de referencias a objetos
> i el tipo declarado para un Array es una
S
clase, dicho Array podrá almacenar objetos de
cualquier subclase del tipo declarado.
class Car {}
class Subaru extends Car {}
class Ferrari extends Car {}
Car [] myCars = {new Subaru(), new
Car(), new Ferrari()};
38. Asignación de Arrays con
referencias a objetos
> ualquier objeto de una clase que
C
implemente una interfaz pasará la prueba “es
un” (instanceof) para dicha interfaz. Por
ejemplo, si Box implementa Foldable:
Foldable[] foldingThings;
Box[] boxThings= new Box[3];
foldingThings= boxThings;
> ero no podremos hacer
P
boxThings = foldingThings;
39. Bloques de inicialización
> n bloque de inicialización estático se ejecuta
U
una única vez, cuando se carga la clase.
> n bloque de inicialización de instancias se
U
ejecuta cada vez que se crea una instancia.
> e ejecutan en el orden en el que aparecen.
S
> os bloques de instancia se ejecutan luego de
L
la llamada a super() en el constructor.
41. ?
static int [] x = new int[4];
static { x[4] = 5; }
> Funciona?
¿
??
42. Wrappers
> n Java existe un wrapper por cada tipo
E
primitivo (Float de float, Integer de int, etc).
> odos los wrappers tienen dos constructores
T
(excepto Character): uno que toma un
primitivo del tipo que envuelve y uno que
toma una representación de tipo String del
tipo a construir.
Integer i1 = new Integer(42);
Integer i2 = new Integer(quot;42quot;);
43. Wrappers (II)
> a clase Character provee un único
L
constructor, que toma un char como
argumento.
Character c1 = new Character('c');
44. Conversión de Wrappers a primitivos
> uando necesitamos convertir el valor de
C
wrappers a primitivos, podemos usar alguno
de los métodos “____Value()” de esa clase.
Integer i2 = new Integer(42);
byte b = i2.byteValue();
short s = i2.shortValue();
double d = i2.doubleValue();
45. parse____() y valueOf()
> mbos toman un String como argumento y
A
arrojan una excepción
NumberFormatException si el String no tiene
el formato correcto.
long L2 = Long.parseLong(quot;101010quot;,2); //
String binario a primitivo: L2 = 42
Long L3 = Long.valueOf(quot;101010quot;, 2); //
String binario a objeto Long: L3 value
= 42
46. toString()
> a idea de este método es obtener una
L
representación coherente de un objeto dado.
> odos los wrappers poseen un método
T
toString estático sobrecargado que toma un
primitivo del tipo apropiado.
47. AutoBoxing
> n Java 5 aparece
E
esta característica
conocida como
autoboxing-
autounboxing o
simplemente boxing-
unboxing.
> int pInt = 420;
> Integer wInt = pInt; // ‘autoboxing’
> int p2 = wInt; // ‘auto-unboxing’
48. > Integer y = new Integer(567);
> int x = y.intValue(); // unwrap
> x++; // incremento
> y = new Integer(x); // re-wrap
> System.out.println(quot;y= quot; + y); // print
> Java 5:
> Integer y = new Integer(567);
> y++; // unwrap, incremento,rewrap
> System.out.println(quot;y= quot; + y); // print
> Ambos imprimen: y = 568
49. AutoBoxing (II)
Integer y = 567; // wrapper
Integer x = y;
System.out.println(y==x);
y++; // unwrap, uso, quot;rewrapquot;
System.out.println(x + quot; quot; + y);
System.out.println(y==x);
50. Boxing, ==, equals()
> or ahora, sabemos que la intención de
P
equals() es determinar cuando dos instancias
de una clase son “significativamente
equivalentes”.
Integer i1 = 1000;
Integer i2 = 1000;
if(i1 != i2)
System.out.println(quot;different
objectsquot;);
if(i1.equals(i2))
System.out.println(quot;meaningfully
equalquot;);
51. Boxing, ==, equals() (II)
> os instancias de Boolean, Byte, Character
D
(de u0000 a u007f), Short e Integer (-128 a
127) serán == si sus valores primitivos son
iguales.
Integer i3 = 10;
Integer i4 = 10;
if(i3 == i4)
System.out.println(quot;same objectquot;);
if(i3.equals(i4))
System.out.println(quot;meaningfully
equalquot;);
52. Sobrecarga
> eamos 3 cosas que pueden hacer la
V
sobrecarga un poco engañosa.
> idening
W
> utoBoxing
A
> ar-args
V
53. Widening
class EasyOver{
static void go(intx) { System.out.print(quot;intquot;); }
static void go(long x) { System.out.print(quot;long quot;); }
static void go(double x){ System.out.print(quot;doublequot;); }
public static void main(String [] args) {
byte b = 5;
short s = 5;
long l = 5;
float f = 5.0f;
go(b);
go(s);
go(l);
go(f);
En cada caso, cuando no se encuentra una
}}//
correspondencia exacta, la JVM usa el método con el
argumento que cumple con ser el “menor de los más
amplios” que el parámetro.
54. Sobrecarga con Boxing
class AddBoxing {
static void go(Integer x) {
System.out.println(quot;Integerquot;); }
static void go(long x) {
System.out.println(quot;longquot;); }
public static void main(String [] args) {
int i = 5;
go(i); // ¿Cuál de los go() se invoca?
}
}
> El compilador, ¿Decide hacer widening o
autoboxing?
55. Sobrecarga con var-args
class AddVarargs{
static void go(int x, int y) {
System.out.println(quot;int,intquot;);}
static void go(byte... x) {
System.out.println(quot;byte... quot;); }
public static void main(String[] args){
byte b = 5;
go(b,b); // ¿Cuál de los go() se invoca?
}
}
56. Conclusión
> l orden en que el compilador elige es el
E
siguiente:
1. Mismo tipo
2. Widening
3. Boxing
4. Var-args
57. Widening de referencias
class Animal {static void eat() { } }
class Dog3 extends Animal {
public static void main(String[] args) {
Dog3 d = new Dog3();
d.go(d); // ¿Esto vale?
}
void go(Animal a) { }
}
> l compilador “ensancha” la referencia de
E
Dog3 a Animal, y la invocación funciona
correctamente. La clave es que el widening
de referencias depende de la herencia.
58. Sobrecarga combinando widening y
boxing
> a regla es que el compilador puede ajustar
L
una invocación siempre y cuando sólo
requiera una única conversión.
class WidenAndBox{
static void go(Long x) {
System.out.println(quot;Longquot;); }
public static void main(String [] args)
{
byte b = 5;
go(b); // requiere widening y boxing -
ilegal
}}
59. Sobrecarga combinando Boxing y
Widening
class BoxAndWiden {
static void go(Object o) {
Byte b2 = (Byte) o;
System.out.println(b2);
}
public static void main(String [] args) {
byte b = 5;
go(b); // ¿Puede este byte volverse un
object?
}
}
> Funciona? ¿Por qué?
¿
60. Sobrecarga combinando con Var-args
class Vararg{
static void wide_vararg(long... x)
{System.out.println(quot;long...quot;);}
static void box_vararg(Integer... x)
{System.out.println(quot;Integer...quot;);}
public static void main(String [] args) {
int i = 5;
wide_vararg(5,5); // widening y var-args
box_vararg(5,5); // boxing y var-args
}
}
61. class Eggs {
int doX(Long x, Long y) { return 1; }
int doX(long... x) { return 2; }
int doX(Integer x, Integer y) { return 3; }
int doX(Number n, Number m) { return 4; }
public static void main(String[] args) {
new Eggs().go(); }
void go() {
short s = 7;
System.out.print(doX(s,s) + quot; quot;);
System.out.println(doX(7,7));
}}
> Cuál es el resultado?
¿
A. 1 1 B. 2 1 C. 3 3 D. 4 3
62. Resumen
> l widening de primitivos usa el tipo más
E
pequeño posible.
> oxing y Var-args, usados individualmente,
B
son compatibles con sobrecarga.
> o se puede ensanchar de un wrapper a otro.
N
> idening -> Boxing = falla
W
> oxing -> Widening = funciona
B
> uede combinarse Var-args con widening o
P
boxing.
63. Garbage Collection
> n C, C++ y otros lenguajes, el programador
E
es responsable de la administración de
memoria.
> n Java, se provee un hilo de sistema que se
E
encarga de esta tarea.
64. Garbage Collection (II)
> urante los ciclos ociosos de la JVM, el
D
garbage collector revisa y libera la memoria
que este en condiciones de ser liberada.
> Elegible” significa que puede ser
“
recolectado.
> olo podemos pedir el garbage collector
S
usando System.gc();
> o puede forzarse, sino más bien, sugerirse.
N
65. Garbage Collection (III)
> n el examen tendremos que identificar
E
cuales objetos son “elegibles” para ser
recolectados.
> a clave es encontrar los objetos que refieren
L
a NULL.
66.
67. class CardBoard{
Short story = 5;
CardBoard go(CardBoard cb) {
cb= null;
return cb; }
public static void main(String[] args) {
CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();
CardBoard c3 = c1.go(c2);
c1 = null;
// do Stuff
}}
> Cuando llegamos a “//do Stuff”, ¿Cuantos elementos son
elegibles para gc?
A. 0 B. 1 C. 2 D. no compila E. Excepción