2012-01-11 13 views
7

Penso che mi manchi qualcosa di base qui. Qualsiasi spiegazione o suggerimento alle domande precedenti sarà molto utile.È una sottoclasse dell'array String di un array Object?

import java.util.Arrays; 
import java.util.List; 

public class St { 

    public static void bla(Object[] gaga) { 
      gaga[0] = new Date(); // throws ArrayStoreException 
     System.out.println(gaga[0]); 
    } 

    public static void bla(List<Object> gaga) { 
     System.out.println(gaga.get(0)); 
    } 

    public static void main(String[] args) { 
      String[] nana = { "bla" }; 
     bla(nana); // Works fine 

     List<String> bla1 = Arrays.asList(args); 
     bla(bla1); // Wont compile 

      System.out.println(new String[0] instanceof Object[]); // prints true 
      System.out.println(nana.getClass().getSuperclass().getSimpleName()); // prints Object 
    } 

} 

Così, sembra come un List<String> non è una sottoclasse di un List<Object> ma un String[] è una sottoclasse di Object[].

È un'ipotesi valida? Se è così, perché? Se no, perché?

Grazie

risposta

10

Java arrays are covariant, cioè permettono Object[] foo = new String[2];. Ma questo non significa che siano sottoclassi. String[] è una sottoclasse di Object (anche se instanceof restituisce true, String[].class.getSuperclass() rendimenti Object)

+0

Dal commento @maerics qui sotto - il 'new String [0] instanceof Object []' restituisce true. Quindi, String [] è un tipo di oggetto e un tipo di oggetto [] e un tipo di CharSequence [] ecc. Corretto? – Kal

+0

@Kal che sembra essere un caso speciale per coprire la covarianza. Vedi il mio aggiornamento – Bozho

+0

Grazie .. Ho appena visto la tua modifica. – Kal

3
(new String[0] instanceof Object[]) // => true 
3

Lei ha ragione. I tipi di matrice sono covarianti in Java in base alla progettazione, ma uno Foo<Sub> non è un Foo<Super>.

5

Sì, la tua ipotesi è valida. Come detto da @Bozho gli array sono covarianti, mentre le raccolte generiche (come l'Elenco generico) non sono covarianti.

covarianza in array è rischioso:

String[] strings = new String[] { "a", "b" } 
Object[] objects = strings; 
objects[0] = new Date(); // <-- Runtime error here 
String s = strings[0]; 
s.substring(5, 3);  // ????!! s is not a String 

La terza linea spara un'eccezione runtime. Se non si attiva questa eccezione, è possibile ottenere una variabile String, s, che fa riferimento a un valore che non è un String (né un suo sottotipo): a Date.

+0

Grazie .. Non ho mai visto l'ArrayStoreException prima. – Kal

2

String [] è una sottoclasse di Object []

corretta, vedi 4.10.3 Subtyping among Array Types:

Se S e T sono entrambi i tipi di riferimento, quindi S []> 1 T [ ] sse S> 1 T.

Da String >1 Object così String[] >1 Object[]

Cioè, String[] è un sottotipo diretta di Object[]

Oggetto> 1 Object []

Perciò Object > String[]; String[] è una (indiretta?) sottotipo di Object

Non esiste tale relazione per i medicinali generici, in modo da List<String> > List<Object> non è vero.

Ora, si consideri il seguente esempio semplice:

import java.util.*; 

class G { 
    interface I { 
    void f(); 
    } 
    class C implements I { 
    public void f() {} 
    } 

    void allF(List<I> li) { 
    for (I i : li) { i.f(); } 
    } 

    void x(List<C> lc) { 
    allF(lc); 
    } 
} 

E non si compila, perché x invoca allF con una List<C> che non è un List<I>. Per essere in grado di utilizzare List<C> la firma deve cambiare un po ':

void allF(List<? extends I> li) { 

Ora si compila. Informalmente, li è un List di qualche tipo che si estende/implementa I. Quindi List<C> è assegnabile aList<? extends I>. Quello che puoi fare con un elenco di questo tipo è limitato. In sostanza, puoi leggerlo/accedervi ma non lo puoi write/modify.

+0

Umm ... sottotipo e sottoclasse significano cose diverse. –

+1

@StephenC, per le sottotitoli delle classi è uguale alla sottoclasse, se sto leggendo [4.10.2] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls- 4.10.2). Immagino che la risposta corretta sarebbe "Gli array non sono classi in modo che non possano avere una relazione sottoclasse ma String [] * è * a * sybtype * di Object []". E 'quello che stai suggerendo? –

Problemi correlati