以下是实现单例的两种方法.各有哪些优缺点?
静态初始化:
class Singleton {
private Singleton instance;
static {
instance = new Singleton();
}
public Singleton getInstance() {
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
延迟初始化是:
class Singleton {
private Singleton instance;
public Singleton getInstance(){
if (instance == null) instance = new Singleton();
return instance;
}
}
Run Code Online (Sandbox Code Playgroud) 我习惯了 Swifts 的可选值,并且看到 TypeScript 有类似的东西。对于诸如属性的延迟初始化之类的事情,拥有一个私有属性nullable和一个public在请求时初始化值的getter 会很好。
class Test {
private _bar: object:null = null;
get bar(): object {
if (_bar === null) {
_bar = { };
}
return _bar;
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以为此使用 undefined 并从私有成员中删除可为空的类型信息,但我想知道是否有一种方法可以做到这一点而不必永远携带该属性的空值。我将从一个我想要处理空值的地方到一个我不再希望强迫任何人处理可空值的边界。
Haskell 有一个非常膨胀的undefined值,它懒惰地引发异常(在评估时)。Ocaml 当然是严格的,所以据我所知,没有等同于 Haskell 的undefined. 不过这很不幸,因为这意味着值没有底部类型。假设我想要一个
val a : int
Run Code Online (Sandbox Code Playgroud)
我当然可以
let a = failwith "undefined"
let () =
print_string "something unrelated\n"
Run Code Online (Sandbox Code Playgroud)
这很高兴编译。不幸的是,在运行它时,我们得到了未定义的异常(这是预期的)。
我想要的是在不改变它的类型的情况下让它a成为一个底部/undefined值(这样的事情Lazy就行不通了)。这可能吗?
额外的细节:
所以我所要求的可能听起来很愚蠢。为了减少对我为什么不应该这样做的任何评论,请允许我简要描述我的用例。我正在编写一个脚本来修改mli文件的 AST以生成一个ml与其签名匹配的“空”文件。对于一般情况,您可能有val a : int,mli所以我需要一种方法来一般地合成底部类型。failwith "undefined"如果我只需要编译成功就可以工作。但不幸的是,我还需要将此ml文件链接到 OUnit 测试套件并运行它(显然该套件会失败,但目的是能够运行它,-list-test以便我可以以编程方式获取所有测试的列表)。
更多细节:
我认识到解决这个问题的正确方法(可能)是编写一个可以为任何泛型类型生成底部类型的函数。对于内置原语(和list,option等),这很简单(只是冗长的)。这对于记录变得更加复杂(可能在 stdlib 中定义,但也可能在同一个文件或不同的包中定义)。为了处理这个问题,我的 AST 转换器需要对 OCaml 类型系统和包的文件导入策略有一个完整的理解,这比我想要/应该包含的逻辑要多得多。
在 kotlin 中,我们可以同时使用这两种方法lazy{}和getter()
延迟初始化:
internal val connector by lazy {
serviceConnector
}
Run Code Online (Sandbox Code Playgroud)
吸气剂():
internal val connector : ServiceConnector
get() = serviceConnector
Run Code Online (Sandbox Code Playgroud)
何时使用哪种方法以及这两种方法在幕后实际做了什么。哪一种是最好的方法?
我们现在有了一种创建惰性变量的新方法。它在swift-evolution/proposals/0258-property-wrappers.md 中有描述:
@propertyWrapper
enum Lazy<Value> {
case uninitialized(() -> Value)
case initialized(Value)
init(wrappedValue: @autoclosure @escaping () -> Value) {
self = .uninitialized(wrappedValue)
}
var wrappedValue: Value {
mutating get {
switch self {
case .uninitialized(let initializer):
let value = initializer()
self = .initialized(value)
return value
case .initialized(let value):
return value
}
}
set {
self = .initialized(newValue)
}
}
}
Run Code Online (Sandbox Code Playgroud)
它是线程安全的实现吗?如果没有,如何重现非线程安全行为?
generics lazy-evaluation lazy-initialization swift property-wrapper
我知道有很多这方面的主题和资源,但我想知道一个非常具体的问题(可能需要很长时间才能检查所有来源以获得明确答案).
我知道JVM/Dalvik保证当你访问类的静态字段时(final static原始值除外),类的静态字段已经初始化.反之亦然吗?如果我从来没有在所有访问类(例如,因为switch-case在另一个静态方法的代码永远不会达到一定的分支),是它保证了虚拟机并没有初始化这个类的静态?
假设我有一个这样的类:
public class Boo {
public static int[] anything = new int[] { 2,3,4 };
private static int[] something = new int[] { 5,6,7 }; // this may be much bigger as well
public static final int[] getAndClear() {
int[] st = something;
something = null;
return st;
}
}
Run Code Online (Sandbox Code Playgroud)
我的应用程序是一个非常特殊的应用程序(在某些方面不典型),并且它可能包含数百个类,例如Boo(由代码生成器生成),其中something可能是不同元素计数的数组(因此它可能包含很多元素,如好吧有时候).
根据应用程序输入,许多这些预生成的类可能永远不会被访问.我不希望很多int[]对象被不必要地初始化,占用大量内存.
如何延迟初始化@Inject的依赖项?
public class ClassA {
@Inject
ClassB classB;
}
@Configuration
public class Config {
@Bean
public ClassA classA() {
return new ClassA();
}
@Bean
@Lazy
public ClassB classB() {
return new ClassB();
}
}
Run Code Online (Sandbox Code Playgroud)
实例化classA bean时,尽管有@Lazy批注,classB bean也被实例化。如何避免classB bean实例化?
Swift中的Lazy或Optional属性有什么区别?
例如,如果某人正在构建从侧面进入的导航栏,那么我认为所有这些都应该在一个之内UIViewController。用户可能永远不会打开菜单,但有时会打开。
var menu: NavigationBar?
lazy var menu: NavigationBar = NavigationBar.initialize()
Run Code Online (Sandbox Code Playgroud)
我认为这两个可选代码都是不错的代码,因为除非需要,否则它们不会创建视图。我知道这Optional意味着可能会有价值nil。我也明白Lazy,在我需要它之前,请不要担心。
具体问题
我的问题是它们的性能模式(安全性和速度)是否表示可选件更快,更安全,反之亦然?
我得到了一个典型的订单和物品的实体关联。为了使只读订单成为可能,项目设置为默认FetchType.LAZY。2级和查询缓存已启用。要读取具有关联项目的订单,我正在使用JPQL查询。查询和实体由EHCache缓存。但是在访问项目时的第二次调用中,引发了LazyInitializationException异常,因为未初始化项目(未从缓存还原)。为什么?实施此要求的最佳方法是什么?
订购:
@Entity
@Cacheable
@NamedQueries({
@NamedQuery(name = Order.NQ_FIND_BY_ID_FETCH_ITEMS, query = "SELECT DISTINCT o FROM Order o JOIN FETCH o.items WHERE o.id = :id")
})
@Table(...)
public class Order extends ... {
...
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
// @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<Item> items = new HashSet<Item>();
...
}
Run Code Online (Sandbox Code Playgroud)
项目:
@Entity
@Cacheable
@Table(...)
public class Item extends ... {
@ManyToOne
@JoinColumn(name = "order_id", nullable = false)
private Order order;
...
}
Run Code Online (Sandbox Code Playgroud)
道:
public class OrderDaoJpaImpl extends …Run Code Online (Sandbox Code Playgroud) 看起来Java内存模型没有定义本地缓存的“刷新”和“刷新”,相反,人们只是为了简单起见才这样称呼它,但实际上“ happens-before”关系意味着以某种方式刷新和刷新(如果您可以对此进行解释,但不能直接成为问题的一部分)。
令我感到困惑的是,JLS中有关Java内存模型的部分并未以易于理解的方式编写。
因此,能否请您告诉我我在以下代码中所做的假设是否正确以及是否可以保证正常运行?
它部分基于Wikipedia文章中有关双重检查锁定的代码,但是作者在其中使用了包装器类(FinalWrapper),但这对我来说并不完全清楚。也许支持null价值观?
public class Memoized<T> {
private T value;
private volatile boolean _volatile;
private final Supplier<T> supplier;
public Memoized(Supplier<T> supplier) {
this.supplier = supplier;
}
public T get() {
/* Apparently have to use local variable here, otherwise return might use older value
* see https://jeremymanson.blogspot.com/2008/12/benign-data-races-in-java.html
*/
T tempValue = value;
if (tempValue == null) {
// Refresh
if (_volatile);
tempValue = value;
if (tempValue == null) …Run Code Online (Sandbox Code Playgroud)