使用泛型:使用泛型中的父值和子值实例化泛型类的对象

时间:2018-04-28 03:04:12

标签: java generics subtyping

考试中提出的问题是: 编写一个名为Registration的类,它可以存储T类型的变量,其中T可以用String替换, 人,学生等。应该可以按如下方式实例化注册:

Registration<String> r1 = new Registration<String>();
Registration<Person> r2 = new Registration<Student>();

我无法弄清楚如何为类标题的泛型部分编写声明。下面我给出了注册课程。要注意,Student类继承Person类。

import java.util.List;
import java.util.ArrayList;
public class Registration<T extends Person> //I believe my issue is here{
private T [] roster;
private List<T> waitList;
private static int rosterCount;
private T lastInstance;

public Registration () {
    roster =  (T[]) new Object[100];
    waitList = new ArrayList<>();
    rosterCount = 0;
    lastInstance = null;
}

public void addIndex (T t) {
    if (rosterCount>=100) {
        waitList.add(t);
    }
    else {
        roster [rosterCount] = t;
        rosterCount++;
    }
    lastInstance = t;
}

public T getLastInstance() {
    return lastInstance;
}

public int getRosterCount() {
    return rosterCount;
}

public int getWaitListCount() {
    return waitList.size();
}
}

**取自Uoft CSC207 Aug2017考试

3 个答案:

答案 0 :(得分:1)

如果Registration必须足够通用以接受任何类型,例如。 String,然后你应该声明为:

class Registration<T> {
    private T[] roster;
    ...
    public Registration (Class<T> clazz) {
        roster = (T[])Array.newInstance(clazz, 100);
    }
    ...
} 

答案 1 :(得分:0)

以下代码段可以做,请注意

Registration<Person> r2 = new Registration<Student>(); 

是不可能的,所以在底部重写。

    static class Person  {}
    static class Student extends Person {}

    static class Registration<T> {
        private T[] roster;
        private List<T> waitList;
        static int rosterCount;
        private T lastInstance;

        public Registration() {
            roster =  (T[]) new Object[100]; ;
            waitList = new ArrayList<T>();
        }
    }

    public static void main(String[] args) {
        Registration<String> r1 = new Registration<String>();
        Registration<? extends Person> r2 = new Registration<Student>();
    }

答案 2 :(得分:0)

问题是错误的,或者您以某种方式错误地复制了它。不存在可以满足此实例化的类声明。

Registration<Person> r = new Registration<Student>();

这是因为通过将对象放在r中,您可以违反其约束。

例如:

Registration<Student> r0 = new Registration<Student>();
r0.addIndex(new Student());
Student s0 = r0.getLastInstance(); // returns a student instance 
r0. addIndex(new Person());  // error, person is not a subclass of student 

Registration<Person> r1 = r0; // error, but we will pretend it's allowed - you could force it with a cast 
r1.addIndex(new Person()); // this is cool, but what happens to the underlying object? 
Person p = r1.getLastInstance(); // this is fine, just like before 
Student s1 = r0.getLastInstance(); // error, returns a person instance!

这是因为r0r1是同一个对象,因此具有相同的最后一个实例 - 一个Person实例。但是r0的泛型类型承诺它的返回类型是Student。这就是为什么你不能以普通类型的方式分配泛型。这就是你使用通配符的原因。这意味着泛型类型只能用于返回该类型的东西,例如。 <? extends Person>,但不将它们作为参数传递。或者它意味着泛型类型只能传递该类型<? super Student>的东西,但不能返回它们。