删除重复的java代码

发布于 2024-10-26 13:25:23 字数 918 浏览 5 评论 0原文

我有大约 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 个,唯一的区别是类类型,因此如您所见,存在大量重复。

有人对如何避免这种重复有任何想法吗? 谢谢。 (我以前问过类似的问题,但我想我问的方式有点不对劲)

I have about 10+ classes, and each one has a LUMP_INDEX and SIZE static constant.
I want an array of each of these classes, where the size of the array is calculated using those two constants.
At the moment i have a function for each class to create the array, something along the lines of:

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;
}

etc.
There are 10 of these functions, and the only differences is the class type, so as you can see, there's a ton of duplication.

Does any one have any ideas on how to avoid this duplication?
Thanks.
(I asked a similar question before, but i guess the way i asked it was a bit off)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤独岁月 2024-11-02 13:25:23

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

Use Java generics. That way, you can just write one generic method and specify a type parameter each time you use it.

ι不睡觉的鱼゛ 2024-11-02 13:25:23

巴拉的解决方案很接近。不过,您无法从泛型类型访问常量,因此我将创建一个 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); }
}

Bala's solution is close. You can't access constants from the generic type though, so I'd create a getCount() (or whatever you want to name it) and have each subtype implement it with the appropriate constants.

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); }
}
筱果果 2024-11-02 13:25:23

好吧,多克......我已经对此进行了测试以确保,并且我相信它可以满足您的要求。

您需要一个接口:

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 类中调用它:

Plane[] p = header.getArray(Plane.class, this);

我认为? :) 有人可以看看这个并看看我是否离开了吗?

编辑:因为我现在已经测试过它 - 有效)

另外一点,您可以通过使 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);

Okey doke ... I've tested this to make sure, and I believe it does what you're looking for.

You need an interface:

public interface MyInterface
{
    public int getSize();
    public int getLumpIndex();
}

Your classes implement that interface:

public class Plane implements MyInterface
{

    ...
    public int getSize()
    {
        return SIZE;
    }

    public int getLumpIndex()
    {
        return LUMP_INDEX;
    }

}

In the class that header is an instance of, you have ...

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;
}

You could call it from say, your Plane class as:

Plane[] p = header.getArray(Plane.class, this);

I think? :) Can someone look at this and see if I'm off?

(EDIT: Becasue I've tested it now - That works)

On an additional note, you could eliminate the getters in each class by making getArray() take the size and index as arguments:

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;
}

And call it as:

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

from inside your classes. The interface just becomes empty to provide the generic type and you don't have to define the getter methods.

OR (last edit I promise, but this does give you choices and explains a bit about generics)

Ditch the interface. What this removes is some sanity checking because the method doesn't care what type of object you give it:

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

Now you don't have to define the interface or implement it, you just call:

Plane p[] = header.getArray(Plane.class, SIZE, LUMP_INDEX);
够钟 2024-11-02 13:25:23

使用泛型,但您需要传递某种工厂对象来构造要放入集合中的实例,例如:

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

Use generics, but you'll need to pass in some sort of factory object to construct instances to put in your collection, eg:

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文