`

14章类型信息-之类型转换前先做检查--之使用类字面常量--类名.class--以及动态instanceof(isInstance方法)----递归计数(计算各个类的个数)

 
阅读更多

实例代码:

实体类父类:

//: typeinfo/pets/Individual.java
package typeinfo.pets;


public class Individual implements Comparable<Individual> {
private static long counter = 0;
private final long id = counter++;
private String name;
public Individual(String name) { this.name = name; }
// 'name' is optional:
public Individual() {}
public String toString() {
return getClass().getSimpleName() +
(name == null ? "" : " " + name);
}
public long id() { return id; }
public boolean equals(Object o) {
return o instanceof Individual &&
id == ((Individual)o).id;
}
public int hashCode() {
int result = 17;
if(name != null)
result = 37 * result + name.hashCode();
result = 37 * result + (int)id;
return result;
}
public int compareTo(Individual arg) {
// Compare by class name first:
String first = getClass().getSimpleName();
String argFirst = arg.getClass().getSimpleName();
int firstCompare = first.compareTo(argFirst);
if(firstCompare != 0)
return firstCompare;
if(name != null && arg.name != null) {
int secondCompare = name.compareTo(arg.name);
if(secondCompare != 0)
return secondCompare;
}
return (arg.id < id ? -1 : (arg.id == id ? 0 : 1));
}
} ///:~

继承类:

//: typeinfo/pets/Cat.java
package typeinfo.pets;


public class Cat extends Pet {
public Cat(String name) { super(name); }
public Cat() { super(); }
} ///:~

 

//: typeinfo/pets/Dog.java
package typeinfo.pets;


public class Dog extends Pet {
public Dog(String name) { super(name); }
public Dog() { super(); }
} ///:~

 

//: typeinfo/pets/Rodent.java
package typeinfo.pets;


public class Rodent extends Pet {
public Rodent(String name) { super(name); }
public Rodent() { super(); }
} ///:~

创建宠物的抽象类:

//: typeinfo/pets/PetCreator.java
// Creates random sequences of Pets.
package typeinfo.pets;
import java.util.*;


public abstract class PetCreator {
private Random rand = new Random(47);
// The List of the different types of Pet to create:
public abstract List<Class<? extends Pet>> types();
public Pet randomPet() { // Create one random Pet
int n = rand.nextInt(types().size());
try {
return types().get(n).newInstance();
} catch(InstantiationException e) {
throw new RuntimeException(e);
} catch(IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public Pet[] createArray(int size) {
Pet[] result = new Pet[size];
for(int i = 0; i < size; i++)
result[i] = randomPet();
return result;
}
public ArrayList<Pet> arrayList(int size) {
ArrayList<Pet> result = new ArrayList<Pet>();
Collections.addAll(result, createArray(size));
return result;
}
} ///:~

实现(创建宠物抽象类)的实现类:

//: typeinfo/pets/LiteralPetCreator.java
// Using class literals.
package typeinfo.pets;
import java.util.*;


public class LiteralPetCreator extends PetCreator {
// No try block needed.
@SuppressWarnings("unchecked")
public static final List<Class<? extends Pet>> types =
Collections.unmodifiableList(Arrays.asList(
Dog.class, Cat.class, Rodent.class));
//这里的Collections.unmodifiableList是指

//返回指定列表的不可修改视图。此方法允许模块为用户提供对内部列表的“只读”访问
public List<Class<? extends Pet>> types() {
return types;
}
}

为了将LiteralPetCreator作为默认实现,创建一个使用了LiteralPetCreator的外观类:

//: typeinfo/pets/Pets.java
// Facade to produce a default PetCreator.
package typeinfo.pets;
import java.util.*;


public class Pets {
public static final PetCreator creator =
new LiteralPetCreator();
public static Pet randomPet() {
return creator.randomPet();
}
public static Pet[] createArray(int size) {
return creator.createArray(size);
}
public static ArrayList<Pet> arrayList(int size) {
return creator.arrayList(size);
}
} ///:~

用于计算各个宠物个数的类:

package typeinfo.pets;


//: typeinfo/PetCount.java
// Using instanceof.
import typeinfo.pets.*;
import java.util.*;
import static net.mindview.util.Print.*;


public class PetCount {
static class PetCounter extends HashMap<String,Integer> {
public void count(String type) {
Integer quantity = get(type);
if(quantity == null)
put(type, 1);
else
put(type, quantity + 1);
}
}
public static void countPets(PetCreator creator) {
PetCounter counter= new PetCounter();
for(Pet pet : creator.createArray(20)) {
// List each individual pet:
printnb(pet.getClass().getSimpleName() + " ");
if(pet instanceof Pet)
counter.count("Pet");
if(pet instanceof Dog)
counter.count("Dog");
if(pet instanceof Cat)
counter.count("Cat");
if(pet instanceof Rodent)
counter.count("Rodent");
}
// Show the counts:
print();
print(counter);
}
}

测试类:

package typeinfo.pets;


//: typeinfo/PetCount2.java
import typeinfo.pets.*;


public class PetCount2 {
public static void main(String[] args) {
PetCount.countPets(Pets.creator);
}
} /* (Execute to see output) *///:~

//测试打印:Rodent Rodent Dog Rodent Dog Rodent Dog Rodent Cat Dog Cat Cat Cat Dog Rodent Dog Dog Dog Rodent Dog
//{Cat=4, Pet=20, Dog=9, Rodent=7}

工具类:

//: net/mindview/util/Print.java
// Print methods that can be used without
// qualifiers, using Java SE5 static imports:
package net.mindview.util;
import java.io.*;


public class Print {
// Print with a newline:
public static void print(Object obj) {
System.out.println(obj);
}
// Print a newline by itself:
public static void print() {
System.out.println();
}
// Print with no line break:
public static void printnb(Object obj) {
System.out.print(obj);
}
// The new Java SE5 printf() (from C):
public static PrintStream
printf(String format, Object... args) {
return System.out.printf(format, args);
}
} ///:~

---------------------动态的instanceof------------------isInstance方法,

-----用到上面的LiteralPetCreator、Pets类-------------------------------

动态计算各个宠物个数的类:

package typeinfo.pets;


//: typeinfo/PetCount3.java
// Using isInstance()
import typeinfo.pets.*;
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;


public class PetCount3 {
static class PetCounter
extends LinkedHashMap<Class<? extends Pet>,Integer> {
public PetCounter() {
super(MapData.map(LiteralPetCreator.types, 0));
}
public void count(Pet pet) {
// Class.isInstance() eliminates instanceofs:
for(Map.Entry<Class<? extends Pet>,Integer> pair
: entrySet())
if(pair.getKey().isInstance(pet))
put(pair.getKey(), pair.getValue() + 1);
}
public String toString() {
StringBuilder result = new StringBuilder("{");
for(Map.Entry<Class<? extends Pet>,Integer> pair
: entrySet()) {
result.append(pair.getKey().getSimpleName());
result.append("=");
result.append(pair.getValue());
result.append(", ");
}
result.delete(result.length()-2, result.length());
result.append("}");
return result.toString();
}
}

//这个是测试结果的main方法

public static void main(String[] args) {
PetCounter petCount = new PetCounter();
for(Pet pet : Pets.createArray(20)) {
printnb(pet.getClass().getSimpleName() + " ");
petCount.count(pet);
}
print();
print(petCount);
}
}

 

//打印结果:Rodent Rodent Cat Rodent Cat Rodent Cat Rodent Dog Cat Dog Dog Dog Cat Rodent Cat Cat Cat Rodent Cat{Dog=4, Cat=9, Rodent=7}

工具类:

1、

//: net/mindview/util/MapData.java
// A Map filled with data using a generator object.
package net.mindview.util;
import java.util.*;


public class MapData<K,V> extends LinkedHashMap<K,V> {
// A single Pair Generator:
public MapData(Generator<Pair<K,V>> gen, int quantity) {
for(int i = 0; i < quantity; i++) {
Pair<K,V> p = gen.next();
put(p.key, p.value);
}
}
// Two separate Generators:
public MapData(Generator<K> genK, Generator<V> genV,
int quantity) {
for(int i = 0; i < quantity; i++) {
put(genK.next(), genV.next());
}
}
// A key Generator and a single value:
public MapData(Generator<K> genK, V value, int quantity){
for(int i = 0; i < quantity; i++) {
put(genK.next(), value);
}
}
// An Iterable and a value Generator:
public MapData(Iterable<K> genK, Generator<V> genV) {
for(K key : genK) {
put(key, genV.next());
}
}
// An Iterable and a single value:
public MapData(Iterable<K> genK, V value) {
for(K key : genK) {
put(key, value);
}
}
// Generic convenience methods:
public static <K,V> MapData<K,V>
map(Generator<Pair<K,V>> gen, int quantity) {
return new MapData<K,V>(gen, quantity);
}
public static <K,V> MapData<K,V>
map(Generator<K> genK, Generator<V> genV, int quantity) {
return new MapData<K,V>(genK, genV, quantity);
}
public static <K,V> MapData<K,V>
map(Generator<K> genK, V value, int quantity) {
return new MapData<K,V>(genK, value, quantity);
}
public static <K,V> MapData<K,V>
map(Iterable<K> genK, Generator<V> genV) {
return new MapData<K,V>(genK, genV);
}
public static <K,V> MapData<K,V>
map(Iterable<K> genK, V value) {
return new MapData<K,V>(genK, value);
}
} ///:~

2、

//: net/mindview/util/Generator.java
// A generic interface.
package net.mindview.util;
public interface Generator<T> { T next(); } ///:~

3、

//: net/mindview/util/Pair.java
package net.mindview.util;


public class Pair<K,V> {
public final K key;
public final V value;
public Pair(K k, V v) {
key = k;
value = v;
}
} ///:~

--------------------------------递归计数-----------------------

------------------------不局限于pet的工具类-------------------------

工具类:

//: net/mindview/util/TypeCounter.java
// Counts instances of a type family.
package net.mindview.util;
import java.util.*;


public class TypeCounter extends HashMap<Class<?>,Integer>{
private Class<?> baseType;
public TypeCounter(Class<?> baseType) {
this.baseType = baseType;
}
public void count(Object obj) {
Class<?> type = obj.getClass();
if(!baseType.isAssignableFrom(type))
throw new RuntimeException(obj + " incorrect type: "
+ type + ", should be type or subtype of "
+ baseType);
countClass(type);
}
private void countClass(Class<?> type) {
Integer quantity = get(type);
put(type, quantity == null ? 1 : quantity + 1);
Class<?> superClass = type.getSuperclass();
if(superClass != null &&
baseType.isAssignableFrom(superClass))//判定此 Class 对象所表示的类或接口与指定的 Class 参数

//所表示的类或接口是否相同,或是否是其超类或超接口。如果是则返回 true;否则返回 false
countClass(superClass);
}
public String toString() {
StringBuilder result = new StringBuilder("{");
for(Map.Entry<Class<?>,Integer> pair : entrySet()) {
result.append(pair.getKey().getSimpleName());
result.append("=");
result.append(pair.getValue());
result.append(", ");
}
result.delete(result.length()-2, result.length());
result.append("}");
return result.toString();
}
} ///:~

测试类:

package typeinfo.pets;


//: typeinfo/PetCount4.java
import typeinfo.pets.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;


public class PetCount4 {
public static void main(String[] args) {
TypeCounter counter = new TypeCounter(Pet.class);
for(Pet pet : Pets.createArray(20)) {
printnb(pet.getClass().getSimpleName() + " ");
counter.count(pet);
}
print();
print(counter);
}
}

打印结果:

//Rodent Rodent Cat Rodent Cat Rodent Cat Rodent Dog Cat Dog Dog Dog Cat Rodent Cat Cat Cat Rodent Cat
{Pet=20, Cat=9, Dog=4, Rodent=7}

分享到:
评论

相关推荐

    javax.servlet-api-3.0.1.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-4.0.0-b01.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    nimbus-jose-jwt-3.9.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    poi-ooxml-4.1.2.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-4.0.0-b04.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-4.0.1.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-4.0.0-b06.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-3.1-b01.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-3.1-b05.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    netty-resolver-4.1.53.Final.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    junit-jupiter-engine-5.8.1.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-3.1.0.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    Windows消息大全,MFC编程--控件类名归类.pdf

    Windows消息大全,MFC编程--控件类名归类.pdf

    mockito-core-2.0.71-beta.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.jdo-3.2.0-m3.jar中文-英文对照文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    poi-ooxml-5.2.2.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-4.0.0-b03.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-3.1-b07.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-3.1-b08.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

    javax.servlet-api-3.1-b05.jar中文文档.zip

    ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件...

Global site tag (gtag.js) - Google Analytics