18

什么时候应该使用构造函数,什么时候应该使用静态方法?

你能用小片段解释一下吗?我浏览了一些线程,但我仍然不清楚这一点。

4

9 回答 9

21

Joshua Bloch建议使用静态工厂方法而不是构造函数(我认为这是一个很好的做法)。几个优点和缺点:

静态工厂方法的优点

  • 与构造函数不同,它们有名称
  • 与构造函数不同,它们不需要在每次调用时都创建一个新对象(您可以缓存实例:例如Boolean.valueOf(..)
  • 与构造函数不同,它们可以返回其返回类型的任何子类型的对象(非常灵活)

静态工厂方法的缺点

  • 它们与其他静态方法并没有真正的区别(如果您不熟悉 API,很难找出如何初始化对象)
  • 主要缺点(如果您只使用静态工厂方法,并将构造函数设为私有)是您不能子类化该类。
于 2012-12-10T14:49:06.250 回答
19

当您只想返回该类型的新对象并且想要简单时,请使用公共构造函数。

一个很好的例子是 StringBuilder,因为它是可变的,你可能每次都想要一个新对象。

public String toString() {
    StringBuilder sb = new StringBuilder();
    // append fields to the sb
    return sb.toString();
}

当您可能想要重用对象(尤其是不可变对象)、您可能想要返回子类或想要描述构造时,请使用静态因子方法。一个很好的例子是 EnumSet,它有许多静态工厂,即使有些具有相同的参数,它们也会做不同的事情。

EnumSet.noneOf(RetentionPolicy.class);
// has the same arguments, but is not the same as
EnumSet.allOf(RetentionPolicy.class);

在这种情况下,使用静态工厂可以清楚地说明这两种构造集合的方式之间的区别。

EnumSet 还可以返回两种不同的实现,一种针对具有少量值 (<= 64) 的枚举进行优化,RegularEnumSet另一种针对称为多个值的枚举进行优化JumboEnumSet

于 2012-12-10T14:37:41.940 回答
8

如果您的类具有状态(即使对于单个实例;单例模式),请始终使用构造函数。

仅对 java.lang.Math 等实用方法使用静态

例子:

public static int max(int a, int b) {
    return (a >= b) ? a : b;
}

不改变对象的任何状态(实例变量),因此它可以被声明为静态的。

于 2012-12-10T14:41:23.317 回答
4
  1. 当您需要一个对象和其他东西(如函数和变量)时,请使用构造函数,每个对象都有一个副本。
  2. 当您想在不创建对象的情况下做某事时,请使用静态方法。

    Example:
    public class Test {
    public int value;
    public static int staticValue;
    public int getValue() {
    return ++value;
    }
    
    public static int getStaticValue() {
    return ++staticValue;
    }
    }
    
    public class TestClass {
    public static void main(String[] args) {
    Test obj = new Test();
    Test obj1 = new Test();
    S.o.p(obj.getValue());
    S.o.p(obj1.getValue));
    S.o.p(Test.getStaticValue());
    S.o.p(Test.getStaticValue());
    }
    }
    
于 2012-12-10T14:41:23.807 回答
3

静态工厂方法有名字,构造函数没有。因此,工厂方法可以自然地记录它们所做的事情,而构造函数却不能。例如,查看 Guava 库中的工厂方法,例如ImmutableMap.copyOf(otherMap). 虽然这可能对构造行为几乎没有影响,但它对代码的可读性有很大影响。如果您要发布 API,请务必考虑这一点。

当您需要对正在创建的对象进行任何更复杂的配置时,您也可以使用工厂,特别是如果您需要发布到其他线程(在池中注册、作为 MBean 公开,以及所有其他方式...... ) 以避免发布不雅内容。(参见例如 Java 并发实践第 3.2 节)

做某事(例如)的静态方法Math.min与静态工厂并不真正相同,静态工厂可以被认为是构造函数的直接替代品,增加了灵活性、可进化性和(通常)清晰性。

于 2012-12-10T14:39:41.813 回答
2

每当您需要创建对象的实例时,都必须使用构造函数。

所以,如果你想创建一个 Car 对象,那么你需要一个构造函数。

关键字 static 意味着可以在不创建实例的情况下调用您的方法。

于 2012-12-10T14:40:18.027 回答
2
class Car
{
   private int num_of_seats;

   public Car(int number_of_seats)
   {
      this.num_of_seats = number_of_seats;
   }

   // You want to get the name of the class that has to do with
   // this class, but it's not bounded with any data of the class
   // itself. So you don't need any instance of the class, and 
   // you can declare it as static.
   static String getClassName()
   {
      return "[Car]";
   }
}

通常,您将使用带有与对象实例不相关的数据的静态类。

另一个例子是:

class Ring
{
   private List nodes;

   public Ring(List nodes) 
   {
      this.nodes = nodes;
   }

   // You want to calculate the distance of two ids on the ring, but
   // you don't care about the ring. You care only about the ids.
   // However, this functionality logical falls into the notion of
   // the ring, that's why you put it here and you can declare it
   // as static. That way you don't have to manage the instance of 
   // ring.
   static double calculateDistance(int id_1, int id_2)
   {
      return (id_1 - id_2)/383; // The divisor is just random just like the calculation.
   }
}

正如上面的帖子所说,这只是你想做什么以及你想怎么做的问题。另外,不要试图立即理解所有内容,编写一些代码然后尝试该代码的不同方法并尝试理解您的代码的作用。例子很好,但你需要写出来然后理解你做了什么。我认为这是您弄清楚为什么要以必须的方式雇用员工的唯一方法。

于 2012-12-11T19:02:19.130 回答
1

静态方法不必每次都实例化新对象。由于对象实例化很昂贵,它允许将实例缓存在对象中。因此,它可以提高性能。

这是来自Effective Java的解释:

这允许不可变类(第 15 条)使用预先构造的实例,或在构造实例时缓存实例,并重复分配它们以避免创建不必要的重复对象。Boolean.valueOf(boolean) 方法说明了这种技术:它从不创建对象。这种技术类似于享元模式 [Gamma95, p. 195]。如果经常请求等效对象,尤其是创建它们的成本很高时,它可以极大地提高性能。

于 2012-12-10T14:46:11.900 回答
1

即如果你想使用一个单例,这意味着你只有一个对象的实例,它可能与其他人共享,那么你需要一个静态方法,它将在内部调用构造函数。因此,每次有人想要该对象的实例时,您将始终返回相同的值,因此您只会为一个对象消耗内存。在面向对象编程中,在每种 OO 语言中,您总是需要一个构造函数。在 java 和许多其他语言中,对象的默认构造函数是隐含的,并且是自动构建的。但是您需要一些自定义功能,您必须自己制作。

在上面,您可以看到一些很好的用法示例。但是,如果您有特定的想法,请告诉我们。我的意思是,如果您有不确定是否应该使用静态方法或构造函数的特定情况。无论如何,您肯定需要一个构造函数,但我不确定静态方法。

于 2012-12-10T14:54:22.593 回答