2011-03-26 65 views
5

我有大约10多个类,每个类都有一个LUMP_INDEX和SIZE静态常量。 我想要这些类中的每一个的数组,其中使用这两个常量来计算数组的大小。 目前我有一个函数为每个类创建阵列,沿着线的东西:重复此java代码复制

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

你在void方法中有return语句吗? – 2011-03-26 19:21:24

+0

这些方法中的'header'对象是什么? – 2011-03-26 19:36:05

+0

为什么不使用ArrayList? – bancer 2011-03-26 21:25:08

回答

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()采取的规模和指标作为参数消除每一类干将:

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方法。

OR(最后编辑我答应了,但是这确实给你的选择,并解释了一些关于仿制药)

沟的接口。这是什么去除一些健全检查,因为该方法不关心你给什么类型的对象是:

public <E> E[] 
    getArray(Class<E> c, int size, int index) 
{ 
    ... 

现在,你不必定义接口或者实现它,你只要致电:

Plane p[] = header.getArray(Plane.class, SIZE, LUMP_INDEX); 
+0

谢谢,我认为这可能是最好的方法(除了getArray函数不需要在页眉内)。然而,当我尝试它,c.newInstance()抛出一个InstantiationException,我不知道为什么,所以我很难过。 – terryhau 2011-03-27 04:20:35

+0

你从来没有发布你的构造函数是你的对象。你有没有参数的构造函数? – 2011-03-27 04:22:56

+0

是的,他们没有任何争论。我想出了为什么抛出异常。谢谢 – terryhau 2011-03-27 05:18:00

3

使用Java generics。这样,您可以只编写一个泛型方法,并在每次使用时指定一个类型参数。

+0

你的意思是像私人无效阅读(类 clazz)?我无法通过clazz参数访问2个常量。 – terryhau 2011-03-26 19:10:18

+2

请注意,您不能使用泛型来执行'new T [x]'。你可以绕过它,但答案并不那么简单。 – 2011-03-26 19:13:42

+0

@布莱恩罗奇:提示什么使用呢?通用容器? – xtofl 2011-03-26 19:15:32

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(); 
} 
2

巴拉的解决方案是密切。尽管你不能访问泛型类型的常量,所以我会创建一个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); } 
} 
+0

您误解了代码。它是一个抽象基类,可以扩展,例如'class Plane extends LumpySize.Base '。 – 2011-03-26 19:53:55

+0

Doh,对不起 - 我误解了它。删除我的评论。 – 2011-03-26 19:55:17

+0

+1。是的。这是将实现相关常量变为泛型代码的方式。非常有用的知道。 – extraneon 2011-03-26 20:35:37