item 33: 考虑类型安全的异构容器
- 一个容器,如
Map<String, Object>
可以通常此方法进行类型检查,保证类型安全,但有些时候,我们可能需要特定类型的数据。那应该如何让编译器为我们进行类型检查呢? - 方法很简单,就是参数化key.将上面的map改为
Map<Class<?>, Object>
public class TestHeterogeneousContainer_33 {
public static void main(String[] args) {
Favorites favorites = new Favorites();
favorites.putFavorite(String.class,"123");
favorites.putFavorite(Integer.class,12);
favorites.putFavorite(Class.class,TestHeterogeneousContainer_33.class);
System.out.println(favorites.getFavorite(String.class));
System.out.println(favorites.getFavorite(Integer.class));
System.out.println(favorites.getFavorite(Class.class));
}
}
class Favorites {
private Map<Class<?>, Object> favors = new HashMap<>();
public <T> T getFavorite(Class<T> type) {
return type.cast(favors.get(type));
}
public <T> void putFavorite(Class<T> type, T e) {
favors.put(Objects.requireNonNull(type),e);
}
}
item 34: 使用枚举取代整型常量
- 枚举是一个特殊的类,枚举值是这个特殊类的一个对象
- 若是一个集合的所有常量事先已经知道,就应该使用泛型,而不是整型常量。
- 如太阳系已知八大行星,应当定义一个Planet枚举,其值就是八大行星(Earth等)。而不应该new Planet(int) 使用int数值代表行星。
public class TestEnum_34 {
public static void main(String[] args) {
double weight = 185.0;
double mass = weight / Planet.EARTH.getSurfaceGravity();
for (Planet p : Planet.values()) {
System.out.printf("mass = %f on %s is %f\n", mass,p.toString(),p.getWeight(mass));
}
double x = 1;
double y = 2;
for (Operation op : Operation.values())
System.out.printf("%f %s %f = %f%n",
x, op, y, op.apply(x, y));
}
}
enum Planet {
EARTH(5.975e+24, 6.378e6),
MARS (6.419e+23, 3.393e6);
private final double mass;
private final double radius;
private final double surfaceGravity;
private static final double G = 6.67300E-11;
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
this.surfaceGravity = G*mass/(radius*radius);
}
public double getSurfaceGravity() {return surfaceGravity;}
public double getWeight(double m) {return surfaceGravity * m;}
}
enum Operation {
PLUS("+") {
@Override
public double apply(double x, double y) {
return x+y;
}
},
MINUS("-") {
@Override
public double apply(double x, double y) {
return x-y;
}
},
MULTIPLY("*") {
@Override
public double apply(double x, double y) {
return x*y;
}
},
DIVIDE("/") {
@Override
public double apply(double x, double y) {
return x/y;
}
};
public abstract double apply(double x, double y);
private String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}