Java构造函数和静态方法

时间:2012-12-10 14:35:43

标签: java

我何时应该使用构造函数,何时应该使用静态方法?

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

9 个答案:

答案 0 :(得分: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

的多个值进行优化

答案 1 :(得分:19)

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

静态工厂方法的

优点

  • 与构造函数不同,它们具有名称
  • 与构造函数不同,每次调用它们时都不需要创建新对象(可以缓存实例:例如Boolean.valueOf(..)
  • 与构造函数不同,它们可以返回其返回类型的任何子类型的对象(极大的灵活性)
静态工厂方法的

缺点

  • 它们与其他静态方法并不是真的不可分割(如果您不熟悉API,很难找到如何初始化对象)
  • 主要的缺点(如果你只使用静态工厂方法,并使构造函数成为私有)是你不能继承该类。

答案 2 :(得分:8)

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

仅对java.lang.Math中的实用程序方法使用static

示例:

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

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

答案 3 :(得分:3)

静态工厂方法有名称,构造函数没有。因此,工厂方法可以携带有关构造者不能做的事情的自然文档。例如,请参阅Guava Libraries中的工厂方法,如ImmutableMap.copyOf(otherMap)。虽然这可能对构造行为几乎没有影响,但它对代码的可读性有很大影响。如果您要发布API,请务必考虑这一点。

当您需要对正在创建的对象进行更复杂的配置时,也可以使用工厂,特别是如果您需要发布到其他线程(在池中注册,作为MBean公开,各种其他方式) ...)以避免出版。 (参见例如Java Concurrency In Practice部分3.2)

某些东西的静态方法(例如Math.min)与静态工厂不同,静态工厂可以被视为构造函数的直接替换,具有更大的灵活性,可进化性和(通常)清晰度。

答案 4 :(得分:3)

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

答案 5 :(得分:2)

每当您需要创建对象的实例时,您将不得不使用构造函数。

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

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

答案 6 :(得分: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.
   }
}

正如上面的帖子所说,这只是你想做什么以及你想怎么做的问题。此外,不要试图立即理解所有内容,编写一些代码然后尝试不同的代码方法并尝试理解代码的作用。示例很好,但您需要编写然后了解您所做的事情。我认为这是你弄明白的唯一方法 为什么你按照自己的方式做员工。

答案 7 :(得分:1)

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

这是Effective Java

的解释
  

这允许不可变类(第15项)使用预构造   实例,或者在实例构建和缓存实例时进行缓存   他们反复避免创建不必要的重复对象。该   Boolean.valueOf(boolean)方法说明了这种技术:它永远不会   创建一个对象。这种技术类似于Flyweight模式   [Gamma95,p。 195]。如果等效,它可以大大提高性能   经常要求对象,特别是如果它们很昂贵的话   创建

答案 8 :(得分:1)

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

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