Posted on 2008-10-25 00:32
非鱼 阅读(2268)
评论(2) 编辑 收藏 所属分类:
Java技术
这个系列,结合IDEA的Inspection和我自己的理解编写。
抽象问题
1. 把实例造型(cast)成具体的类型
这个问题的含义是,当得到一个实例时,把它cast到一个更加具体的类型使用。这个问题存在于以下场景:
- 出于个人原因,比如只熟悉这个具体的类型、不动脑筋的编码。
这是新手常见的问题。比如可能程序员只熟悉ArrayList,并不知道其上的更加抽象的接口;或者个人感觉ArrayList更加“好用”。这是不应该出现的问题,有经验的程序员应该指导初学者,避免犯错。
- 需要的方法不在更抽象的类型中,只在具体类型中才有定义。
这个问题更多的表示了设计层面考虑的不充分。比如组织本身的代码(非外来代码),接口定义的类型不能满足接口实现者的具体需求;返回值的类型过于泛化;本地变量(Local variable)定义的类型过于泛化等等。这些问题一般意味着在设计上考虑不周,导致了对象交互过程中的“对接不顺利”,这是设计上的不一致,需要对设计进行仔细评估。以下是几个这样的例子:
public Collection aMethod(Collection c) {
List list = (List)c;
Object o = list.get(0); // Collection中没有get方法。导致实现者必须cast。
...
}
public void test() {
// 返回值必须cast才能使用更加具体的方法。
List alist = (List)aMethod(Arrays.asList(new String[]{"1", "2"}));
Object obj = alist.get(0);
...
}
public someMethod() {
MyInterface mi = new MyImplementation();
...
// 大部分时间调用MyInterface中的方法,但忽然发现有某个地方需要调用特定的非接口实现:
int count = ((MyImplementation)mi).specialMethod();
...
}
最后这个例子,可能是方法的实现本身的问题,比如完全可以直接使用MyImplementation来定义变量mi;也可能是抽象问题,即没有把本来具有普遍性的方法放到接口中,而是放到了具体实现中。
上面谈到的设计问题,是指的组织内部的设计。在很多时候,需要使用外部的接口和实现,这些接口因为考虑了更加广泛的使用环境而采用了更加泛化的接口。这就需要顺应已经存在的设计来实现,不得不使用cast。但同时也要注意,在不得不cast的时候,一定要安全的使用cast,比如安全检查或者安全的类型转换,下面是示例:
public boolean equals(Object o) {
if (o == null) return false;
if (o instanceof MyClass) { // 安全检查!
MyClass mc = (MyClass)o;
// 调用MyClass中的特定方法。
...
}
public method() {
Collection c = aMethodReturnsCollection();
List list = new ArrayList(c); //安全的类型转换,把Collection转换成List。
...
}
Coding, issue, abstract, cast