Não há static
palavras-chave no Kotlin.
Qual é a melhor maneira de representar um static
método Java no Kotlin?
Não há static
palavras-chave no Kotlin.
Qual é a melhor maneira de representar um static
método Java no Kotlin?
Respostas:
Você coloca a função no "objeto complementar".
Portanto, o código java como este:
class Foo {
public static int a() { return 1; }
}
se tornará
class Foo {
companion object {
fun a() : Int = 1
}
}
Você pode usá-lo de dentro do código Kotlin como
Foo.a();
Mas a partir do código Java, você precisaria chamá-lo como
Foo.Companion.a();
(Que também funciona de dentro do Kotlin.)
Se você não gosta de especificar o Companion
bit, pode adicionar uma @JvmStatic
anotação ou nomear sua classe complementar.
Dos documentos :
Objetos complementares
Uma declaração de objeto dentro de uma classe pode ser marcada com a palavra-chave associada:
class MyClass { companion object Factory { fun create(): MyClass = MyClass() } }
Os membros do objeto complementar podem ser chamados usando simplesmente o nome da classe como qualificador:
val instance = MyClass.create()
...
No entanto, na JVM, é possível ter membros de objetos complementares gerados como métodos e campos estáticos reais, se você usar a
@JvmStatic
anotação. Consulte a seção de interoperabilidade Java para obter mais detalhes.
Adicionar a @JvmStatic
anotação se parece com isso
class Foo {
companion object {
@JvmStatic
fun a() : Int = 1;
}
}
e existirá como uma função estática Java real, acessível a partir de Java e Kotlin como Foo.a()
.
Se o Companion
nome for detestado , você também poderá fornecer um nome explícito para o objeto complementar, assim:
class Foo {
companion object Blah {
fun a() : Int = 1;
}
}
que permitirá que você o chame do Kotlin da mesma maneira, mas do tipo java Foo.Blah.a()
(que também funcionará no Kotlin).
fun a(): Int { return 1 }
ou até mesmofun a(): Int = 1
fun a() = 1
.
Factory
é o nome do objeto complementar - mas para que ele pode ser usado? Não tenho ideia, mas estava interessado, então criei uma pergunta dedicada a isso: stackoverflow.com/q/45853459/221955 .
A Docs recomenda solucionar a maioria das necessidades de funções estáticas com funções no nível do pacote . Eles são simplesmente declarados fora de uma classe em um arquivo de código-fonte. O pacote de um arquivo pode ser especificado no início de um arquivo com a palavra-chave package.
Declaração
package foo
fun bar() = {}
Uso
import foo.bar
alternativamente
import foo.*
Agora você pode chamar a função com:
bar()
ou se você não usar a palavra-chave import:
foo.bar()
Se você não especificar o pacote, a função estará acessível a partir da raiz.
Se você só tem experiência com java, isso pode parecer um pouco estranho. A razão é que o kotlin não é uma linguagem estritamente orientada a objetos. Você poderia dizer que ele suporta métodos fora das classes.
Editar: Eles editaram a documentação para não incluir mais a frase sobre a recomendação de funções no nível do pacote. Este é o original que foi mencionado acima.
class FooPackage
com todas as propriedades e funções de nível superior e encaminharia todas as suas referências para eles adequadamente. Mais informações de jetbrains.
bar()
, não importa o nome do arquivo, você pode nomeá-lo BarUtils.kt
ou qualquer outra coisa; então, como o texto diz, você importará com issoimport <package name>.bar
A. Antigo Caminho Java:
Declare a companion object
para incluir um método / variável estático
class Foo{
companion object {
fun foo() = println("Foo")
val bar ="bar"
}
}
Usar :
Foo.foo() // Outputs Foo
println(Foo.bar) // Outputs bar
B. Nova maneira de Kotlin
Declare diretamente no arquivo sem classe em um .kt
arquivo.
fun foo() = println("Foo")
val bar ="bar"
Use o methods/variables
com seus nomes . ( Depois de importá-los )
Usar :
foo() // Outputs Foo
println(bar) // Outputs bar
INSTANCE
palavra-chave, como esta:Foo.INSTANCE.sayFoo()
static CLASS
não apenas static methdos
. Porque com objetos complementares você ainda pode instanciar a classe pai.
val
não é estática, é equivalente static final
em Java
Use o objeto para representar o método val / var / para tornar estático. Você pode usar o objeto em vez da classe singleton também. Você pode usar complementar se quiser tornar estática dentro de uma classe
object Abc{
fun sum(a: Int, b: Int): Int = a + b
}
Se você precisar chamá-lo de Java:
int z = Abc.INSTANCE.sum(x,y);
No Kotlin, ignore o INSTANCE.
object objectName {
fun funName() {
}
}
Você precisa passar o objeto complementar para o método estático, porque o kotlin não possui uma palavra-chave estática - os membros do objeto complementar podem ser chamados usando simplesmente o nome da classe como qualificador:
package xxx
class ClassName {
companion object {
fun helloWord(str: String): String {
return stringValue
}
}
}
Existem 2 maneiras de aplicar estática no Kotlin
Primeiro faça um objeto complementar na classe
Por exemplo:
class Test{
companion object{
fun isCheck(a:Int):Boolean{
if(a==0) true else false
}
}
}
você pode chamar essa função como
Test.Companion.isCheck(2)
Outra maneira que podemos usar é criar uma classe de objeto
object Test{
fun isCheck(a:Int):Boolean{
if(a==0) true else false
}
}
Feliz codificação!
Test.Companion.isCheck(2)
), o IDE mostra avisos e diz Companion reference is redundant
. Pode ser reduzido Test.isCheck(2)
e a forma reduzida é mais próxima do equivalente a java.
Kotlin não tem nenhuma palavra-chave estática. Você usou isso para java
class AppHelper {
public static int getAge() {
return 30;
}
}
e para Kotlin
class AppHelper {
companion object {
fun getAge() : Int = 30
}
}
Chamada para Java
AppHelper.getAge();
Chamada para Kotlin
AppHelper.Companion.getAge();
Eu acho que está funcionando perfeitamente.
Gostaria de adicionar algo às respostas acima.
Sim, você pode definir funções nos arquivos de código-fonte (fora da classe). Mas é melhor se você definir funções estáticas dentro da classe usando o Objeto complementar, pois poderá adicionar mais funções estáticas aproveitando as extensões Kotlin .
class MyClass {
companion object {
//define static functions here
}
}
//Adding new static function
fun MyClass.Companion.newStaticFunction() {
// ...
}
E você pode chamar a função acima definida, como chamará qualquer função dentro do Objeto complementar.
Embora agora tenha pouco mais de 2 anos e tenha muitas respostas excelentes, estou vendo algumas outras maneiras de obter campos Kotlin "estáticos". Aqui está um guia de exemplo para a static
interoperabilidade Kotlin-Java :
Cenário 1: Criando um método estático no Kotlin para Java
Kotlin
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java package com.frybits class KotlinClass { companion object { //This annotation tells Java classes to treat this method as if it was a static to [KotlinClass] @JvmStatic fun foo(): Int = 1 //Without it, you would have to use [KotlinClass.Companion.bar()] to use this method. fun bar(): Int = 2 } }
Java
package com.frybits; class JavaClass { void someFunction() { println(KotlinClass.foo()); //Prints "1" println(KotlinClass.Companion.bar()); //Prints "2". This is the only way to use [bar()] in Java. println(KotlinClass.Companion.foo()); //To show that [Companion] is still the holder of the function [foo()] } //Because I'm way to lazy to keep typing [System.out], but I still want this to be compilable. void println(Object o) { System.out.println(o); } }
A resposta de Michael Anderson fornece mais profundidade do que isso e definitivamente deve ser referenciada para esse cenário.
O próximo cenário trata da criação de campos estáticos no Kotlin, para que o Java não precise continuar chamando KotlinClass.foo()
os casos em que você não deseja uma função estática.
Cenário 2: Criando uma variável estática no Kotlin para Java
Kotlin
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java package com.frybits class KotlinClass { companion object { //This annotation tells Kotlin to not generate the getter/setter functions in Java. Instead, this variable should be accessed directly //Also, this is similar to [@JvmStatic], in which it tells Java to treat this as a static variable to [KotlinClass]. @JvmField var foo: Int = 1 //If you want something akin to [final static], and the value is a primitive or a String, you can use the keyword [const] instead //No annotation is needed to make this a field of [KotlinClass]. If the declaration is a non-primitive/non-String, use @JvmField instead const val dog: Int = 1 //This will be treated as a member of the [Companion] object only. It generates the getter/setters for it. var bar: Int = 2 //We can still use [@JvmStatic] for 'var' variables, but it generates getter/setters as functions of KotlinClass //If we use 'val' instead, it only generates a getter function @JvmStatic var cat: Int = 9 } }
Java
package com.frybits; class JavaClass { void someFunction() { //Example using @JvmField println(KotlinClass.foo); //Prints "1" KotlinClass.foo = 3; //Example using 'const val' println(KotlinClass.dog); //Prints "1". Notice the lack of a getter function //Example of not using either @JvmField, @JvmStatic, or 'const val' println(KotlinClass.Companion.getBar()); //Prints "2" KotlinClass.Companion.setBar(3); //The setter for [bar] //Example of using @JvmStatic instead of @JvmField println(KotlinClass.getCat()); KotlinClass.setCat(0); } void println(Object o) { System.out.println(o); } }
Um dos grandes recursos do Kotlin é que você pode criar funções e variáveis de nível superior. Isso facilita a criação de listas "sem classe" de campos e funções constantes, que por sua vez podem ser usados como static
funções / campos em Java.
Cenário 3: Acessando campos e funções de nível superior no Kotlin a partir de Java
Kotlin
//In this example, the file name is "KSample.kt". If this annotation wasn't provided, all functions and fields would have to accessed //using the name [KSampleKt.foo()] to utilize them in Java. Make life easier for yourself, and name this something more simple @file:JvmName("KotlinUtils") package com.frybits //This can be called from Java as [KotlinUtils.TAG]. This is a final static variable const val TAG = "You're it!" //Since this is a top level variable and not part of a companion object, there's no need to annotate this as "static" to access in Java. //However, this can only be utilized using getter/setter functions var foo = 1 //This lets us use direct access now @JvmField var bar = 2 //Since this is calculated at runtime, it can't be a constant, but it is still a final static variable. Can't use "const" here. val GENERATED_VAL:Long = "123".toLong() //Again, no need for @JvmStatic, since this is not part of a companion object fun doSomethingAwesome() { println("Everything is awesome!") }
Java
package com.frybits; class JavaClass { void someFunction() { println(KotlinUtils.TAG); //Example of printing [TAG] //Example of not using @JvmField. println(KotlinUtils.getFoo()); //Prints "1" KotlinUtils.setFoo(3); //Example using @JvmField println(KotlinUtils.bar); //Prints "2". Notice the lack of a getter function KotlinUtils.bar = 3; //Since this is a top level variable, no need for annotations to use this //But it looks awkward without the @JvmField println(KotlinUtils.getGENERATED_VAL()); //This is how accessing a top level function looks like KotlinUtils.doSomethingAwesome(); } void println(Object o) { System.out.println(o); } }
Outra menção notável que pode ser usada em Java como campos "estáticos" são as object
classes Kotlin . Essas são classes singleton de parâmetro zero que são instanciadas preguiçosamente no primeiro uso. Mais informações sobre eles podem ser encontradas aqui: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
No entanto, para acessar o singleton, INSTANCE
é criado um objeto especial , que é tão complicado de lidar quanto Companion
é. Veja como usar anotações para dar uma static
sensação limpa em Java:
Cenário 4: Usando
object
ClassesKotlin
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java package com.frybits object KotlinClass { //No need for the 'class' keyword here. //Direct access to this variable const val foo: Int = 1 //Tells Java this can be accessed directly from [KotlinClass] @JvmStatic var cat: Int = 9 //Just a function that returns the class name @JvmStatic fun getCustomClassName(): String = this::class.java.simpleName + "boo!" //Getter/Setter access to this variable, but isn't accessible directly from [KotlinClass] var bar: Int = 2 fun someOtherFunction() = "What is 'INSTANCE'?" }
Java
package com.frybits; class JavaClass { void someFunction() { println(KotlinClass.foo); //Direct read of [foo] in [KotlinClass] singleton println(KotlinClass.getCat()); //Getter of [cat] KotlinClass.setCat(0); //Setter of [cat] println(KotlinClass.getCustomClassName()); //Example of using a function of this 'object' class println(KotlinClass.INSTANCE.getBar()); //This is what the singleton would look like without using annotations KotlinClass.INSTANCE.setBar(23); println(KotlinClass.INSTANCE.someOtherFunction()); //Accessing a function in the object class without using annotations } void println(Object o) { System.out.println(o); } }
Para abreviar, você pode usar o "objeto complementar" para entrar no mundo estático do Kotlin, como:
companion object {
const val TAG = "tHomeFragment"
fun newInstance() = HomeFragment()
}
e para criar um campo constante, use "const val" como no código. mas tente evitar as classes estáticas, pois isso dificulta os testes de unidade usando o Mockito !.
A conversão exata do método estático java em equivalente kotlin seria assim. Por exemplo, aqui a classe util possui um método estático que seria equivalente em java e kotlin. O uso de @JvmStatic é importante.
Código Java:
class Util{
public static String capitalize(String text){
return text.toUpperCase();}
}
Código Kotlin:
class Util {
companion object {
@JvmStatic
fun capitalize(text:String): String {
return text.toUpperCase()
}
}
}
Simplesmente você precisa criar um objeto complementar e colocar a função nele
class UtilClass {
companion object {
// @JvmStatic
fun repeatIt5Times(str: String): String = str.repeat(5)
}
}
Para invocar o método de uma classe kotlin:
class KotlinClass{
fun main(args : Array<String>) {
UtilClass.repeatIt5Times("Hello")
}
}
ou Usando importação
import Packagename.UtilClass.Companion.repeatIt5Times
class KotlinClass{
fun main(args : Array<String>) {
repeatIt5Times("Hello")
}
}
Para invocar o método de uma classe java:
class JavaClass{
public static void main(String [] args){
UtilClass.Companion.repeatIt5Times("Hello");
}
}
ou adicionando a anotação @JvmStatic ao método
class JavaClass{
public static void main(String [] args){
UtilClass.repeatIt5Times("Hello")
}
}
ou ambos, adicionando a anotação @JvmStatic ao método e fazendo a importação estática em java
import static Packagename.UtilClass.repeatIt5Times
class JavaClass{
public static void main(String [] args){
repeatIt5Times("Hello")
}
}
Para Java:
public class Constants {
public static final long MAX_CLICK_INTERVAL = 1000;}
Código Kotlin equivalente:
object Constants {
const val MAX_CLICK_INTERVAL: Long = 1000}
Portanto, para o equivalente aos métodos estáticos Java, existe uma classe de objeto no Kotlin.
Para Android, use uma sequência de uma única atividade para toda a atividade necessária. Assim como estática em java
public final static String TEA_NAME = "TEA_NAME";
Abordagem equivalente em Kotlin:
class MainActivity : AppCompatActivity() {
companion object {
const val TEA_NAME = "TEA_NAME"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Outra atividade em que o valor é necessário:
val teaName = MainActivity.TEA_NAME
exceto a resposta de Michael Anderson, eu tenho codificado com outras duas formas no meu projeto.
você pode colocar todas as variáveis em branco em uma classe. criou um arquivo kotlin chamado Const
object Const {
const val FIRST_NAME_1 = "just"
const val LAST_NAME_1 = "YuMu"
}
Você pode usá-lo no código kotlin e java
Log.d("stackoverflow", Const.FIRST_NAME_1)
Você pode usar a função de extensão do Kotlin,
criando um arquivo kotlin chamado Ext , abaixo do código é o código todo no arquivo Ext
package pro.just.yumu
/**
* Created by lpf on 2020-03-18.
*/
const val FIRST_NAME = "just"
const val LAST_NAME = "YuMu"
Você pode usá-lo no código kotlin
Log.d("stackoverflow", FIRST_NAME)
Você pode usá-lo no código java
Log.d("stackoverflow", ExtKt.FIRST_NAME);
Escreva-os diretamente nos arquivos.
Em Java (feio):
package xxx;
class XxxUtils {
public static final Yyy xxx(Xxx xxx) { return xxx.xxx(); }
}
Em Kotlin:
@file:JvmName("XxxUtils")
package xxx
fun xxx(xxx: Xxx): Yyy = xxx.xxx()
Esses dois pedaços de código são iguais após a compilação (mesmo o nome do arquivo compilado, file:JvmName
é usado para controlar o nome do arquivo compilado, que deve ser colocado antes da declaração do nome do pacote).
Usar @JVMStatic
anotação
companion object {
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
EditProfileFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
Vamos, você tem uma classe Estudante . E você tem um método estático getUniversityName () e um campo estático chamado totalStudent .
Você deve declarar o bloco de objeto complementar dentro da sua classe.
companion object {
// define static method & field here.
}
Então sua classe parece
class Student(var name: String, var city: String, var rollNumber: Double = 0.0) {
// use companion object structure
companion object {
// below method will work as static method
fun getUniversityName(): String = "MBSTU"
// below field will work as static field
var totalStudent = 30
}
}
Então você pode usar esses métodos e campos estáticos assim.
println("University : " + Student.getUniversityName() + ", Total Student: " + Student.totalStudent)
// Output:
// University : MBSTU, Total Student: 30
Não há palavra-chave estática no kotlin. O kotlin docs recomenda o uso de funções no nível do pacote se você quiser seguir o DRY. Crie um arquivo com extensão .kt e coloque seu método nele.
package p
fun m(){
//fun body
}
após a compilação, m terá uma assinatura de nulo final estático público
e
import p.m
☺
Você pode obter a funcionalidade estática no Kotlin por objetos complementares
Um objeto complementar não pode ser declarado fora da classe.
class MyClass{
companion object {
val staticField = "This is an example of static field Object Decleration"
fun getStaticFunction(): String {
return "This is example of static function for Object Decleration"
}
}
}
Os membros do objeto complementar podem ser chamados usando simplesmente o nome da classe como qualificador:
Resultado:
MyClass.staticField // This is an example of static field Object Decleration
MyClass.getStaticFunction() : // This is an example of static function for Object Decleration
Muitas pessoas mencionam objetos complementares, o que está correto. Mas, só para você saber, você também pode usar qualquer tipo de objeto (usando a palavra-chave objeto, não classe), ou seja,
object StringUtils {
fun toUpper(s: String) : String { ... }
}
Use-o como qualquer método estático em java:
StringUtils.toUpper("foobar")
Esse tipo de padrão é meio inútil no Kotlin, porém, um dos seus pontos fortes é que ele se livra da necessidade de classes preenchidas com métodos estáticos. É mais apropriado utilizar funções globais, de extensão e / ou locais, dependendo do seu caso de uso. Onde trabalho, geralmente definimos funções de extensão global em um arquivo simples e separado com a convenção de nomenclatura: [className] Extensions.kt, ou seja, FooExtensions.kt. Porém, mais tipicamente, escrevemos funções onde são necessárias dentro de sua classe ou objeto operacional.
Em Java, podemos escrever abaixo
class MyClass {
public static int myMethod() {
return 1;
}
}
Em Kotlin, podemos escrever abaixo
class MyClass {
companion object {
fun myMethod() : Int = 1
}
}
um companheiro é usado como estático no Kotlin.
O provedor de documentos kotlin oferece três maneiras de fazer isso, a primeira é definir a função no pacote, sem classe:
package com.example
fun f() = 1
o segundo é usar a anotação @JvmStatic:
package com.example
class A{
@JvmStatic
fun f() = 1
}
e o terceiro é usar o objeto complementar:
package com.example
clss A{
companion object{
fun f() = 1
}
}
Se você precisar que uma função ou propriedade seja vinculada a uma classe e não a instâncias dela, poderá declará-la dentro de um objeto complementar:
class Car(val horsepowers: Int) {
companion object Factory {
val cars = mutableListOf<Car>()
fun makeCar(horsepowers: Int): Car {
val car = Car(horsepowers)
cars.add(car)
return car
}
}
}
O objeto complementar é um singleton e seus membros podem ser acessados diretamente através do nome da classe que o contém
val car = Car.makeCar(150)
println(Car.Factory.cars.size)
Você pode usar objetos complementares - kotlinlang
Que pode ser mostrado criando primeiro essa interface
interface I<T> {
}
Então temos que fazer uma função dentro dessa interface:
fun SomeFunc(): T
Depois, precisamos de uma aula:
class SomeClass {}
dentro dessa classe, precisamos de um objeto complementar dentro dessa classe:
companion object : I<SomeClass> {}
dentro desse objeto complementar, precisamos dessa SomeFunc
função antiga , mas precisamos substituí-la:
override fun SomeFunc(): SomeClass = SomeClass()
Finalmente, abaixo de todo esse trabalho, precisamos de algo para alimentar essa função estática, precisamos de uma variável:
var e:I<SomeClass> = SomeClass()