Reflection: refactor property construction and fix memory leak
Properties obtained by KClass.properties were having strong references to descriptors (captured by closures, which are strongly retained by DescriptorBasedProperty). Support initial value in lazy soft properties
This commit is contained in:
@@ -18,6 +18,7 @@ package kotlin.reflect.jvm.internal
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
|
import org.jetbrains.kotlin.load.java.structure.reflect.desc
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||||
@@ -26,10 +27,22 @@ import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
|||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
abstract class DescriptorBasedProperty(computeDescriptor: () -> PropertyDescriptor) {
|
abstract class DescriptorBasedProperty private(
|
||||||
protected abstract val container: KCallableContainerImpl
|
container: KCallableContainerImpl,
|
||||||
|
name: String,
|
||||||
|
receiverParameterDesc: String?,
|
||||||
|
descriptorInitialValue: PropertyDescriptor?
|
||||||
|
) {
|
||||||
|
constructor(container: KCallableContainerImpl, name: String, receiverParameterClass: Class<*>?) : this(
|
||||||
|
container, name, receiverParameterClass?.desc, null
|
||||||
|
)
|
||||||
|
|
||||||
protected abstract val name: String
|
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : this(
|
||||||
|
container,
|
||||||
|
descriptor.getName().asString(),
|
||||||
|
descriptor.getExtensionReceiverParameter()?.getType()?.let { type -> RuntimeTypeMapper.mapTypeToJvmDesc(type) },
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
|
||||||
private data class PropertyProtoData(
|
private data class PropertyProtoData(
|
||||||
val proto: ProtoBuf.Callable,
|
val proto: ProtoBuf.Callable,
|
||||||
@@ -37,7 +50,9 @@ abstract class DescriptorBasedProperty(computeDescriptor: () -> PropertyDescript
|
|||||||
val signature: JvmProtoBuf.JvmPropertySignature
|
val signature: JvmProtoBuf.JvmPropertySignature
|
||||||
)
|
)
|
||||||
|
|
||||||
protected val descriptor: PropertyDescriptor by ReflectProperties.lazySoft(computeDescriptor)
|
protected val descriptor: PropertyDescriptor by ReflectProperties.lazySoft<PropertyDescriptor>(descriptorInitialValue) {
|
||||||
|
container.findPropertyDescriptor(name, receiverParameterDesc)
|
||||||
|
}
|
||||||
|
|
||||||
// null if this is a property declared in a foreign (Java) class
|
// null if this is a property declared in a foreign (Java) class
|
||||||
private val protoData: PropertyProtoData? by ReflectProperties.lazyWeak {
|
private val protoData: PropertyProtoData? by ReflectProperties.lazyWeak {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|||||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||||
import org.jetbrains.kotlin.load.java.structure.reflect.classLoader
|
import org.jetbrains.kotlin.load.java.structure.reflect.classLoader
|
||||||
import org.jetbrains.kotlin.load.java.structure.reflect.createArrayType
|
import org.jetbrains.kotlin.load.java.structure.reflect.createArrayType
|
||||||
import org.jetbrains.kotlin.load.java.structure.reflect.desc
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
@@ -42,9 +41,7 @@ abstract class KCallableContainerImpl {
|
|||||||
|
|
||||||
abstract val scope: JetScope
|
abstract val scope: JetScope
|
||||||
|
|
||||||
protected fun findPropertyDescriptor(name: String, receiverParameterClass: Class<*>? = null): () -> PropertyDescriptor = {
|
fun findPropertyDescriptor(name: String, receiverDesc: String? = null): PropertyDescriptor {
|
||||||
val receiverDesc = receiverParameterClass?.desc
|
|
||||||
|
|
||||||
val properties = scope
|
val properties = scope
|
||||||
.getProperties(Name.identifier(name))
|
.getProperties(Name.identifier(name))
|
||||||
.filter { descriptor ->
|
.filter { descriptor ->
|
||||||
@@ -57,14 +54,14 @@ abstract class KCallableContainerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (properties.size() != 1) {
|
if (properties.size() != 1) {
|
||||||
val debugText = if (receiverParameterClass == null) name else "${receiverParameterClass.getSimpleName()}.$name"
|
val debugText = if (receiverDesc == null) name else "$receiverDesc.$name"
|
||||||
throw KotlinReflectionInternalError(
|
throw KotlinReflectionInternalError(
|
||||||
if (properties.isEmpty()) "Property '$debugText' not resolved in $this"
|
if (properties.isEmpty()) "Property '$debugText' not resolved in $this"
|
||||||
else "${properties.size()} properties '$debugText' resolved in $this"
|
else "${properties.size()} properties '$debugText' resolved in $this"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.single() as PropertyDescriptor
|
return properties.single() as PropertyDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check resulting method's return type
|
// TODO: check resulting method's return type
|
||||||
|
|||||||
@@ -69,14 +69,14 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
|
|||||||
|
|
||||||
fun getProperties(declared: Boolean): Collection<KMemberProperty<T, *>> =
|
fun getProperties(declared: Boolean): Collection<KMemberProperty<T, *>> =
|
||||||
getProperties(extension = false, declared = declared) { descriptor ->
|
getProperties(extension = false, declared = declared) { descriptor ->
|
||||||
if (descriptor.isVar()) KMutableMemberPropertyImpl<T, Any?>(this) { descriptor }
|
if (descriptor.isVar()) KMutableMemberPropertyImpl<T, Any?>(this, descriptor)
|
||||||
else KMemberPropertyImpl<T, Any?>(this) { descriptor }
|
else KMemberPropertyImpl<T, Any?>(this, descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getExtensionProperties(declared: Boolean): Collection<KMemberExtensionProperty<T, *, *>> =
|
fun getExtensionProperties(declared: Boolean): Collection<KMemberExtensionProperty<T, *, *>> =
|
||||||
getProperties(extension = true, declared = declared) { descriptor ->
|
getProperties(extension = true, declared = declared) { descriptor ->
|
||||||
if (descriptor.isVar()) KMutableMemberExtensionPropertyImpl<T, Any?, Any?>(this) { descriptor }
|
if (descriptor.isVar()) KMutableMemberExtensionPropertyImpl<T, Any?, Any?>(this, descriptor)
|
||||||
else KMemberExtensionPropertyImpl<T, Any?, Any?>(this) { descriptor }
|
else KMemberExtensionPropertyImpl<T, Any?, Any?>(this, descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <P : KProperty<*>> getProperties(extension: Boolean, declared: Boolean, create: (PropertyDescriptor) -> P): Collection<P> =
|
private fun <P : KProperty<*>> getProperties(extension: Boolean, declared: Boolean, create: (PropertyDescriptor) -> P): Collection<P> =
|
||||||
@@ -91,10 +91,10 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
|
|||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
fun memberProperty(name: String): KMemberProperty<T, *> =
|
fun memberProperty(name: String): KMemberProperty<T, *> =
|
||||||
KMemberPropertyImpl<T, Any>(this, findPropertyDescriptor(name))
|
KMemberPropertyImpl<T, Any>(this, name)
|
||||||
|
|
||||||
fun mutableMemberProperty(name: String): KMutableMemberProperty<T, *> =
|
fun mutableMemberProperty(name: String): KMutableMemberProperty<T, *> =
|
||||||
KMutableMemberPropertyImpl<T, Any>(this, findPropertyDescriptor(name))
|
KMutableMemberPropertyImpl<T, Any>(this, name)
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean =
|
override fun equals(other: Any?): Boolean =
|
||||||
other is KClassImpl<*> && jClass == other.jClass
|
other is KClassImpl<*> && jClass == other.jClass
|
||||||
|
|||||||
+13
-8
@@ -23,10 +23,11 @@ import kotlin.reflect.IllegalPropertyAccessException
|
|||||||
import kotlin.reflect.KMemberExtensionProperty
|
import kotlin.reflect.KMemberExtensionProperty
|
||||||
import kotlin.reflect.KMutableMemberExtensionProperty
|
import kotlin.reflect.KMutableMemberExtensionProperty
|
||||||
|
|
||||||
open class KMemberExtensionPropertyImpl<D : Any, E, out R>(
|
open class KMemberExtensionPropertyImpl<D : Any, E, out R> : DescriptorBasedProperty, KMemberExtensionProperty<D, E, R>, KPropertyImpl<R> {
|
||||||
override val container: KClassImpl<D>,
|
constructor(container: KClassImpl<D>, name: String, receiverParameterClass: Class<E>) : super(container, name, receiverParameterClass)
|
||||||
computeDescriptor: () -> PropertyDescriptor
|
|
||||||
) : DescriptorBasedProperty(computeDescriptor), KMemberExtensionProperty<D, E, R>, KPropertyImpl<R> {
|
constructor(container: KClassImpl<D>, descriptor: PropertyDescriptor) : super(container, descriptor)
|
||||||
|
|
||||||
override val name: String get() = descriptor.getName().asString()
|
override val name: String get() = descriptor.getName().asString()
|
||||||
|
|
||||||
override val getter: Method get() = super<DescriptorBasedProperty>.getter!!
|
override val getter: Method get() = super<DescriptorBasedProperty>.getter!!
|
||||||
@@ -45,10 +46,14 @@ open class KMemberExtensionPropertyImpl<D : Any, E, out R>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class KMutableMemberExtensionPropertyImpl<D : Any, E, R>(
|
class KMutableMemberExtensionPropertyImpl<D : Any, E, R> :
|
||||||
container: KClassImpl<D>,
|
KMemberExtensionPropertyImpl<D, E, R>,
|
||||||
computeDescriptor: () -> PropertyDescriptor
|
KMutableMemberExtensionProperty<D, E, R>,
|
||||||
) : KMemberExtensionPropertyImpl<D, E, R>(container, computeDescriptor), KMutableMemberExtensionProperty<D, E, R>, KMutablePropertyImpl<R> {
|
KMutablePropertyImpl<R> {
|
||||||
|
constructor(container: KClassImpl<D>, name: String, receiverParameterClass: Class<E>) : super(container, name, receiverParameterClass)
|
||||||
|
|
||||||
|
constructor(container: KClassImpl<D>, descriptor: PropertyDescriptor) : super(container, descriptor)
|
||||||
|
|
||||||
override val setter: Method get() = super<KMemberExtensionPropertyImpl>.setter!!
|
override val setter: Method get() = super<KMemberExtensionPropertyImpl>.setter!!
|
||||||
|
|
||||||
override fun set(instance: D, extensionReceiver: E, value: R) {
|
override fun set(instance: D, extensionReceiver: E, value: R) {
|
||||||
|
|||||||
@@ -21,10 +21,11 @@ import kotlin.reflect.IllegalPropertyAccessException
|
|||||||
import kotlin.reflect.KMemberProperty
|
import kotlin.reflect.KMemberProperty
|
||||||
import kotlin.reflect.KMutableMemberProperty
|
import kotlin.reflect.KMutableMemberProperty
|
||||||
|
|
||||||
open class KMemberPropertyImpl<T : Any, out R>(
|
open class KMemberPropertyImpl<T : Any, out R> : DescriptorBasedProperty, KMemberProperty<T, R>, KPropertyImpl<R> {
|
||||||
override val container: KClassImpl<T>,
|
constructor(container: KClassImpl<T>, name: String) : super(container, name, null)
|
||||||
computeDescriptor: () -> PropertyDescriptor
|
|
||||||
) : DescriptorBasedProperty(computeDescriptor), KMemberProperty<T, R>, KPropertyImpl<R> {
|
constructor(container: KClassImpl<T>, descriptor: PropertyDescriptor) : super(container, descriptor)
|
||||||
|
|
||||||
override val name: String get() = descriptor.getName().asString()
|
override val name: String get() = descriptor.getName().asString()
|
||||||
|
|
||||||
override fun get(instance: T): R {
|
override fun get(instance: T): R {
|
||||||
@@ -40,10 +41,11 @@ open class KMemberPropertyImpl<T : Any, out R>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class KMutableMemberPropertyImpl<T : Any, R>(
|
class KMutableMemberPropertyImpl<T : Any, R> : KMemberPropertyImpl<T, R>, KMutableMemberProperty<T, R>, KMutablePropertyImpl<R> {
|
||||||
container: KClassImpl<T>,
|
constructor(container: KClassImpl<T>, name: String) : super(container, name)
|
||||||
computeDescriptor: () -> PropertyDescriptor
|
|
||||||
) : KMemberPropertyImpl<T, R>(container, computeDescriptor), KMutableMemberProperty<T, R>, KMutablePropertyImpl<R> {
|
constructor(container: KClassImpl<T>, descriptor: PropertyDescriptor) : super(container, descriptor)
|
||||||
|
|
||||||
override fun set(instance: T, value: R) {
|
override fun set(instance: T, value: R) {
|
||||||
try {
|
try {
|
||||||
val setter = setter
|
val setter = setter
|
||||||
|
|||||||
@@ -31,21 +31,17 @@ class KPackageImpl(override val jClass: Class<*>) : KCallableContainerImpl(), KP
|
|||||||
|
|
||||||
override val scope: JetScope get() = descriptor.getMemberScope()
|
override val scope: JetScope get() = descriptor.getMemberScope()
|
||||||
|
|
||||||
fun topLevelVariable(name: String): KTopLevelVariable<*> {
|
fun topLevelVariable(name: String): KTopLevelVariable<*> =
|
||||||
return KTopLevelVariableImpl<Any?>(this, findPropertyDescriptor(name))
|
KTopLevelVariableImpl<Any?>(this, name)
|
||||||
}
|
|
||||||
|
|
||||||
fun mutableTopLevelVariable(name: String): KMutableTopLevelVariable<*> {
|
fun mutableTopLevelVariable(name: String): KMutableTopLevelVariable<*> =
|
||||||
return KMutableTopLevelVariableImpl<Any?>(this, findPropertyDescriptor(name))
|
KMutableTopLevelVariableImpl<Any?>(this, name)
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> topLevelExtensionProperty(name: String, receiver: Class<T>): KTopLevelExtensionProperty<T, *> {
|
fun <T> topLevelExtensionProperty(name: String, receiver: Class<T>): KTopLevelExtensionProperty<T, *> =
|
||||||
return KTopLevelExtensionPropertyImpl<T, Any?>(this, findPropertyDescriptor(name, receiver))
|
KTopLevelExtensionPropertyImpl<T, Any?>(this, name, receiver)
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> mutableTopLevelExtensionProperty(name: String, receiver: Class<T>): KMutableTopLevelExtensionProperty<T, *> {
|
fun <T> mutableTopLevelExtensionProperty(name: String, receiver: Class<T>): KMutableTopLevelExtensionProperty<T, *> =
|
||||||
return KMutableTopLevelExtensionPropertyImpl<T, Any?>(this, findPropertyDescriptor(name, receiver))
|
KMutableTopLevelExtensionPropertyImpl<T, Any?>(this, name, receiver)
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean =
|
override fun equals(other: Any?): Boolean =
|
||||||
other is KPackageImpl && jClass == other.jClass
|
other is KPackageImpl && jClass == other.jClass
|
||||||
|
|||||||
+9
-9
@@ -16,16 +16,14 @@
|
|||||||
|
|
||||||
package kotlin.reflect.jvm.internal
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import kotlin.reflect.IllegalPropertyAccessException
|
import kotlin.reflect.IllegalPropertyAccessException
|
||||||
import kotlin.reflect.KMutableTopLevelExtensionProperty
|
import kotlin.reflect.KMutableTopLevelExtensionProperty
|
||||||
import kotlin.reflect.KTopLevelExtensionProperty
|
import kotlin.reflect.KTopLevelExtensionProperty
|
||||||
|
|
||||||
open class KTopLevelExtensionPropertyImpl<T, out R>(
|
open class KTopLevelExtensionPropertyImpl<T, out R> : DescriptorBasedProperty, KTopLevelExtensionProperty<T, R>, KPropertyImpl<R> {
|
||||||
override val container: KPackageImpl,
|
constructor(container: KPackageImpl, name: String, receiverParameterClass: Class<T>) : super(container, name, receiverParameterClass)
|
||||||
computeDescriptor: () -> PropertyDescriptor
|
|
||||||
) : DescriptorBasedProperty(computeDescriptor), KTopLevelExtensionProperty<T, R>, KPropertyImpl<R> {
|
|
||||||
override val name: String get() = descriptor.getName().asString()
|
override val name: String get() = descriptor.getName().asString()
|
||||||
|
|
||||||
override val getter: Method get() = super<DescriptorBasedProperty>.getter!!
|
override val getter: Method get() = super<DescriptorBasedProperty>.getter!!
|
||||||
@@ -41,10 +39,12 @@ open class KTopLevelExtensionPropertyImpl<T, out R>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KMutableTopLevelExtensionPropertyImpl<T, R>(
|
class KMutableTopLevelExtensionPropertyImpl<T, R> :
|
||||||
container: KPackageImpl,
|
KTopLevelExtensionPropertyImpl<T, R>,
|
||||||
computeDescriptor: () -> PropertyDescriptor
|
KMutableTopLevelExtensionProperty<T, R>,
|
||||||
) : KTopLevelExtensionPropertyImpl<T, R>(container, computeDescriptor), KMutableTopLevelExtensionProperty<T, R>, KMutablePropertyImpl<R> {
|
KMutablePropertyImpl<R> {
|
||||||
|
constructor(container: KPackageImpl, name: String, receiverParameterClass: Class<T>) : super(container, name, receiverParameterClass)
|
||||||
|
|
||||||
override val setter: Method get() = super<KTopLevelExtensionPropertyImpl>.setter!!
|
override val setter: Method get() = super<KTopLevelExtensionPropertyImpl>.setter!!
|
||||||
|
|
||||||
override fun set(receiver: T, value: R) {
|
override fun set(receiver: T, value: R) {
|
||||||
|
|||||||
@@ -16,16 +16,14 @@
|
|||||||
|
|
||||||
package kotlin.reflect.jvm.internal
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import kotlin.reflect.IllegalPropertyAccessException
|
import kotlin.reflect.IllegalPropertyAccessException
|
||||||
import kotlin.reflect.KMutableTopLevelVariable
|
import kotlin.reflect.KMutableTopLevelVariable
|
||||||
import kotlin.reflect.KTopLevelVariable
|
import kotlin.reflect.KTopLevelVariable
|
||||||
|
|
||||||
open class KTopLevelVariableImpl<out R>(
|
open class KTopLevelVariableImpl<out R> : DescriptorBasedProperty, KTopLevelVariable<R>, KVariableImpl<R> {
|
||||||
override val container: KPackageImpl,
|
constructor(container: KPackageImpl, name: String) : super(container, name, null)
|
||||||
computeDescriptor: () -> PropertyDescriptor
|
|
||||||
) : DescriptorBasedProperty(computeDescriptor), KTopLevelVariable<R>, KVariableImpl<R> {
|
|
||||||
override val name: String get() = descriptor.getName().asString()
|
override val name: String get() = descriptor.getName().asString()
|
||||||
|
|
||||||
override val getter: Method get() = super<DescriptorBasedProperty>.getter!!
|
override val getter: Method get() = super<DescriptorBasedProperty>.getter!!
|
||||||
@@ -41,10 +39,9 @@ open class KTopLevelVariableImpl<out R>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KMutableTopLevelVariableImpl<R>(
|
class KMutableTopLevelVariableImpl<R> : KTopLevelVariableImpl<R>, KMutableTopLevelVariable<R>, KMutableVariableImpl<R> {
|
||||||
container: KPackageImpl,
|
constructor(container: KPackageImpl, name: String) : super(container, name)
|
||||||
computeDescriptor: () -> PropertyDescriptor
|
|
||||||
) : KTopLevelVariableImpl<R>(container, computeDescriptor), KMutableTopLevelVariable<R>, KMutableVariableImpl<R> {
|
|
||||||
override val setter: Method get() = super<KTopLevelVariableImpl>.setter!!
|
override val setter: Method get() = super<KTopLevelVariableImpl>.setter!!
|
||||||
|
|
||||||
override fun set(value: R) {
|
override fun set(value: R) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package kotlin.reflect.jvm.internal;
|
|||||||
|
|
||||||
import kotlin.Function0;
|
import kotlin.Function0;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@@ -67,8 +68,11 @@ import java.lang.ref.WeakReference;
|
|||||||
private final Function0<T> initializer;
|
private final Function0<T> initializer;
|
||||||
private SoftReference<Object> value = null;
|
private SoftReference<Object> value = null;
|
||||||
|
|
||||||
public LazySoftVal(@NotNull Function0<T> initializer) {
|
public LazySoftVal(@Nullable T initialValue, @NotNull Function0<T> initializer) {
|
||||||
this.initializer = initializer;
|
this.initializer = initializer;
|
||||||
|
if (initialValue != null) {
|
||||||
|
this.value = new SoftReference<Object>(escape(initialValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -120,9 +124,14 @@ import java.lang.ref.WeakReference;
|
|||||||
return new LazyVal<T>(initializer);
|
return new LazyVal<T>(initializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static <T> LazySoftVal<T> lazySoft(@Nullable T initialValue, @NotNull Function0<T> initializer) {
|
||||||
|
return new LazySoftVal<T>(initialValue, initializer);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static <T> LazySoftVal<T> lazySoft(@NotNull Function0<T> initializer) {
|
public static <T> LazySoftVal<T> lazySoft(@NotNull Function0<T> initializer) {
|
||||||
return new LazySoftVal<T>(initializer);
|
return lazySoft(null, initializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
Reference in New Issue
Block a user