我在下面有一个简单的代码:
import java.util.ArrayList;
public class BoidList extends ArrayList
{
synchronized public Boid GetBoid( int idx_ ) throws ArrayIndexOutOfBoundsException
{
if( idx_ < super.size() &&
idx_ >= 0 )
{
return (Boid) super.get(idx_);
}
else
{
throw new ArrayIndexOutOfBoundsException();
}
}
synchronized public void RemoveBoid( int idx_ ) throws ArrayIndexOutOfBoundsException
{
if( idx_ < super.size() &&
idx_ >= 0 )
{
super.remove(idx_);
}
else
{
throw new ArrayIndexOutOfBoundsException();
}
}
}
两种方法之间有很多相似之处,但它们做了两件不同的事情。有可能重构这个吗?
答案 0 :(得分:20)
BoidList
的真正目的是什么?请考虑以下事项:
List<Boid> boids = Collections.synchronizedList(new ArrayList<Boid>());
这行代码或多或少等同于您尝试创建的子类:
ArrayList
已经抛出IndexOutOfBoundsException
Collections.synchronizedList()
确保对列表的同步访问根据您提供的源代码,我认为没有任何理由创建您自己的子类。
答案 1 :(得分:12)
public class BoidList extends ArrayList<Boid> {
private void checkIndex(int idx) {
if (idx >= super.size() || idx < 0) {
throw new ArrayIndexOutOfBoundsException(String.valueOf(idx));
}
}
synchronized public Boid getBoid(int idx) {
checkIndex(idx);
return super.get(idx);
}
synchronized public void removeBoid(int idx) {
checkIndex(idx);
super.remove(idx);
}
}
这可以通过多种方式修复您的代码:
修改强>
您可能还想查看CopyOnWriteArrayList&lt; Boid&gt;
答案 2 :(得分:4)
仅为了您的信息,ArrayList
类具有执行边界检查的get
和remove
方法,如果指定的索引超出范围,则抛出IndexOutofBoundsException
列表。
除非目标平台在Java 5下,否则使用generics可能是更优选的方法。使用泛型,可以确保ArrayList
的内容都是相同的类型,这将消除执行类型转换,类型检查和面对可能ClassCastException
的需要。
例如:
List<String> list = new ArrayList<String>();
list.add("Hello");
list.add("World");
String s = list.remove(0); // No need for typecasting.
list.add(10); // Compile error, as 10 is not of type String.
答案 3 :(得分:3)
您可以将检查有效性的代码提取到单独的方法中:
private void checkIndex(int i) throws ArrayIndexOutOfBoundsException
{
if (idx < 0 || idx_ >= super.size()) {
throw new ArrayIndexOutOfBoundsException();
}
}
synchronized public void RemoveBoid( int idx_ ) throws ArrayIndexOutOfBoundsException
{
checkIndex(idx_);
super.remove(idx_);
}
此外,您还需要扩展java.util.ArrayList [Boid]。
但扩展java.util.ArrayList似乎是一个坏主意。你为什么要这样做?
答案 4 :(得分:1)
我认为它们是完全不同的,一个通过指定索引获取一个对象,另一个删除它,无论代码是否相似,方法执行的任务都是完全相反的。
答案 5 :(得分:1)
你为什么要打扰?
较少的代码不是目标(除了perl one liner竞赛:-))。
编码风格应该有三个目标: - 清晰度,正确性和运行时效率。
原始代码足够清晰,大概是正确的,并且可以像使用java集合的任何东西一样有效地运行。
任何重构尝试都会使类本身不那么清晰,并且使得使用该类的任何代码都不太清楚。任何更改都可能会引发错误,因此它不太正确,并且不太可能更有效地使用数组类。
答案 6 :(得分:0)
您可以编写如下函数:
private boolean checkIndex( int _idx ) throws ArrayIndexOutOfBoundsException {
if ( idx_ < super.size() && idx_ >= 0 ) {
return true;
} else {
throw ArrayIndexOutOfBoundsException();
}
}
然后使用此方法进行检查。但是,这可能只比您已使用的代码提供了一个小优势。
你绝对不应该做的是尝试在你已经拥有的2个方法中制作1个方法。这基本上违反了我所知道的每个OO原则; - )
答案 7 :(得分:0)
您可以将其重构为getOrRemoveBoid方法,其中参数可以处理决策。但这看起来像代码味道。这些方法具有不同的语义,应该分开。
该类的大部分内容是关于异常处理和语言语法。你不应该混合方法,它们足够干燥。
答案 8 :(得分:-1)
不要为了它而重构!
唯一可能的部分:
idx_ < super.size() && idx_ >= 0
可能是浪费时间(如果多次执行此操作,进入新的“isValidIndex(int)”方法可能会对未经修改的代码造成性能损失。)