2

我了解 Java 基础知识,现在我正在阅读 Effective Java。这本书建议使用静态工厂方法而不是构造函数。所以我有这样的 Groovy 代码:

public class Anto {
    public static void main(String[] args) {
            println Java.javaInstance()
        }
}

class Java {
    public static Java javaInstance() {
        return this
    }
}

当我编译这个时,我得到一个这样的错误:

Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class Java' with class 'java.lang.Class' to class 'Java'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class Java' with class 'java.lang.Class' to class 'Java'
    at Java.javaInstance(Anto.groovy:9)
    at Java$javaInstance.call(Unknown Source)
    at Anto.main(Anto.groovy:3)

我在哪里犯错?

4

4 回答 4

3

您可以使用return new Java();. 静态方法无权访问this.

编辑:

这些静态工厂通常是单例的,这意味着应该只使用该类的一个实例(通常,例如与数据库的连接)。如果您想将此维度添加到您的Java类中,请使用私有静态属性,如下所示:

class Java {

    private static Java instance;

    public static Java javaInstance() {
        if(instance == null) {
            instance = new Java();
        }
        return instance;
    }

}
于 2012-05-04T07:34:21.090 回答
2

正确创建 Singleton 很容易出错(尤其是在多线程环境中),因此您最好使用 Groovy 附带的Singleton 注释而不是自己滚动:

public class Anto {
  public static void main(String[] args) {
    println Java.instance
  }
}

@Singleton
class Java {
}

这将Java类转换为:

class Java {
  private static volatile Java instance
  private Java() {}
  static Java getInstance () {
    if( instance ) {
      instance
    } else {
      synchronized( Java ) {
        if( instance ) {
          instance
        } else {
          instance = new Java()
        }
      }
    }
  }
}
于 2012-05-04T08:03:23.977 回答
2

Google Guava是使用静态工厂方法的库的一个很好的示例(尽管不是特定于 Groovy)。Guava 在很多地方都使用了这个成语。例如,它们的Range类支持九种类型的范围,如果它们使用普通的构造函数,它们的签名在几种情况下会发生冲突,因为唯一可以用来区分它们的就是它们的参数。

另一方面,静态方法也可以通过它们的名称来区分,因此 Guava 为每种类型的 Range 定义了不同的方法。在内部,这些方法仍然调用普通的构造函数,但它不是可公开访问的。

import com.google.common.collect.Ranges
import com.google.common.collect.DiscreteDomains

final dom = DiscreteDomains.integers()

assert [1,2,3,4,5] as Set == Ranges.closed(1, 5).asSet(dom)
assert [2,3,4] as Set     == Ranges.open(1, 5).asSet(dom)

这是一个有用的习惯用法,但不应该只是自动优先于普通构造函数。在普通构造函数就足够的情况下,您最多编写的代码比您需要的更多,最坏的情况是无法扩展类,因为任何子类仍然需要它们可以调用的公共或受保护的构造函数。

于 2012-05-04T16:07:35.483 回答
0

您不能使用this,因为static方法不是实例方法。

每次创建特定类的新实例时,该新对象/实例都将作为它自己的状态。this指向一个特定的实例。

你想做一个单身人士吗?意味着您只想要一个类的单个实例?

class Singleton {
     //static reference to a particular instance
     private static Singleton instance;

     //private constructor so that it cant be called outside this class scope
     private Singleton();

     //synchronized in case your working in threaded enviroment
     public synchronized static Singleton getInstance()
     {
       if(NULL == instance)
       {
         instance = new Singleton();
       }
       return instance;
     }
}
于 2012-05-04T07:44:26.253 回答