首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过静态工厂方法返回对象?

如何通过静态工厂方法返回对象?
EN

Stack Overflow用户
提问于 2012-05-04 15:32:45
回答 4查看 932关注 0票数 2

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

代码语言:javascript
复制
public class Anto {
    public static void main(String[] args) {
            println Java.javaInstance()
        }
}

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

当我编译这段代码时,我得到一个类似下面这样的错误:

代码语言:javascript
复制
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)

我在哪里犯了错?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-05-04 16:03:24

正确地创建单例很容易出错(特别是在多线程环境中),所以您最好使用Groovy附带的Singleton annotation,而不是使用自己的:

代码语言:javascript
复制
public class Anto {
  public static void main(String[] args) {
    println Java.instance
  }
}

@Singleton
class Java {
}

这会将Java类转换为:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2012-05-04 15:34:21

您可以使用return new Java();来完成此操作。静态方法不能访问this

编辑:

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

代码语言:javascript
复制
class Java {

    private static Java instance;

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

}
票数 3
EN

Stack Overflow用户

发布于 2012-05-05 00:07:35

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

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

代码语言:javascript
复制
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)

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10444615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档