14章类型信息之使用类字面常量

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}

时间: 2024-10-10 13:56:21

14章类型信息之使用类字面常量的相关文章

14章.类型信息(1)

运行时类型信息使得你可以在程序运行时发现和使用类型信息. java在运行时识别对象和类的信息有两种方式:(1)“传统的”RTTI,它假定我们在编译时已经知道了所有的类型:(2)“反射”机制,它允许我们在运行时发现和使用类的信息. 一.为什么需要RTTI(Run-Time-Type-Information) 面向对象编程的基本目的是:让代码只操纵基类的引用,这样如果要在基类下面添加新类时,不会影响原来的代码. 例如: 图中的动物是基类,位于顶部,派生类向下扩展. 先看一下,如果我们不操纵基类,会有

Java编程思想——第14章 类型信息(二)反射

六.反射:运行时的类信息 我们已经知道了,在编译时,编译器必须知道所有要通过RTTI来处理的类.而反射提供了一种机制——用来检查可用的方法,并返回方法名.区别就在于RTTI是处理已知类的,而反射用于处理未知类.Class类与java.lang.reflect类库一起对反射概念进行支持,该类库包含Field.Method以及Constructor(每个类都实现了Member接口).这些类型是由JVM运行时创建的,用来表示未知类种对应的成员.使用Constructor(构造函数)创建新的对象,用ge

14章类型信息-之类型转换前先做检查--之instanceof

instanceof用法: 对于instanceof有比较严格的限制,只可将其与命名类型进行比较,而不能与class对象做比较. 理解:这里所说的就是像if(pet instanceof Mutt)        counter.count("Mutt");这里的Mutt,不能用对象比较,只能用类名,比如(Mutt mutt = new Mutt()然后用mutt)或者 Mutt.class就不行了, 实例代码: 实体类父类: //: typeinfo/pets/Individual.

14章类型信息

1.初始化被延迟到了对静态方法(构造器隐式地是静态的)或者非常数静态域进行首次引用时才执行 01.static final int staticFinal = 47;这样直接引用class就可以不用初始化,因为这个是编译期常量,这个值不需要对Initable类进行初始化就可以被读取. 02. static final int staticFinal2 =ClassInitialization.rand.nextInt(1000); 这个是不确定的,所以要初始化后,才能引用(对于像这里的stati

Java编程思想读书笔记--第14章类型信息

7.动态代理 代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象.这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色. 什么是代理模式? 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 代理模式有什么好处? 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式一般涉及到的角色有: 抽象角色:声明真实对象和代理对象的共同接口,这样一来在任何可以使用目标对象

《JAVA编程思想》学习笔记——第十四章 类型信息

运行时类型信息使得你可以在程序运行时发现和使用类型信息. 主要有两种方式:一种是"传统的"RTTI, 它假定我们在编译时已经知道了所有的类型;另一种是"反射"机制,它允许我们在运行时发现和使用类的信息. Class对象 类是程序的一部分,每个类都有一个Class对象.换言之,每当编写并且编译一个新类,就会产生一个Class对象(更恰当的说,是被保存在一个同名的.class文件中).为了生成这个类的对象,运行这个程序的Java虚拟机(JVM)将使用被称为"类

快学Scala第14章----模式匹配和样例类

本章要点 match表达式是一个更好的switch,不会有意外掉入到下一个分支的问题. 如果没有模式能够匹配,会抛出MatchError.可以用case _ 模式来避免. 模式可以包含一个随意定义的条件,称作守卫. 你可以对表达式的类型进行匹配:优先选择模式匹配而不是isInstanceOf/asInstanceOf. 你可以匹配数组.元组和样例类的模式,然后将匹配到的不同部分绑定到变量. 在for表达式中,不能匹配的情况会被安静的跳过. 样例类继承层级中的公共超类应该是sealed的. 用Op

第十四章 类型信息

前言 在开始介绍类型信息之前一定要区分一些概念: 1.静态类型语言与动态类型语言 静态类型语言:在编译期进行类型检查的语言(例如,Java).(例如 int i = 3;) 动态类型语言:在运行期进行类型检查的语言(例如,JavaScript).最明显的特征为变量没有类型值有类型(如,var=3;) 2.类型检查与类型转换(在Java中的区别) 类型检查:发生在编译期,检查方法是不是接收到了合适类型的参数,赋值是不是有合适类型的右值. 类型转换正确性检查:发生在运行期,检查一个类型变换到另外一个

第十四章 类型信息1(java的反射)

1.java语言的反射 1 package cn.itcast_01; 2 /* 1.通过反射获取构造方法并使用 3 * // 获取字节码文件对象 4 Class c = Class.forName("cn.itcast_01.Person"); 5 //获取指定的构造器对象(仅仅是获取到了) 6 该方法的形式参数就是构造方法的形式参数的.class对象(Class<?>... parameterTypes) 7 * parameterTypes 参数是 Class 对象的