题目1:实现如下图所示的类及其结构,Pet是基类,Cat、Dog和Rodent直接继承Pet,余下的其他类分别继承自各自的超类。基类Pet为每个实例(包括子类的实例)自动生成一个不重复的编码,储存在私有域long id中。基类Pet重载toString()函数,返回类型名+编号。
实现PetCreator类,1)实现公共方法返回指向随机的Pet子类对象的引用,2)实现公共方法返回填充随机Pet子类对象的数组,3)实现公共方法返回填充随机Pet子类对象的List。
解答1:
1)创建Pet及其子类,为每个类单独编写一个.java文件。
//:pets\\Pet.java package pets; public class Pet{private static long counter;private long id = counter++; public String toString(){return getClass().getSimpleName()+"_"+id; }//:pets\\Cat.java package pets; public class Cat extends Pet{}//:pets\\EgyptianMau.java package pets; public class EgyptianMau extends Cat{}//:pets\\Manx.java package pets; public class Manx extends Cat{}//:pets\\Cymric.java package pets; public class Cymric extends Manx{}//:pets\\Dog.java package pets; public class Dog extends Pet{}//:pets\\Mutt.java package pets; public class Mutt extends Dog{}//:pets\\Pug.java package pets; public class Pug extends Dog{}//:pets\\Rodent.java package pets; public class Rodent extends Pet{}//:pets\\Rat.java package pets; public class Rat extends Rodent{}//:pets\\Mouse.java package pets; public class Mouse extends Rodent{}//:pets\\Hamster.java package pets; public class Hamster extends Rodent{}
2)实现PetCreator类,放在PetCreator.java文件中。
//:pets\\PetCreator.java package pets;import java.util.*;public class PetCreator{public Pet getRandomPet() throws Exception {return types.get(rand.nextInt(types.size())).newInstance();}public Pet[] getRandomPetArray(int size) throws Exception{Pet[] pets = new Pet[size];for(int i = 0; i < size; i++){pets[i] = getRandomPet();}return pets;}public List<Pet> getRandomPetList(int size) throws Exception{List<Pet> pets = new LinkedList<Pet>();for(int i = 0; i < size; i++){pets.add(getRandomPet());}return pets;}private Random rand = new Random(47);private static final String typeNames[] = {"pets.Pug", "pets.Mutt","pets.EgyptianMau", "pets.Manx", "pets.Cymric","pets.Rat", "pets.Mouse", "pets.Hamster"};private static List<Class<? extends Pet>> types = new ArrayList<Class<? extends Pet>>();static{loader();}@SuppressWarnings("unchecked")private static void loader(){for(String name : typeNames){try{types.add((Class<? extends Pet>) Class.forName(name));}catch(ClassNotFoundException e){e.printStackTrace();throw new RuntimeException();}}}public static void main(String[] args) throws Exception {PetCreator pc = new PetCreator();for(int i = 0; i < 5; i++){System.out.println(pc.getRandomPet());}System.out.println(Arrays.toString(pc.getRandomPetArray(5)));System.out.println(pc.getRandomPetList(5));} } /* output Rat_0 Manx_1 Cymric_2 Pug_3 Mutt_4 [Cymric_5, Mutt_6, Manx_7, Cymric_8, Rat_9] [EgyptianMau_10, Hamster_11, EgyptianMau_12, Pug_13, Pug_14] */
分析:
- 基类Pet的toString()方法中调用的getName()方法在编译时会动态绑定为子类相应的方法。
- 对Class对象应用泛型与通常的泛型规则不同。比如对List接口应用泛型,由List<Pet>引用指向的List对象可以存入任意Pet子类的引用,但Class<Pet>的引用却无法指向Pet子类的Class对象。这是因为虽然Pet子类继承自Pet,但Pet子类的Class对象并不是Pet类的Class对象的子类。因此对Class对象应用泛型需要用通配符(wildcard)。比如定义可以指向任意Pet子类的Class对象的引用的语句为Class<? extends Pet>。