我有大约10个类,每个类都有一个LUMP_INDEX和SIZE静态常量。 我想要一个这些类的数组,其中数组的大小是使用这两个常量计算的。 目前我为每个类创建了一个函数来创建数组,类似于:
private Plane[] readPlanes()
{
int count = header.lumps[Plane.LUMP_INDEX].filelen / Plane.SIZE;
Plane[] planes = new Plane[count];
for(int i = 0; i < count; i++)
planes[i] = new Plane();
return planes;
}
private Node[] readNodes()
{
int count = header.lumps[Node.LUMP_INDEX].filelen / Node.SIZE;
Node[] nodes = new Node[count];
for(int i = 0; i < count; i++)
nodes[i] = new Node();
return nodes;
}
private Leaf[] readLeaves()
{
int count = header.lumps[Leaf.LUMP_INDEX].filelen / Leaf.SIZE;
Leaf[] leaves = new Leaf[count];
for(int i = 0; i < count; i++)
leaves[i] = new Leaf();
return leaves;
}
等。 这些函数中有10个,唯一的区别是类类型,所以你可以看到,有很多重复。
有没有人对如何避免这种重复有任何想法? 谢谢。 (之前我问了一个类似的问题,但我想我的方式有点过时了)
答案 0 :(得分:3)
使用Java generics。这样,您可以只编写一个通用方法,并在每次使用时指定一个类型参数。
答案 1 :(得分:2)
Bala的解决方案很接近。但是你不能从泛型类型访问常量,所以我创建了一个getCount()(或者你想要命名的任何东西)并让每个子类型用适当的常量实现它。
interface LumpySize<L extends LumpySize> {
int getCount(); // subtypes return the appropriate header.lumps[Plane.LUMP_INDEX].filelen / Plane.SIZE;
T[] initializeArray();
abstract <T extends LumpySize> static class Base implements LumpySize<T> {
protected T[] initializeArray(Class<T> cls) {
int count = getCount();
T[] lumps = (T[]) Array.newInstance(cls, count);
for(int i = 0; i < count; i++) {
try {
lumps[i] = cls.newInstance();
} catch (Exception e) { // obviously this isn't good practice.
throw new RuntimeException(e);
}
}
return lumps;
}
}
}
class Plane extends LumpySize.Base<Plane> {
public int getCount() {
return header.lumps[Plane.LUMP_INDEX].filelen / Plane.SIZE; // assuming header is available somewhere
}
public Plane[] initializeArray() { return initializeArray(Plane.class); }
}
答案 2 :(得分:1)
Okey doke ...我已经对此进行了测试以确保,并且我相信它可以满足您的需求。
您需要一个界面:
public interface MyInterface
{
public int getSize();
public int getLumpIndex();
}
您的类实现了该接口:
public class Plane implements MyInterface
{
...
public int getSize()
{
return SIZE;
}
public int getLumpIndex()
{
return LUMP_INDEX;
}
}
在header
是其实例的类中,您有......
public <E extends MyInterface> E[]
getArray(Class<E> c, MyInterface foo)
{
int count = lumps[foo.getLumpIndex()].filelen / foo.getSize();
E[] myArray = (E[]) Array.newInstance(c, count);
for(int i = 0; i < count; i++)
myArray[i] = c.newInstance();
return myArray;
}
你可以把它称为你的飞机课:
Plane[] p = header.getArray(Plane.class, this);
我想? :)有人可以看看这个,看看我是否已经离开?
(编辑: Becasue我现在已经测试过 - 这有效)
另外请注意,您可以通过使getArray()
将大小和索引作为参数来消除每个类中的getter:
public <E extends MyInterface> E[]
getArray(Class<E> c, int size, int index)
{
int count = lumps[index].filelen / size;
E[] myArray = (E[]) Array.newInstance(c, count);
for(int i = 0; i < count; i++)
myArray[i] = c.newInstance();
return myArray;
}
并将其命名为:
Plane p[] = header.getArray(Plane.class, SIZE, LUMP_INDEX);
来自课堂内部。接口只是变空,以提供泛型类型,您不必定义getter方法。
或(最后编辑我保证,但这确实可以为您提供选择并解释一些关于泛型的信息)
抛弃界面。这个删除的是一些健全性检查,因为该方法不关心你给它的对象类型:
public <E> E[]
getArray(Class<E> c, int size, int index)
{
...
现在您不必定义界面或实现它,只需调用:
Plane p[] = header.getArray(Plane.class, SIZE, LUMP_INDEX);
答案 3 :(得分:0)
使用泛型,但是您需要传递某种工厂对象来构造要放入集合的实例,例如:
public class MyClass {
public <E> E[] getArray(IObjectFactory builder, int index, int size){
ArrayList<E> arrayList = new ArrayList<E>();
int count = header.lumps[index].filelen / size;//wasn'tsure where header was coming from...
for(int i = 0; i< count; i++){
E newInstance = builder.getNewInstance();
arrayList.add(newInstance);
}
return (E[]) arrayList.toArray();
}
}
interface IObjectFactory {
<E> E getNewInstance();
}