2

目标:我需要创建一个或多个函数来处理不同类型的List参数,并且我将遍历函数中的列表。

尝试:

1-具有不同类型列表的多个功能

public static int update(List<MyClass> myClasses){};
public static int update(List<Project> rojects){};
public static int update(List<Time> times){};

但这被认为是不可编译的,因为具有相同参数类型的多个函数List

2- 列表的通用类型,并使用 ( instanceof) 但是,我没有完全做到这一点,因为我不确定如何做到这一点,而且就我所读的而言,这似乎是这种行动的不利方式。

我的问题:实现这种要求的 Java 方式是什么?我需要一个干净的代码,我不在乎它是否复杂,我主要关心的是准确性和正确的编码。

PS:如果instanceof方法正确,那么请您提供一个关于如何用不同类型迭代列表的小例子。

提前致谢 :)

编辑:不同的对象彼此没有关系,例如,它们不相互扩展,也不扩展超类。每个函数的块都生成一个 SQLite 语句,每种类型的语句都不同。


回应“苛刻”的回答:

所以我最终结合了你的建议,那就是实现一个基类,它的函数getClassType()返回一个类名的字符串,然后我会检查update(List<T> list)函数中的返回值。

public static <T extends Item> int update(List<T> list){
    ...
    // Loop through the list and call the update function
    for (T item: list){
        if (item.getClassType() == MyClass.CLASS_TYPE)
            update((MyClass) item);

    }
    ...
}

public interface Item {
    /**
     * @return Return the class type, which is the name of the class
     */
    public String getClassType();
}

public class ClassProject implements Item{
    public static final String CLASS_TYPE = "ClassProject";
    @Override
    public String getClassType() {
        return CLASS_TYPE;
    }
    ...
}

public class ClassTime implements Item{
    public static final String CLASS_TYPE = "ClassTime";
    @Override
    public String getClassType() {
        return CLASS_TYPE;
    }
    ...
}

public class MyClass implements Item{
    public static final String CLASS_TYPE = "MyClass";
    @Override
    public String getClassType() {
        return CLASS_TYPE;
    }
    ...
}

这样做的原因interface是因为我不喜欢istanceof并且不确定它的性能和成本,所以我试图自己做一个。现在这是一种可怕的做法吗?

4

3 回答 3

4

你能做这样的事情:

public class Update<T>
{

public static int update(List<T> objects){};

}

或者

public static <T> int update(List<T> objects){};

哪个更适合您的情况。

因此,如果您采用第二种方法并且由于在运行时进行类型擦除,您将进行 instanceof 检查:

public static <T> int update(List<T> objects){
        for(T object : objects)
        {
            if(object.getClass().isInstance(Pair.class))
            {
                //do something
            }else if(object.getClass().isInstance(Time.class))
            {

            }
        }
        return 0;
    }

但这看起来不是一个好的设计,您可以通过使用工厂方法进行上述改进:

    static Handler getHandler(Class<?> handlerClass)
        {
            if(handlerClass.isInstance(Project.class))
            {
                //return ProjectHandler
            }else if(handlerClass.isInstance(Time.class))
            {
                //return TimeHandler
            }
            //return errorHandler
        }
        interface Handler {
            int handle();
        }
       public static <T> int update(List<T> objects){
            for(T object : objects)
            {
                getHandler(object.getClass()).handle();
            }
            return 0;
        }

现在,一种更好的方法 IMO 是通过标记接口指定要更新的类,然后干净地处理每个类中的更新:

    interface Updateable {
        int update();
    }

    public static <T extends Updateable> int update2(List<T> objects){
        for(T object : objects)
        {
            object.update();
        }
        return 0;
    }
于 2013-05-20T11:17:20.757 回答
1

根据您对我的评论的回答,您有两种方法。首先是尝试提出一个接口,该接口将传递给该方法的所有可能类型都实现。如果您的接口被称为 Foo 您可以将方法定义为:

public int update(List<Foo> list)

然后你的代码将基于 Foo 中可用的方法。

如果你不能这样做,那么你将需要每种可能的类型单独的方法。由于类型擦除,您不能在运行时执行 instanceof。如果列表在编译代码中被擦除,则底层类型将不可用于 instanceof 逻辑。

编辑:为了澄清我上面的答案的一些困惑。迭代列表时,您可以instanceof基于每个元素执行操作,如下所示:

for(Object item:list){
  if (item instanceof A){
    //do A based logic
  }
  else if (item instanceof B){
    //do B based logic
  }
}

但是,您不能像这样在运行时检查列表类型:

if (list instanceof List<A>)

您最好的选择实际上是尝试通过我的第一个解决方案中建议的接口来概括支持的类型。执行 instanceof 方法将导致代码在添加更多支持的类型时需要不断修改。

于 2013-05-20T11:36:48.373 回答
0

扩大苛刻的答案,你不能这样做:

public class Update
{

public static <T> int update(List<T> objects, Class<T> clazz){};

}

然后,在您的实现中,根据传递的 Class 实例改变行为?

于 2013-05-20T11:55:14.180 回答