无状态类有多少字节?

时间:2012-03-21 02:00:54

标签: java methods singleton

如果我有这个课程:

public interface IBinaryCalculator{
double addition(double numb1, double numb2);
}

public class BinaryCalculator implements IBinaryCalculator{
 double addition(double numb1, double numb2){
  return numb1+numb2;  

}
}

好的,这个方法应该是静态的,但是我在这里有一个接口。单身是唯一的答案,只是在课堂上为BinaryCalc?假设我构建了10,000个BinaryCalculator,它只有方法,它对性能有影响,还是应该使用单例。

5 个答案:

答案 0 :(得分:1)

这个特定类中没有任何东西不能“静止”。

当一个类实例可能具有不同的状态数据时,那么您将需要单个对象。

“Singleton”是一回事(原谅双关语; - ))。

“静态”是另一回事。

可伸缩性是另一个独立的问题。

底线:如果你需要某个东西作为一个对象,那么把它变成一个对象。如果一个方法永远不需要引用实例数据 - 无论如何。如果你愿意,可以自己解决问题,并将其作为一种静态方法。

... IMHO

答案 1 :(得分:1)

我无法完全确定,但您似乎过分担心与创建给定对象的许多实例相关的性能问题。

恕我直言,你应该首先担心设计,如果这样的事情成为问题,你可以担心性能。老实说,你的班级看起来不像是你将有一百万个物品在堆里游泳的类。

您的界面就是所谓的SAM类型(单一抽象方法)。 JDK本身就有很多这样的例子。例如,java.util.Comparator和java.lang.Comparable是两个很好的例子。

如果将方法定义为静态,则必须基于您的设计,而不是基于其执行的任务的功能或简单性。您可能比其他任何人都更了解您的设计,本论坛的开发人员可以帮助您提出好的想法或挑战您当前的设计,这可能有助于改善您已有的设计。

您提到的单例模式旨在阻止创建超过预定义数量的给定类的实例,通常它们将其限制为单个实例。在你的设计中,为什么你想做这样的事情并不明显,但是担心与实例数相关的性能并不是最好的理由。

在寻找简化设计的方法时,如果计划使用不同类型的计算器,可能需要static factory method类您可以在其中放置所有SAM类型的实现:

public class Calculators {

    public static BinaryCalculator getBasicCalculator(){
        return new BinaryCalculator() {

            @Override
            public double addition(double numb1, double numb2) {
                return numb1 + numb2;
            }
        };
    }

    public static BinaryCalculator getSofisticatedCalculator(){
        return new BinaryCalculator() {

            @Override
            public double addition(double numb1, double numb2) {
                //do any other sofisticated calculation
                return numb1 + numb2;
            }
        };
    }

}

然后你可以这样做:

public static void main(String[] args) {
    BinaryCalculator simple = Calculators.getBasicCalculator();
    BinaryCalculator complex = Calculators.getSofisticatedCalculator();

    double result;
    result = simple.addition(10,11);
    result = complex.addition(10,11);
}

此外,如果您被允许进行实验,您可能想试试JDK 8 Lambda Preview,您可以将计算器的实现编写为lamdba表达式。

BinaryCalculator simple = (num1, num2) -> num1 + num2;

甚至在方法中内联,例如

public class Pair {
        private final double a;
        private final double b;

        public Pair(double a, double b){
            this.a = a;
            this.b = b;
        }

        public double calculateWith(BinaryCalculator calculator){
            return calculator.addition(a,b);
        }
    }

然后你可以简单地为你的SAM类型提供一个lambda实现,如下所示:

Pair p = new Pair(10,11);
double result = p.calculateWith( (num1, num2) -> num1 + num2 );
System.out.println(result);

当然,这只是JDK 8的预览,但是,如果您被允许尝试最新功能,那么这将是一个非常酷的解决方案: - )

答案 2 :(得分:0)

几个问题,几个答案。

  1. 我不确定没有状态的对象占用多少内存,但它需要一些,因为它有一个与之关联的监视器。
  2. 对于此类的类,您可以使用静态方法(如java.lang.Math)或基于常规实例的方法。
  3. Singleton越来越被认为是不好的风格,应谨慎使用。对于无状态类,它可能没问题,但就个人而言,我宁愿只依靠用户来创建无用的对象。

答案 3 :(得分:0)

不要'做:

10,000  new BinaryCalculator().addition(42,24);

执行:

BinaryCalculator bc = new BinaryCalculator();
10,000  bc.addition(42,24);

如果您使用:

MemoryMXBean mBean = ManagementFactoryHelper.getMemoryMXBean();
mBean.getHeapMemoryUsage().getUsed()

在一个单独的测试中,您应该看到第一个示例中的getUsed()增长和收缩,以及第二个示例中的稳定使用。您还可以使用getUsed()来了解堆耗尽和GC的速度。

答案 4 :(得分:0)

单个类实例使用的内存取决于您使用的JVM,在某些情况下取决于其他内容。但是对象的标题通常占用8到16个字节。根据对对象的处理,也可以有其他隐藏状态; e.g。

  • “充气”锁定数据结构,
  • 存储对象的标识哈希码值。

但是,这可能对您的应用程序的性能没有任何可衡量的影响。