有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

oop Java=返回对象列表/数组与ResultObject(与方法参数相同)

这似乎是一个奇怪的问题:我正在努力确定在非常精细的级别上处理“类型化对象”是否是一种良好的实践和“有效的”

public Object[] doSomething() {
    Object[] resultList = new Object[] {new Foo(), new Bar()};
    return resultList;
}

public Result doSomething() {
    Result result = new Result();
    result.foo = new Foo();
    result.bar = new Bar();
    return result;
}

public class Result{
    Foo foo;
    Bar bar;
}

我的问题具体如下:

  1. 就CPU周期而言(作为一个相对数字),第二种方法消耗了多少资源。(如100%以上)

  2. 关于内存消耗的相同问题

注意(这两个问题需要更多地理解,不是关于过早优化的问题)

  1. 在“良好设计实践”方面。你认为版本1是绝对不可能的还是你认为它实际上并不重要。。。或者你会建议永远不要返回“对象数组”((在面向对象的编程语言中))

这是一个问题,我一直在想,我是应该为所有东西创建专用对象(用于传递值),还是应该使用通用对象(和公共方法参数…)

这个问题也适用于

public doSomething(Query query ) 

public doSomething(Foo foo, Bar bar, Aaaa, a, Bbbbb)

谢谢

马库斯


共 (3) 个答案

  1. # 1 楼答案

    我不认为定义一个Result类并返回一个在运行时消耗比构建一个Object[]更多资源的类。(当然,存储和加载类定义的成本很小。)您是否有数据表明存在其他情况

    返回非类型化对象数组是一种糟糕的做法,原因有很多,其中包括:

    1. 这很容易出错
    2. 它更难维护
    3. 回归“真实”类型也不是免费的

    关于你的其他问题:

    public doSomething(Query query) 
    

    public doSomething(Foo foo, Bar bar)
    

    这一点不那么明确。如果将FooBar打包成Query对象在问题域中是有意义的,那么我肯定会这样做。如果只是为了最小化参数数量而打包(也就是说,在您的问题域中没有“查询对象”概念),那么我可能不会这么做。如果这是一个运行时性能的问题,那么答案是(一如既往)配置文件

  2. # 2 楼答案

    3.) In terms of "good design pratice". Do you think version 1 is an absolute No-Go or do you rather think it actually does not matter...Or would you propose never returnung "object Arrays" (((in an object oriented programming langauge/regarding encapsulation ...)))...

    第1版是绝对禁止的。它几乎完全没有类型。调用者必须知道实际的类型以及它们在数组中的位置,并进行适当的强制转换。您将丢失任何有用的编译时类型检查,并且代码本身明显不太清晰

    我永远不会返回Object[],除非它包含的值是用new Object()构造的

  3. # 3 楼答案

    我必须做一个实验才能真正知道,但我猜对象数组不会明显更快。它甚至可能更慢。毕竟,无论哪种情况,都必须创建一个对象:数组对象或结果对象。对于结果对象,您必须在第一次使用它时从磁盘读取类定义,并且类定义必须在内存中浮动,因此会有一些额外的成本。但是对于array对象,当您取出数据时,必须进行强制转换,JVM必须对数组进行边界检查(如果调用方试图检索resultList[12]?),会发生什么情况,这也需要额外的工作。我的猜测是,如果只执行一次或两次,数组将更快(因为类加载时间),但如果执行多次,专用对象将更快(因为强制转换和数组访问时间)。但我承认我只是在猜测

    在任何情况下,即使阵列确实有一点性能优势,代码可读性和可维护性的损失几乎肯定是不值得的

    最糟糕的情况是,如果数组中返回的值属于同一类,但语义不同。假设你这样做:

    public Object[] getCustomerData(int customerid)
    {
      String customerName=... however you get it ...
      BigDecimal currentDue=...
      BigDecimal pastDue=...
      return new Object[] {customerName, pastDue, currentDue};
    }
    ... meanwhile, back at the ranch ...
    Object[] customerData=getCustomerData(customerid);
    BigDecimal pastDue=(BigDecimal)customerData[2];
    if (pastDue>0)
      sendNastyCollectionLetter();
    

    你看到错误了吗?当条目#2应该是#1时,我将其检索为pastDue。你可以很容易地想象,如果一个程序员在一个不考虑的时刻,从一开始而不是从零开始计算字段,就会发生这种情况。或者,如果他算错了,说“14”,而实际上是“15”。由于两者都有相同的数据类型,因此可以很好地编译和运行。但我们将向未到期的客户发送不适当的催款信。这对客户关系非常不利

    好吧,也许这是一个糟糕的例子,我只是把它从我的头顶上扯下来,因为我们可能会在测试中发现它。但是,如果我们切换的值很少使用,以至于没有人想到为它们包含一个测试场景,该怎么办呢。或者它们的影响很微妙,因此错误可能会在测试中漏掉。就这一点而言,如果您匆忙完成一项更改,或者如果测试人员出现失误,等等,那么您可能无法在测试中捕捉到这一点