Casting

di il
13 risposte

Casting

Salve, dato che nell'esame alcuni esercizi propongono di risolvere esercizi sul casting esplicito mi piacerebbe sapere se c'è uno schema che racchiude i possibili casting espliciti e non. Dovrei avrei errore di compilazione?

13 Risposte

  • Re: Casting

    giulio0 ha scritto:


    Salve, dato che nell'esame alcuni esercizi propongono di risolvere esercizi sul casting esplicito mi piacerebbe sapere se c'è uno schema che racchiude i possibili casting espliciti e non. Dovrei avrei errore di compilazione?
    L'argomento è un pochino ampio. Innanzitutto il cast può essere implicito o esplicito. E si può applicare a tipi primitivi o tipi reference.
    Quali sono esattamente i tuoi dubbi?
  • Re: Casting

    Quando lo si può e non lo si può fare, per esempio:
    int i;
    boolean b;

    i = (int) b; // non fattibile perché il boolean non può essere mai convertito
    b = (boolean) i; //fattibile (credo)
  • Re: Casting

    giulio0 ha scritto:


    int i;
    boolean b;

    i = (int) b; // non fattibile perché il boolean non può essere mai convertito
    b = (boolean) i; //fattibile (credo)
    NO, nessuno dei due è lecito. Il boolean NON può essere convertito a/da qualunque altro primitivo. Il boolean è un tipo "da solo", a sé stante.

    -----------------

    Partiamo da alcuni concetti: innanzitutto il cast può essere implicito solo se è un widening (un "allargamento" o up-cast). Se è un narrowing ("restringimento" o down-cast) deve essere esplicito. C'è una sola situazione in cui un narrowing può essere implicito. Quando una costante byte/short/char/int viene assegnata ad una variabile di tipo più piccolo e il valore della costante "ci sta" in quella variabile. Es.

    byte b = 120;

    120 è una costante int. Ma ci sta come valore in un byte. E per via di questa regoletta speciale, questo narrowing implicito è lecito.

    Il widening sui primitivi è abbastanza facile, perché detto in generale non fa "perdere" nulla. Ci sono 2 casi particolari però:
    - da int a float
    - da long a double

    int e float sono entrambi a 32 bit. Ma il float ha meno bit per la parte significativa (perché c'è anche l'esponente). Quindi se passi da int a float mantieni sicuramente la "grandezza" del valore ma PUOI perdere in precisione.
    Cosa similare per long->double entrambi a 64 bit.

    Il narrowing sui primitivi invece è più grave. Detto in generale: puoi perdere la grandezza, la precisione e (attenzione!) pure il segno.

    -----------------

    Con i tipi reference il discorso è diverso. Bisogna avere ben chiaro cosa è lecito per il compilatore e cosa invece può succedere a runtime.

    Il widening sui reference è facile (e può essere implicito). Basta assegnare ad un super-tipo, detto in generale (super-classe o interfaccia implementata).
    String str = "ciao";
    Object o = str;          // 2
    CharSequence cs = str;   // 3
    Object è una superclasse di String e CharSequence è una interfaccia implementata da String. Sono, in generale, "super tipi" rispetto a String, quindi nelle righe 2 e 3 c'è un widening implicito.

    Il narrowing deve essere esplicito ed è un cast "controllato" a runtime. Per il compilatore è sufficiente che il cast teoricamente sia sensato. Non si può fare ad esempio un cast da un Number ad un String. Il compilatore "sa" già (lo deduce dai tipi) che NON sono in linea di ereditarietà.

    Mentre invece ad esempio un Object può essere castato ad un String. Ma ... quale è l'oggetto realmente assegnato alla variabile Object fa sì che il cast a runtime abbia successo o fallisca.

    Object o = "abc";
    String s = (String) o;

    Il cast è lecito (una variabile di tipo Object può fare riferimento ad un String). E a runtime il cast ha successo, perché l'oggetto è realmente un String.

    Object o = new Integer(123);
    String s = (String) o;

    Qui il cast è ancora sempre lecito per il compilatore ma FALLISCE a runtime con un bel ClassCastException. Perché l'oggetto non è realmente un String.

    Ci sarebbero svariate altre cose da dire, specialmente sui cast tra classi e interfacce. Ma non posso fare un manualone in un post ...

    Posso aggiungere una cosa: da Java 5, se non lo sai, esiste il auto-boxing/unboxing che permette di trattare i primitivi e le rispettive classi "wrapper" (Byte, Short, ecc...) in maniera praticamente interscambiabile.

    Il Java Language Specification dice che è possibile fare un boxing di un primitivo opzionalmente seguito da un widening del reference. Tipo ad esempio:

    int i = 123;
    Object o = i;

    La catena di cast è: int ---> Integer (per auto-boxing) e poi Integer ---> Object (per widening del reference).

    Ed è anche possibile un unboxing opzionalmente seguito da un widening del primitivo, tipo in:

    Integer i = new Integer(123);
    long l = i;

    Nota che non c'è un cast esplicito! Per via del auto-unboxing è come se quel i "fosse" un int primitivo. Quindi Integer ---> int (per unboxing) e poi int ---> long (widening implicito)
  • Re: Casting

    Ciao per caso ho trovato una tua risposta che si completa a questa qui, ti cito il link:


    Nella risposta dici che in Java "In Java se S è un sottotipo di T, allora S[] è un sottotipo di T[]. Esempio: Integer è un sottotipo di Object, pertanto Integer[] è un sottotipo di Object[].", m'interessava capire quali sono i sottotipi dei tipi. Nel senso che Object ha come sottotipi intero, double(?), float(?), string(?), boolean(no)?

    Comunque grazie per il messaggio precedente che è stato delucidante
  • Re: Casting

    giulio0 ha scritto:


    m'interessava capire quali sono i sottotipi dei tipi. Nel senso che Object ha come sottotipi intero, double(?), float(?), string(?), boolean(no)?
    java.lang.Object è la classe "padre" di TUTTI gli oggetti in Java.

    Se ti riferisci alle classi "wrapper" dei primitivi, innanzitutto java.lang.Number estende Object. Poi le classi Byte, Short, Integer, Long ecc.. estendono Number.
    E comunque la gerarchia delle classi la puoi benissimo vedere nella documentazione javadoc del framework.
  • Re: Casting

    Va bene grazie per la dritta. vorrei analizzare con te due esercizi per verifica.
    La traccia: quali tra questi dà errore di compilazione?
       String d;
                Integer e;
                Object z;
                
              A. d = z;
              B. d = (String) e;
              C. d = e; //Questa è la risposta corretta?
              D. e = z;
              E. z =(Object) e;
    Scelto la C perché gli altri casi sono leciti poiché un intero può essere convertito in stringa se esplicitato ed un oggetto è superclasse di stringa ed intero.

    e quest'altro:
    [code ]Object g; Error r; Integer s; s = new Integer(0); r = new Error(); g = Integer(0); A. r = (Error) g; B. s = (Integer) g; C. r = (Error) s; D. s = (Integer) r; Nella seconda azzardo la D (?)
  • Re: Casting

    giulio0 ha scritto:


    Nella seconda azzardo la D (?)
    Perdonami, ma a che facoltà sei iscritto? Filosofia?
    Scarica NetBeans o altro e vedi direttamente cosa non compila.
  • Re: Casting

    giulio0 ha scritto:


    Scelto la C perché gli altri casi sono leciti poiché un intero può essere convertito in stringa se esplicitato ed un oggetto è superclasse di stringa ed intero.
    No.

    La A NON compila. Un Object non lo puoi "vedere" implicitamente come String. Deve esserci un cast (down-cast) esplicito a String (poi cosa succeda a runtime, dipende dall'oggetto realmente assegnato).
    La B NON compila. La variabile e è di tipo Integer. NON c'è modo di fare un cast a String. Il compilatore "sa" che Integer non c'entra nulla con String, quindi errato.
    La C NON compila (idem, similare alla B ma anche peggio)
    La D NON compila (stessa identica cosa come la A)
    La E COMPILA (nota: il cast è esplicitato ma può essere implicito, un Integer è-un Object).

    giulio0 ha scritto:


    e quest'altro:
    Nella seconda azzardo la D (?)
    Nota: c'è scritto g = Integer(0); ma presumo volessi scrivere g = new Integer(0);
    Se così, ok.


    La A compila (Error sicuramente deriva da Object) quindi è possibile che la variabile g (Object) faccia riferimento ad un Error. Ma a runtime FALLISCE, perché g fa riferimento realmente ad un oggetto Integer.
    La B compila e a runtime ha SUCCESSO, perché g fa riferimento ad un oggetto Integer.
    La C NON compila, una variabile Integer NON può essere vista come Error (non c'entrano niente tra di loro)
    La D NON compila (stesso discorso come C)


    P.S. devi ancora chiarirti le idee ...
    P.S.2: "provare" quei codici su un IDE/compilatore NON ti aiuta più di tanto se non hai compreso i concetti .. io per risponderti non li ho affatto provati .. i concetti li so.
  • Re: Casting

    andbin ha scritto:



    Nota: c'è scritto g = Integer(0); ma presumo volessi scrivere g = new Integer(0);
    Se così, ok.
    O magari Integer.valueOf(0)

    andbin ha scritto:



    P.S.2: "provare" quei codici su un IDE/compilatore NON ti aiuta più di tanto se non hai compreso i concetti .. io per risponderti non li ho affatto provati .. i concetti li so.
    Vabbè ma tu sei tu
  • Re: Casting

    AH HO CAPITO! Purtroppo interpretavo male la traccia che in originale è: "Quali tra questi assegnamenti è corretto in tempo di compilazione?" Interpretavo "corretto" nel senso sbagliato come "quale il compilatore non accetta?", quindi andavo a pensare che tutti fossero giusti tranne uno, mentre andava interpretato "Qual è quello giusto?". Infatti adesso torna tutto.
  • Re: Casting

    Weierstrass ha scritto:


    giulio0 ha scritto:


    Nella seconda azzardo la D (?)
    Perdonami, ma a che facoltà sei iscritto? Filosofia?
    Scarica NetBeans o altro e vedi direttamente cosa non compila.
    Scusa pensavo che fosse un forum.
  • Re: Casting

    giulio0 ha scritto:


    Weierstrass ha scritto:


    giulio0 ha scritto:


    Nella seconda azzardo la D (?)
    Perdonami, ma a che facoltà sei iscritto? Filosofia?
    Scarica NetBeans o altro e vedi direttamente cosa non compila.
    Scusa pensavo che fosse un forum.
    Infatti fai bene a chiedere, però così perdi tempo. Già con un IDE lo capivi da solo che le cose sbagliate erano più di una. Compili e vedi se ti viene in mente qualcosa, altrimenti vieni a chiedere perché non compila la D
  • Re: Casting

    Weierstrass ha scritto:


    giulio0 ha scritto:


    Weierstrass ha scritto:




    Perdonami, ma a che facoltà sei iscritto? Filosofia?
    Scarica NetBeans o altro e vedi direttamente cosa non compila.
    Scusa pensavo che fosse un forum.
    Infatti fai bene a chiedere, però così perdi tempo. Già con un IDE lo capivi da solo che le cose sbagliate erano più di una. Compili e vedi se ti viene in mente qualcosa, altrimenti vieni a chiedere perché non compila la D
    Infatti avevo compilato però avendo un incongruenza con la traccia non arrivavo alla conclusione...
Devi accedere o registrarti per scrivere nel forum
13 risposte