Java:Vector <subclass>向Vector <class>的不需要的向上转换

时间:2018-01-17 11:10:47

标签: java list polymorphism downcast

我正在构建一个管理Vector<Studente>Vector<StudenteLaureato>类型的课程,其中StudenteLaureato扩展Studente。 在我添加合并inserisciLaureatiVector<Studente>的方法Vector<StudenteLaureato>之前,一切正常。 现在,当我传递stampaDati一个Vector<Studente>也包含StudenteLaureato个对象时,它不会打印它们的子类特定属性。无法弄清楚如何编辑功能来解决这个问题。

public class GestioneRegistro {
    private Vector<Studente> elenco = new Vector<Studente>();

    Vector<Studente> letturaDati(String nomeFileDaLeggere) {
    System.out.println("inizio la lettura");
    String rowRead;
    BufferedReader in;
    in = new BufferedReader(new InputStreamReader(new FileInputStream(nomeFileDaLeggere)));
        while((rowRead = in.readLine()) != null) {
            StringTokenizer st = new StringTokenizer(rowRead);
            StudenteLaureato s = new StudenteLaureato(st.nextToken(), st.nextToken(), st.nextToken());
            elenco.add(s);
        }
    return elenco;
    }

    public void stampaDati(Vector<Studente> elencoloc){
        List<Studente> arrlist = new ArrayList<Studente>();
        Enumeration<Studente> e = elencoloc.elements(); 
        arrlist = Collections.list(e);
        System.out.println("Contenuto di elenco: "+arrlist);
    }

    public Vector<Studente> merger(Vector<Studente> Va, Vector<Studente> Vb) {
          Vector<Studente> merge = new Vector<Studente>();
          merge.addAll(Va);
          merge.addAll(Vb);
          return merge;
        }
    public void inserisciLaureati(Vector<Studente> elencoloc, String nomeFileDaLeggere) {
        elencoloc = merger( elencoloc, letturaDati(nomeFileDaLeggere));
    }

    public static void main(String args[]) {
    GestioneRegistro reg = new GestioneRegistro();
    Vector<Studente> elencoloc = new Vector<Studente>();
    elencoloc = reg.letturaDati(args[0]);
    reg.stampaDati(elencoloc);
    reg.inserisciLaureati(elencoloc, "C:\\Users\\Nixon\\Desktop\\archiviolau.txt");
}
}

Studente就是这样:

public class Studente implements Serializable{
    private static final long serialVersionUID = 1L;

    String nome;
    String cognome;
    String matricola;

    public Studente(String n, String c, String m){
        nome = n;
        cognome = c;
        matricola = m;
    }
    public String toString() {
        return nome+" "+cognome+" "+matricola;
    }
}

和StudenteLaureato是这样的:

public class StudenteLaureato extends Studente {
    private static final long serialVersionUID = 1L;

    String indirizzo;
    String dataLaurea;
    public StudenteLaureato(String n, String c, String m, String i, String d) {
        super(n, c, m);
        indirizzo = i;
        dataLaurea = d;
    }
    public StudenteLaureato(String n, String c, String m){
        super(n, c, m);
    }
    public String toString() {
        return nome+" "+cognome+" "+matricola+" "+indirizzo+" "+dataLaurea;
    }
}

1 个答案:

答案 0 :(得分:0)

您必须告诉编译器您merge方法接受ClassA和所有子类的向量。这称为covariance,在Java中,您使用通配符?

class A {}
class B extends A {}
class C extends A {}

public void foo(List<A> as, List<B> bs, List<C> cs) {
    merge(as,as);
    merge(bs,bs);
    merge(cs,cs);
    merge(bs,as);
    merge(cs,as);
    merge(bs,cs);
}

public <T> List<T> merge(List<? extends T> x, List<? extends T> y) {
    List<T> result = new ArrayList<T>();
    result.addAll(x);
    result.addAll(y);

    return result;
}

现在,编译器将类型T推断为xy元素的父类型。

对通配符类型及其在Effective Java中作为参数的用法有一个非常好的解释。我肯定会建议你阅读这篇文章。

您也可以直接将其编码为类型变量的约束。但是,由于我们对XY类型不感兴趣,只是它们是T的某个子类,我更喜欢通配符。

public <T, X extends T, Y extends T> List<T> merge(List<X> x, List<Y> y) {
    List<T> result = new ArrayList<T>();
    result.addAll(x);
    result.addAll(y);

    return result;
}

It also recommended to not use the old collection classes such as Vector.