我了解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)
我在哪里犯了错误?
答案 0 :(得分:3)
您可以使用return new Java();
执行此操作。静态方法无权访问this
。
修改强>
这些静态工厂通常是单例,这意味着只应该使用该类的一个实例(例如,通常是与db的连接)。如果您想将此维度添加到Java
类,请使用私有静态属性,如下所示:
class Java {
private static Java instance;
public static Java javaInstance() {
if(instance == null) {
instance = new Java();
}
return instance;
}
}
答案 1 :(得分:2)
正确创建一个Singleton很容易出错(特别是在多线程环境中),所以你可能更好地使用Groovy附带的Singleton annotation而不是自己编译:
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()
}
}
}
}
}
答案 2 :(得分:2)
使用静态工厂方法的库的一个好的(尽管不是特定于Groovy)示例是Google 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)
这是一个有用的习惯用语,但不应该比普通的构造函数更自动地优先使用。在普通构造函数足够的情况下,您最多编写的代码超出了您的需要,最坏的情况是扩展类不可能,因为任何子类仍然需要一个可以调用的公共或受保护构造函数。
答案 3 :(得分: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;
}
}