Clase3 asignaciones

68
SCJP 6 Clase 3 – Asignaciones Ezequiel Aranda Sun Microsystems Campus Ambassador

Transcript of Clase3 asignaciones

Page 1: Clase3 asignaciones

SCJP 6 Clase 3 – Asignaciones

Ezequiel Aranda

Sun Microsystems Campus Ambassador

Page 2: Clase3 asignaciones

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/

Page 3: Clase3 asignaciones

AGENDA

>!Literales

>!Referencias

>!Arrays

>!Wrappers

>!Boxing y Widening

>!Sobrecarga con boxing, widening y var-args

>!Garbage Collection

Page 4: Clase3 asignaciones

Stack y Heap

>!Las variables de instancia y los objetos se almeacenan en el heap.

>!Las variables locales, en el stack.

Page 5: Clase3 asignaciones

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

Page 6: Clase3 asignaciones

Literales Hexadecimales

>!Un valor hexadecimal comienza con 0x u OX.

>!Por Ejemplo:

int x = 0X0001;

int y = 0x7fffffff;

int z = 0xDeadCafe;

x = 1 y = 2147483647 z = -559035650

>!0XCAFE y 0xcafe son validos y tienen el mismo valor.

Page 7: Clase3 asignaciones

Literales de punto flotante

>!Los literales de punto flotante están definidos 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;

Page 8: Clase3 asignaciones

Literales de caracter

>!Es posible escribirlos como el valor Unicode del caracter, usando el prefijo \u.

char letraN= '\u004E'; // la letra 'N'

>!Los caracteres son enteros sin signo de 16 bits.

char e = -29; // necesitará un cast

char f = 70000 // necesitará un cast

Page 9: Clase3 asignaciones

Primitivos vs. Referencias

>!Esto se llama Referencia:

Button b = new Button();

String s = new String();

>!Button b = null;

Esto significa que “Button no refiere a ningún objeto”

Page 10: Clase3 asignaciones

Asignaciones sobre primitivos

>!Se puede asignar un valor a una variable 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?

Page 11: Clase3 asignaciones

Asignaciones sobre primitivos (II)

>!byte b = 3; // 3 entra en un byte

>!byte c = 8; // 8 entra en un byte

>!byte d = b + c; //No debería haber problema al sumar dos bytes, pero ¿funciona? ¿Por qué?

Page 12: Clase3 asignaciones

Casts en primitivos

>!Los casts (conversiones) pueden ser implícitos o explícitos. Que sea implícito significa que sucede automáticamente.

>!Los casts implícitos se dan al poner un tipo más “pequeño” en un contenedor “más grande”

>!int a = 100;

>!long b = a;//cast implícito: un int simpre entra en un long.

Page 13: Clase3 asignaciones

Casts en primitivos (II)

>!Un valor que no cabe en un contenedor más 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.

Page 14: Clase3 asignaciones

Asignar un literal demasiado grande a una variable

>!Si intentamos asignar un literal demasiado 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;

Page 15: Clase3 asignaciones

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 = " + a);

int x = a;

x = 30;

System.out.println(“second a = " + a);

}

}

Page 16: Clase3 asignaciones

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

}

}

Page 17: Clase3 asignaciones

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.

Page 18: Clase3 asignaciones

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("y ="+y);

}

}

Page 19: Clase3 asignaciones

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("The year is " + year);

}

}

Page 20: Clase3 asignaciones

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("The title is "+ b.getTitle());

}

}

Page 21: Clase3 asignaciones

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

}

}

Page 22: Clase3 asignaciones

Primitivos Locales

>!Las variables locales, incluyendo primitivos, siempre deben ser inicializados antes de utilizarlos.

>!Si intentamos utilizar un primitivo sin inicializar, obtendremos un error de compilación.

Page 23: Clase3 asignaciones

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("date es null");

}

}

Page 24: Clase3 asignaciones

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("a.height = " + a.height);

Dimension b = a;

b.height = 30;

System.out.println("a.height = " + a.height +" after change to b");

}

}

Page 25: Clase3 asignaciones

Asignar una variable de referencia a otra (II)

>!Se declara b, y se le asignan el valor de a. En 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.

>!Si asignamos la variable a a b, el patrón de bits en a es copiado, y la nueva copia se coloca en b.

Page 26: Clase3 asignaciones

String

>!Una excepción a la forma en la que se asignan las referencias a objetos es String.

>!Los objetos String son inmutables, no se puede cambiar el valor de un objeto String.

>!Siempre que hagamos un cambio en un String, la VM actualizará la variable de referencia para apuntar a un nuevo objeto.

Page 27: Clase3 asignaciones

String (II)

>!Se crea un nuevo String se crea (o se encuentra uno nuevo en el String Pool), dejando el original sin modificar.

>!La referencia utilizada para modificar el String se asigna al nuevo objeto.

Page 28: Clase3 asignaciones

Pasando referencias

>!Cuando pasamos una variable (referencia a objeto) a un método, debemos tener en cuenta que estamos pasando una referencia y no el objeto en sí mismo.

Page 29: Clase3 asignaciones

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("Before modify() d.height = "+ d.height);

rt.modify(d);

System.out.println("After modify() d.height = "+ d.height);

}

void modify(Dimension dim) {

dim.height = dim.height + 1;

System.out.println("dim = " + dim.height);

}

}

Page 30: Clase3 asignaciones

class ReferenceTest {

public static void main (String [] args) {

int a = 1;

ReferenceTest rt = new ReferenceTest();

System.out.println("Before = " +a);

rt.modify(a);

System.out.println("After = " + a);

}

void modify(int number) {

number = number + 1;

System.out.println("number = " + number);

}

}

Page 31: Clase3 asignaciones

Variables de instancia – Arrays

>!Un Array es un objeto, por lo tanto una variable de instancia declarada pero no inicializada explícitamente, tendrá un valor null.

>!Pero… si el Array es inicializado, a todos los elementos que lo componen se les asigna su valor por defecto.

Page 32: Clase3 asignaciones

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);

}

}

Page 33: Clase3 asignaciones

Arrays >!int[][] myArray= new int[3][]; // Legal

Page 34: Clase3 asignaciones

Arrays (II)

>!int[][] scores = {{5,2,4,7}, {9,2}, {3,4}};

>!scores[0] // un array de cuatro ints

>!scores[1] // un array de dos ints

>!scores[2] // un array de dos ints

>!scores[0][1] // valor entero 2

>!scores[2][1] // valor entero 4

Page 35: Clase3 asignaciones

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});

}

}

Page 36: Clase3 asignaciones

Arrays de tipos primitivos

>!int[] weightList= new int[5];

>!byte b = 4;

>!char c = 'c';

>!short s = 7;

>!weightList[0] = b; // OK, byte < int

>!weightlist[1] = c; // OK, char < int

>!weightList[2] = s; // OK, short < int

Page 37: Clase3 asignaciones

Arrays de referencias a objetos

>!Si el tipo declarado para un Array es una 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()};

Page 38: Clase3 asignaciones

Asignación de Arrays con referencias a objetos

>!Cualquier objeto de una clase que 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;

>!Pero no podremos hacer

boxThings = foldingThings;

Page 39: Clase3 asignaciones

Bloques de inicialización

>!Un bloque de inicialización estático se ejecuta una única vez, cuando se carga la clase.

>!Un bloque de inicialización de instancias se ejecuta cada vez que se crea una instancia.

>!Se ejecutan en el orden en el que aparecen.

>!Los bloques de instancia se ejecutan luego de la llamada a super() en el constructor.

Page 40: Clase3 asignaciones

class Init {

Init(int x) {

System.out.println("1-arg const");

}

Init() {

System.out.println("no-arg const");

}

static { System.out.println("1st static init");}

{ System.out.println("1st instance init"); }

{ System.out.println("2nd instance init"); }

static { System.out.println("2nd static init"); }

public static void main(String [] args) {

new Init();

new Init(7);

}

}

Page 41: Clase3 asignaciones

?

static int [] x = new int[4];

static { x[4] = 5; }

>!¿Funciona?

? ?

Page 42: Clase3 asignaciones

Wrappers

>!En Java existe un wrapper por cada tipo primitivo (Float de float, Integer de int, etc).

>!Todos los wrappers tienen dos constructores (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("42");

Page 43: Clase3 asignaciones

Wrappers (II)

>!La clase Character provee un único constructor, que toma un char como argumento.

Character c1 = new Character('c');

Page 44: Clase3 asignaciones

Conversión de Wrappers a primitivos

>!Cuando necesitamos convertir el valor de 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();

Page 45: Clase3 asignaciones

parse____() y valueOf()

>!Ambos toman un String como argumento y arrojan una excepción NumberFormatException si el String no tiene el formato correcto.

long L2 = Long.parseLong("101010",2); // String binario a primitivo: L2 = 42

Long L3 = Long.valueOf("101010", 2); // String binario a objeto Long: L3 value = 42

Page 46: Clase3 asignaciones

toString()

>!La idea de este método es obtener una representación coherente de un objeto dado.

>!Todos los wrappers poseen un método toString estático sobrecargado que toma un primitivo del tipo apropiado.

Page 47: Clase3 asignaciones

AutoBoxing

>!En Java 5 aparece esta característica conocida como autoboxing-autounboxing o simplemente boxing-unboxing.

>!int pInt = 420;

>!Integer wInt = pInt; // ‘autoboxing’

>!int p2 = wInt; // ‘auto-unboxing’

Page 48: Clase3 asignaciones

>!Integer y = new Integer(567);

>!int x = y.intValue(); // unwrap

>!x++; // incremento

>!y = new Integer(x); // re-wrap

>!System.out.println("y= " + y); // print

>!Java 5:

>!Integer y = new Integer(567);

>!y++; // unwrap, incremento,rewrap

>!System.out.println("y= " + y); // print

>!Ambos imprimen: y = 568

Page 49: Clase3 asignaciones

AutoBoxing (II)

Integer y = 567; // wrapper

Integer x = y;

System.out.println(y==x);

y++; // unwrap, uso, "rewrap"

System.out.println(x + " " + y);

System.out.println(y==x);

Page 50: Clase3 asignaciones

Boxing, ==, equals()

>!Por ahora, sabemos que la intención de equals() es determinar cuando dos instancias de una clase son “significativamente equivalentes”. Integer i1 = 1000;

Integer i2 = 1000;

if(i1 != i2) System.out.println("different objects");

if(i1.equals(i2))

System.out.println("meaningfully equal");

Page 51: Clase3 asignaciones

Boxing, ==, equals() (II)

>!Dos instancias de Boolean, Byte, Character (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("same object");

if(i3.equals(i4))

System.out.println("meaningfully equal");

Page 52: Clase3 asignaciones

Sobrecarga

>!Veamos 3 cosas que pueden hacer la sobrecarga un poco engañosa.

>!Widening

>!AutoBoxing

>!Var-args

Page 53: Clase3 asignaciones

Widening class EasyOver{

static void go(intx) { System.out.print("int"); }

static void go(long x) { System.out.print("long "); }

static void go(double x){ System.out.print("double"); }

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.

Page 54: Clase3 asignaciones

Sobrecarga con Boxing

class AddBoxing {

static void go(Integer x) {

System.out.println("Integer"); }

static void go(long x) {

System.out.println("long"); }

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?

Page 55: Clase3 asignaciones

Sobrecarga con var-args class AddVarargs{

static void go(int x, int y) {

System.out.println("int,int");}

static void go(byte... x) {

System.out.println("byte... "); }

public static void main(String[] args){

byte b = 5;

go(b,b); // ¿Cuál de los go() se invoca?

}

}

Page 56: Clase3 asignaciones

Conclusión

>!El orden en que el compilador elige es el siguiente:

1.! Mismo tipo

2.! Widening

3.! Boxing

4.! Var-args

Page 57: Clase3 asignaciones

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) { }

}

>!El compilador “ensancha” la referencia de Dog3 a Animal, y la invocación funciona correctamente. La clave es que el widening de referencias depende de la herencia.

Page 58: Clase3 asignaciones

Sobrecarga combinando widening y boxing

>!La regla es que el compilador puede ajustar una invocación siempre y cuando sólo requiera una única conversión. class WidenAndBox{

static void go(Long x) {

System.out.println("Long"); }

public static void main(String [] args) {

byte b = 5;

go(b); // requiere widening y boxing -ilegal

}}

Page 59: Clase3 asignaciones

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é?

Page 60: Clase3 asignaciones

Sobrecarga combinando con Var-args class Vararg{

static void wide_vararg(long... x)

{System.out.println("long...");}

static void box_vararg(Integer... x)

{System.out.println("Integer...");}

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

}

}

Page 61: Clase3 asignaciones

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) + " ");

System.out.println(doX(7,7));

} }

>!¿Cuál es el resultado?

A. 1 1 B. 2 1 C. 3 3 D. 4 3

Page 62: Clase3 asignaciones

Resumen

>!El widening de primitivos usa el tipo más pequeño posible.

>!Boxing y Var-args, usados individualmente, son compatibles con sobrecarga.

>!No se puede ensanchar de un wrapper a otro.

>!Widening -> Boxing = falla

>!Boxing -> Widening = funciona

>!Puede combinarse Var-args con widening o boxing.

Page 63: Clase3 asignaciones

Garbage Collection

>!En C, C++ y otros lenguajes, el programador es responsable de la administración de memoria.

>!En Java, se provee un hilo de sistema que se encarga de esta tarea.

Page 64: Clase3 asignaciones

Garbage Collection (II)

>!Durante los ciclos ociosos de la JVM, el garbage collector revisa y libera la memoria que este en condiciones de ser liberada.

>!“Elegible” significa que puede ser recolectado.

>!Solo podemos pedir el garbage collector usando System.gc();

>!No puede forzarse, sino más bien, sugerirse.

Page 65: Clase3 asignaciones

Garbage Collection (III)

>!En el examen tendremos que identificar cuales objetos son “elegibles” para ser recolectados.

>!La clave es encontrar los objetos que refieren a NULL.

Page 66: Clase3 asignaciones
Page 67: Clase3 asignaciones

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

Page 68: Clase3 asignaciones

Preguntas