Como verificar se uma variável "lateinit" foi inicializada?


428

Gostaria de saber se existe uma maneira de verificar se uma lateinitvariável foi inicializada. Por exemplo:

class Foo() {

    private lateinit var myFile: File

    fun bar(path: String?) {
        path?.let { myFile = File(it) }
    }

    fun bar2() {
        myFile.whateverMethod()
        // May crash since I don't know whether myFile has been initialized
    }
}

3
Talvez o que você precise é tornar a propriedade anulável (altere o tipo para File?) e verifique se ela é nula?
Marcin Koziński

1
Bem, eu realmente tentei isso e ele vai fazer o truque, no entanto eu vou ter que editar o allSeriesvar para seriesDir?.listFiles()?.map { it.name }?.toTypedArray(), o que não é muito "bonito"
Mathew Hany

1
Você pode fazer uma verificação nula simples e antiga e a conversão inteligente a tornará mais bonita. if (seriesDir != null) { allSeries = seriesDir.listFiles().map { it.name }.toTypedArray() }
Marcin Koziński

Por favor, considere aceitar mais atualizado resposta
misantropo

Respostas:


978

Há uma lateinitmelhoria no Kotlin 1.2 que permite verificar lateinitdiretamente o estado de inicialização da variável:

lateinit var file: File    

if (this::file.isInitialized) { ... }

Veja o comunicado no blog JetBrains ou a proposta KEEP .

ATUALIZAÇÃO: Kotlin 1.2 foi lançado. Você pode encontrar lateinitmelhorias aqui:


3
@ fer.marino: Bem, o Kotlin 1.2 realmente permite que você use lateinittambém para variáveis ​​locais, consulte kotlinlang.org/docs/reference/…
xsveda

9
Isso :: lateinitVar.isInitialized
vihkat 11/11

17
qual é o significado de ::antes file?
Malwinder Singh 16/05/19

5
@MalwinderSingh cria uma referência de membro ou uma referência de classe.
notGeek

5
No amor com Kotlin agora
Naveed Ahmad

46

Usando a .isInitializedpropriedade, é possível verificar o estado de inicialização de uma variável lateinit.

if(::file.isInitialized){
    //File is initialized
}else{
    //File is not initialized
}

Isso não fornece uma resposta para a pergunta. Para criticar ou solicitar esclarecimentos a um autor, deixe um comentário abaixo da postagem. - Do comentário
gforce301

2
@ gforce301 Definitivamente será usado para verificação.
Nikhil Katekhaye

39

Tente usá-lo e você receberá um UninitializedPropertyAccessExceptionse não for inicializado.

lateinité especificamente para casos em que os campos são inicializados após a construção, mas antes do uso real (um modelo usado pela maioria das estruturas de injeção). Se esse não for seu caso de usolateinit pode não ser a escolha certa.

EDIT: Com base no que você deseja fazer algo assim funcionaria melhor:

val chosenFile = SimpleObjectProperty<File?>
val button: Button

// Disables the button if chosenFile.get() is null
button.disableProperty.bind(chosenFile.isNull())

Eu tenho um aplicativo JavaFX e um botão que sempre será desativado, a menos que uma variável (que seja lateinit) tenha sido inicializada. Em outras palavras: desejo que o botão seja desativado enquanto a variável não tiver sido inicializada. Existe uma boa maneira de fazer isso?
Mathew Hany

@ MathewHany Como seria inicializado normalmente? Você pode querer olhar para propriedade getter / setters e uma SimpleBooleanProperty que você pode vincular a propriedade desativado do botão
Kiskae

1
Para ser mais específico, eu tenho um aplicativo simples que contém 4 botões, o primeiro botão abrirá uma caixa de diálogo DirectoryChooser e os outros 3 serão desativados quando o usuário escolher um diretório, e todos os outros botões estarão disponíveis para o usuário.
Mathew Hany

@ MathewHany, você pode implementar isso nativamente usando um SimpleObjectProperty para armazenar o arquivo escolhido e, em seguida, usando a isNullligação para desativar os outros botões.
Kiskae

1
kotlinlang.org/docs/reference/... xsveda resposta é mais atualizado
Serge

19

Você pode fazer isso facilmente:

::variableName.isInitialized

ou

this::variableName.isInitialized

Mas se você estiver dentro de um ouvinte ou classe interna, faça o seguinte:

this@YourClassName::variableName.isInitialized

Nota: As instruções acima funcionam bem se você as estiver gravando no mesmo arquivo (mesma classe ou classe interna) em que a variável é declarada, mas isso não funcionará se você desejar verificar a variável de outra classe (não a superclasse ou declarada em outro arquivo) , por exemplo:

class Test {
    lateinit var str:String
}

E para verificar se str é inicializado:

insira a descrição da imagem aqui

O que estamos fazendo aqui acessando o campo strde Testclasse em Test2classe. E obtemos um erro ao fazer o campo var não estar acessível neste momento. Verifique uma pergunta já levantada sobre isso.


12

A resposta aceita gera um erro do compilador. Kotlin 1.3+Eu tive que mencionar explicitamente a thispalavra - chave antes ::. Abaixo está o código de trabalho.

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}

Eu estou usando uma variável init local quando eu uso esta verificação que dá um erro como referência não resolvida
MarGin 08/01

3

Para verificar se a lateinit varfoi inicializado ou não use a .isInitializedna referência a essa propriedade:

if (foo::bar.isInitialized) {
    println(foo.bar)
}

Essa verificação está disponível apenas para as propriedades acessíveis lexicamente, ou seja, declaradas no mesmo tipo ou em um dos tipos externos, ou no nível superior no mesmo arquivo.


1
qual é o significado de ::antes bar?
Malwinder Singh 16/05/19

@Malwinder Singh "cria uma referência membro ou uma referência de classe" - Kotlin Doc
DMonkey

0
kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized

Bytecode diz ... blá blá ..

public final static synthetic access$getClientKeypair$p(Lcom/takharsh/ecdh/MainActivity;)Ljava/security/KeyPair;

`L0
LINENUMBER 11 L0
ALOAD 0
GETFIELD com/takharsh/ecdh/MainActivity.clientKeypair : Ljava/security/KeyPair;
DUP
IFNONNULL L1
LDC "clientKeypair"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.throwUninitializedPropertyAccessException (Ljava/lang/String;)V
    L1
ARETURN

L2 LOCALVARIABLE $ this Lcom / takharsh / ecdh / MainActivity; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 1

O Kotlin cria uma variável local extra da mesma instância e verifica se ela é nula ou não, se nula lança 'throwUninitializedPropertyAccessException' ou então retorna o objeto local. O bytecode acima explicado aqui Solução Como o kotlin 1.2, ele permite verificar se o lateinit var foi inicializado ou não está sendo usado.isInitialized

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.