Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

186
Visualizações
Using Kotlin Value classes in Java

We have two projects, and the kotlin one publishes a package that's imported by java.

In kotlin, is a value class like

@JvmInline
value class CountryId(private val id: UUID) {
    override fun toString(): String = id.toString()
    companion object { fun empty(): CountryId = CountryId(EMPTY_UUID) }
}

In java, we can't see a constructor, or actually instantiate this class. I have also tried creating a factory in Kotlin to create them

class IdentifierFactory 
{
    companion object {
        fun buildString(): String {
            return "hello"
        }

        fun buildCountry(): CountryId {
            return CountryId.empty()
        }
    }
}

In java, I can call IdentifierFactory.Companion.buildString() and it will work, but IdentifierFactory.Companion.buildCountry() doesn't even exist.

Is Java really this awful with Value classes?

ps. I've attempted with @JvmStatic as well, with no success

pps. If I decompile the kotlin bytecode from the java side, and get a CountryId.decompiled.java, this is what the constructor looks like

// $FF: synthetic method
private CountryId(UUID id) {
    Intrinsics.checkNotNullParameter(id, "id");
    super();
    this.id = id;
}

ppps. Kotlin 1.5.21 and Java 12

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Is Java really this awful with Value classes?

Value classes are a Kotlin feature. They are basically sugar to allow more type safety (in Kotlin!) while reducing allocations by unboxing the inner value. The fact that the CountryId class exists in the bytecode is mostly because some instances need to be boxed in some cases (when used as a generic type, or a supertype, or a nullable type - in short, somewhat like primitives). But technically it's not really meant to be used from the Java side of things.

In java, I can call IdentifierFactory.Companion.buildString() and it will work, but IdentifierFactory.Companion.buildCountry() doesn't even exist.

The functions with value classes in their signature are intentionally not visible from Java by default, in order to avoid strange issues with overloads in Java. This is accomplished via name mangling. You can override the name for the Java method by using the @JvmName annotation on the factory function on Kotlin side to make it visible from Java:

@JvmName("buildCountryUUID") // prevents mangling due to value class
fun buildCountry(): CountryId {
    return CountryId.empty()
}

Then it is accessible on Java side and returns a UUID (the inlined value):

UUID uuid = IdentifierFactory.Companion.buildCountryUUID();

ideally, I'd just like the constructor to work and not use the factory

I realized from the comments that you were after creating actual CountryId instances from Java. Using the CountryId constructor from Java works fine for me:

CountryId country = new CountryId(UUID.randomUUID());

But I am not sure how this is possible, given that the generated constructor is private in the bytecode...

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda