这是我针对问题的上下文而编写的一组类

水族馆类:

package test;

import java.util.ArrayList;

public class Aquarium {

// the aquarium is composed of fish tanks

ArrayList<Object> aquarium;

public Aquarium(){

    aquarium = new ArrayList<Object>();

}

public <T> void addFishToTank(int index, T fish){

    FishTank<T> tank = (FishTank<T>) aquarium.get(index);
    tank.addFish(fish);

}


public ArrayList<Object> getAquarium(){

    return aquarium;

}

public String toString(){

    String holder = "";

    int i = 0;

    for (Object tank : aquarium){

        holder += "Tank " + i + ":\n";

        holder += tank.toString();

        i ++;

    }

    return holder;

}

public static void main(String[] args){


    Aquarium seaWorld = new Aquarium();

    seaWorld.getAquarium().add(new FishTank<Salmon>());

    seaWorld.addFishToTank(0, new Salmon());
    seaWorld.addFishToTank(0, new Grouper());

    System.out.println(seaWorld.toString());

}

}

FishTank类:
package test;

import java.util.ArrayList;

public class FishTank<T>{

// inside each fish tank there is a group of fish

ArrayList<T> fishGroup = new ArrayList<T>();

public void addFish(T element){

    fishGroup.add(element);

}

public String toString(){

    String holder = "";

    for (T fish: fishGroup){

        holder += fish.toString() + "\n";

    }

    return holder;
}


}

鲑鱼类:
package test;

public class Salmon {

public String toString(){

    return "This is a salmon";
}

}

石斑鱼类:
package test;

public class Grouper {

public String toString(){

    return "This is a grouper";
}

}

所有代码都能正常编译,Aquarium的输出最终被
Tank 0:
This is a salmon
This is a grouper

这怎么可能?当我将水箱添加到水族馆时
seaWorld.getAquarium().add(new FishTank<Salmon>());

指定它是只能容纳Salmon对象的FishTank。首先,我添加了Salmon对象
seaWorld.addFishToTank(0, new Salmon());

那样很好,因为位于水族馆索引0的鱼缸是一个装有鲑鱼物体的鱼缸。但是当我向索引为0的鲑鱼缸添加一个Grouper对象时
seaWorld.addFishToTank(0, new Grouper());

它仍然将石斑鱼添加到坦克中。在运行时是否应该引发异常?然后,如何执行强制措施,以便仅将鲑鱼对象添加到鲑鱼缸?

最佳答案

泛型仅用于编译时类型安全。如果您想要一个具有单独类型的水箱的水族馆,而这些水箱的底层鱼类类型在编译时不知道,那么您在Java中是不走运的。更糟糕的是,由于泛型类型在编译过程中都会被删除,因此剩下的就是Object了。

没有类强制转换异常的原因是,在运行时,它只是每个数组索引处的FishTank(原始类型),您可以在其中自由混合鱼类(或陆地动物或心理构造物)。

解决此类问题的一种方法是,通过包含Class< T >字段,使FishTank在运行时意识到其成员资格。然后,水箱可以在addFish()期间进行运行时检查,尽管所述检查的严格性是有限的(例如,如果您的鱼本身是通用容器,则仍然可以在同一水箱中混合容器; getClass()返回一个“擦除的”类对象)。

07-26 04:50