В static
Котлине нет ключевого слова.
Каков наилучший способ представления static
метода Java в Kotlin?
В static
Котлине нет ключевого слова.
Каков наилучший способ представления static
метода Java в Kotlin?
Ответы:
Вы помещаете функцию в «объект-компаньон».
Таким образом, код Java, как это:
class Foo {
public static int a() { return 1; }
}
станет
class Foo {
companion object {
fun a() : Int = 1
}
}
Затем вы можете использовать его внутри кода Kotlin как
Foo.a();
Но из Java-кода вам нужно будет назвать его как
Foo.Companion.a();
(Который также работает изнутри Kotlin.)
Если вам не нравится указывать Companion
бит, вы можете добавить @JvmStatic
аннотацию или назвать свой класс-компаньон.
Из документов :
Сопутствующие объекты
Объявление объекта внутри класса может быть помечено ключевым словом companion:
class MyClass { companion object Factory { fun create(): MyClass = MyClass() } }
Члены объекта-компаньона можно вызывать, используя просто имя класса в качестве квалификатора:
val instance = MyClass.create()
...
Однако в JVM вы можете создавать элементы сопутствующих объектов, сгенерированные как реальные статические методы и поля, если вы используете
@JvmStatic
аннотацию. Посмотрите раздел о совместимости Java для более подробной информации.
Добавление @JvmStatic
аннотации выглядит так
class Foo {
companion object {
@JvmStatic
fun a() : Int = 1;
}
}
и тогда она будет существовать как настоящая статическая функция Java, доступная как из Java, так и из Kotlin Foo.a()
.
Если оно просто не нравится Companion
имени, то вы также можете предоставить явное имя для объекта-компаньона, которое выглядит следующим образом:
class Foo {
companion object Blah {
fun a() : Int = 1;
}
}
что позволит вам вызывать его из Kotlin таким же образом, но из java как Foo.Blah.a()
(что также будет работать в Kotlin).
fun a(): Int { return 1 }
или дажеfun a(): Int = 1
fun a() = 1
.
Factory
- это имя объекта-компаньона, но для чего это можно использовать? Понятия не имею, но мне было интересно, поэтому я создал вопрос, посвященный этому: stackoverflow.com/q/45853459/221955 .
Docs рекомендует решить большинство потребностей статических функций с помощью функций уровня пакета . Они просто объявляются вне класса в файле исходного кода. Пакет файла может быть указан в начале файла с ключевым словом пакета.
декларация
package foo
fun bar() = {}
Применение
import foo.bar
альтернативно
import foo.*
Теперь вы можете вызвать функцию с помощью:
bar()
или если вы не используете ключевое слово import:
foo.bar()
Если вы не укажете пакет, функция будет доступна из корня.
Если у вас есть только опыт работы с Java, это может показаться немного странным. Причина в том, что kotlin не является строго объектно-ориентированным языком. Можно сказать, что он поддерживает методы вне классов.
Редактировать: они отредактировали документацию, чтобы больше не включать предложение о рекомендации функций уровня пакета. Это оригинал, о котором говорилось выше.
class FooPackage
со всеми свойствами и функциями верхнего уровня и соответствующим образом направит все ваши ссылки на них. Больше информации от jetbrains.
bar()
не имеет значения имя файла, вы можете назвать его BarUtils.kt
или как угодно, тогда как в тексте сказано, что вы импортируете его сimport <package name>.bar
А. Старый Путь Явы:
Объявите companion object
для включения статического метода / переменной
class Foo{
companion object {
fun foo() = println("Foo")
val bar ="bar"
}
}
Используйте:
Foo.foo() // Outputs Foo
println(Foo.bar) // Outputs bar
Б. Новый Котлинский путь
Объявите непосредственно в файле без класса в .kt
файле.
fun foo() = println("Foo")
val bar ="bar"
Используйте methods/variables
с их именами . ( После импорта их )
Используйте:
foo() // Outputs Foo
println(bar) // Outputs bar
INSTANCE
ключевое слово, например:Foo.INSTANCE.sayFoo()
static CLASS
не просто static methdos
. Потому что с сопутствующими объектами вы все еще можете создать экземпляр родительского класса.
val
не является статичным, это эквивалентно static final
в Java
Используйте объект для представления val / var / method, чтобы сделать статичным. Вы также можете использовать объект вместо синглтон-класса. Вы можете использовать компаньон, если вы хотите сделать статические внутри класса
object Abc{
fun sum(a: Int, b: Int): Int = a + b
}
Если вам нужно вызвать его из Java:
int z = Abc.INSTANCE.sum(x,y);
В Котлине игнорируйте МОМЕНТ.
object objectName {
fun funName() {
}
}
Вам необходимо передать сопутствующий объект для статического метода, потому что kotlin не имеет статического ключевого слова. Члены этого сопутствующего объекта можно вызвать, используя просто имя класса в качестве квалификатора:
package xxx
class ClassName {
companion object {
fun helloWord(str: String): String {
return stringValue
}
}
}
Есть два способа применения статики в Котлине
Сначала создайте объект-компаньон в классе
Например:
class Test{
companion object{
fun isCheck(a:Int):Boolean{
if(a==0) true else false
}
}
}
Вы можете вызвать эту функцию как
Test.Companion.isCheck(2)
Другой способ, которым мы можем воспользоваться, это сделать объектный класс
object Test{
fun isCheck(a:Int):Boolean{
if(a==0) true else false
}
}
Удачного кодирования!
Test.Companion.isCheck(2)
) IDE показывает предупреждения и сказать Companion reference is redundant
. Это может быть уменьшено до, Test.isCheck(2)
и уменьшенная форма более близка к эквиваленту Java.
У Kotlin нет статического ключевого слова. Вы использовали это для Java
class AppHelper {
public static int getAge() {
return 30;
}
}
и для котлина
class AppHelper {
companion object {
fun getAge() : Int = 30
}
}
Призыв к Java
AppHelper.getAge();
Позвони в Котлин
AppHelper.Companion.getAge();
Я думаю, что это работает отлично.
Я хотел бы добавить что-то к ответам выше.
Да, вы можете определять функции в файлах исходного кода (вне класса). Но будет лучше, если вы определите статические функции внутри класса, используя Companion Object, потому что вы можете добавить больше статических функций, используя расширения Kotlin .
class MyClass {
companion object {
//define static functions here
}
}
//Adding new static function
fun MyClass.Companion.newStaticFunction() {
// ...
}
И вы можете вызвать определенную выше функцию, как и любую другую функцию внутри объекта Companion.
Несмотря на то, что ему уже более 2 лет, и у него было много отличных ответов, я вижу, что отсутствуют некоторые другие способы получения «статических» полей Котлина. Вот пример руководства по static
взаимодействию Kotlin-Java :
Сценарий 1. Создание статического метода в Kotlin для Java
Котлин
@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 } }
Ява
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); } }
Ответ Майкла Андерсона дает больше глубины, чем это, и на него обязательно следует ссылаться для этого сценария.
Этот следующий сценарий обрабатывает создание статических полей в Kotlin, так что Java не нужно постоянно вызывать KotlinClass.foo()
в тех случаях, когда вам не нужна статическая функция.
Сценарий 2. Создание статической переменной в Kotlin для Java
Котлин
@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 } }
Ява
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); } }
Одной из замечательных особенностей Kotlin является то, что вы можете создавать функции и переменные верхнего уровня. Это позволяет создавать «бесклассовые» списки константных полей и функций, которые, в свою очередь, могут использоваться как static
функции / поля в Java.
Сценарий 3: Доступ к полям и функциям верхнего уровня в Kotlin из Java
Котлин
//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!") }
Ява
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); } }
Еще одно заметное упоминание, которое можно использовать в Java в качестве «статических» полей, - это object
классы Kotlin . Это одноэлементные классы с нулевым параметром, которые лениво создаются при первом использовании. Более подробную информацию о них можно найти здесь: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
Однако для доступа к синглтону создается специальный INSTANCE
объект, с которым так же сложно работать, как и Companion
раньше. Вот как использовать аннотации для придания этому static
Java ясности:
Сценарий 4. Использование
object
классовКотлин
@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'?" }
Ява
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); } }
Для краткости вы можете использовать «объект-компаньон», чтобы попасть в статический мир Kotlin, например:
companion object {
const val TAG = "tHomeFragment"
fun newInstance() = HomeFragment()
}
и для создания постоянного поля используйте «const val», как в коде. но старайтесь избегать статических классов, так как это затрудняет юнит-тестирование с использованием Mockito !.
Точное преобразование статического метода Java в эквивалент Котлина будет выглядеть следующим образом. Например, здесь класс util имеет один статический метод, который был бы эквивалентен как в java, так и в kotlin. Использование @JvmStatic важно.
Java-код:
class Util{
public static String capitalize(String text){
return text.toUpperCase();}
}
Код Котлина:
class Util {
companion object {
@JvmStatic
fun capitalize(text:String): String {
return text.toUpperCase()
}
}
}
Просто вам нужно создать сопутствующий объект и поместить в него функцию
class UtilClass {
companion object {
// @JvmStatic
fun repeatIt5Times(str: String): String = str.repeat(5)
}
}
Чтобы вызвать метод из класса kotlin:
class KotlinClass{
fun main(args : Array<String>) {
UtilClass.repeatIt5Times("Hello")
}
}
или используя импорт
import Packagename.UtilClass.Companion.repeatIt5Times
class KotlinClass{
fun main(args : Array<String>) {
repeatIt5Times("Hello")
}
}
Чтобы вызвать метод из класса Java:
class JavaClass{
public static void main(String [] args){
UtilClass.Companion.repeatIt5Times("Hello");
}
}
или добавив аннотацию @JvmStatic к методу
class JavaClass{
public static void main(String [] args){
UtilClass.repeatIt5Times("Hello")
}
}
или оба, добавив аннотацию @JvmStatic к методу и сделав статический импорт в Java
import static Packagename.UtilClass.repeatIt5Times
class JavaClass{
public static void main(String [] args){
repeatIt5Times("Hello")
}
}
Для Java:
public class Constants {
public static final long MAX_CLICK_INTERVAL = 1000;}
Эквивалентный код Котлина:
object Constants {
const val MAX_CLICK_INTERVAL: Long = 1000}
Так что для эквивалента Java статические методы - это объектный класс в Kotlin.
Для Android используется строка от одного действия до всего необходимого действия. Так же, как статические в Java
public final static String TEA_NAME = "TEA_NAME";
Эквивалентный подход в Котлине:
class MainActivity : AppCompatActivity() {
companion object {
const val TEA_NAME = "TEA_NAME"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Другой вид деятельности, где необходимо значение:
val teaName = MainActivity.TEA_NAME
кроме ответа Майкла Андерсона, у меня есть код с двумя другими способами в моем проекте.
Вы можете перевести все переменные в один класс. создал файл kotlin с именем Const
object Const {
const val FIRST_NAME_1 = "just"
const val LAST_NAME_1 = "YuMu"
}
Вы можете использовать его в кодлин и кодлин Java
Log.d("stackoverflow", Const.FIRST_NAME_1)
Вы можете использовать функцию расширения Kotlin,
создав файл Kotlin с именем Ext , ниже код весь код в файле Ext
package pro.just.yumu
/**
* Created by lpf on 2020-03-18.
*/
const val FIRST_NAME = "just"
const val LAST_NAME = "YuMu"
Вы можете использовать его в коде kotlin
Log.d("stackoverflow", FIRST_NAME)
Вы можете использовать его в коде Java
Log.d("stackoverflow", ExtKt.FIRST_NAME);
Запишите их прямо в файлы.
На Яве (некрасиво):
package xxx;
class XxxUtils {
public static final Yyy xxx(Xxx xxx) { return xxx.xxx(); }
}
В Котлине:
@file:JvmName("XxxUtils")
package xxx
fun xxx(xxx: Xxx): Yyy = xxx.xxx()
Эти две части кода сравниваются после компиляции (даже имя скомпилированного файла, file:JvmName
используется для управления именем скомпилированного файла, которое следует поместить непосредственно перед объявлением имени пакета).
Использовать @JVMStatic
аннотацию
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)
}
}
}
Пусть у вас есть ученик класса . И у вас есть один статический метод getUniversityName () и одно статическое поле с именем totalStudent .
Вы должны объявить блок сопутствующего объекта внутри вашего класса.
companion object {
// define static method & field here.
}
Тогда ваш класс выглядит
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
}
}
Затем вы можете использовать эти статические методы и поля, как этот способ.
println("University : " + Student.getUniversityName() + ", Total Student: " + Student.totalStudent)
// Output:
// University : MBSTU, Total Student: 30
В kotlin нет статического ключевого слова. kotlin docs рекомендует использовать функции уровня пакета, если вы хотите следовать DRY. Создайте файл с расширением .kt и поместите в него свой метод.
package p
fun m(){
//fun body
}
после компиляции m будет иметь подпись public static final void
а также
import p.m
☺
Вы можете достичь статической функциональности в Kotlin с помощью Companion Objects
Объект спутник не может быть объявлен вне класса.
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"
}
}
}
Члены объекта-компаньона можно вызывать, используя просто имя класса в качестве квалификатора:
Вывод:
MyClass.staticField // This is an example of static field Object Decleration
MyClass.getStaticFunction() : // This is an example of static function for Object Decleration
Многие люди упоминают сопутствующие объекты, и это правильно. Но, как вы знаете, вы также можете использовать любой объект (используя ключевое слово object, а не class), т.е.
object StringUtils {
fun toUpper(s: String) : String { ... }
}
Используйте его так же, как любой статический метод в Java:
StringUtils.toUpper("foobar")
Подобный шаблон бесполезен в Kotlin, однако, одна из его сильных сторон заключается в том, что он избавляется от необходимости в классах, заполненных статическими методами. Вместо этого более целесообразно использовать глобальные, расширенные и / или локальные функции, в зависимости от вашего варианта использования. Там, где я работаю, мы часто определяем глобальные функции расширения в отдельном плоском файле с соглашением об именах: [className] Extensions.kt, т.е. FooExtensions.kt. Но чаще мы пишем функции там, где они нужны, внутри их рабочего класса или объекта.
В Java мы можем написать ниже
class MyClass {
public static int myMethod() {
return 1;
}
}
В Kotlin мы можем написать ниже
class MyClass {
companion object {
fun myMethod() : Int = 1
}
}
спутник используется в качестве статического в Kotlin.
Поставщик документов kotlin может сделать это тремя способами. Первый - определить функцию в пакете без класса:
package com.example
fun f() = 1
вторая - использовать аннотацию @JvmStatic:
package com.example
class A{
@JvmStatic
fun f() = 1
}
и третий - использование объекта-компаньона:
package com.example
clss A{
companion object{
fun f() = 1
}
}
Если вам требуется привязать функцию или свойство к классу, а не к его экземплярам, вы можете объявить его внутри объекта-компаньона:
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
}
}
}
Сопутствующий объект является одиночным, и к его членам можно получить доступ напрямую через имя содержащего класса.
val car = Car.makeCar(150)
println(Car.Factory.cars.size)
Вы можете использовать Companion Objects - kotlinlang
Что это может быть показано, сначала создав этот интерфейс
interface I<T> {
}
Затем мы должны сделать функцию внутри этого интерфейса:
fun SomeFunc(): T
Тогда после, нам нужен класс:
class SomeClass {}
внутри этого класса нам нужен сопутствующий объект внутри этого класса:
companion object : I<SomeClass> {}
внутри этого объекта-компаньона нам нужна эта старая SomeFunc
функция, но нам нужно перегрузить ее:
override fun SomeFunc(): SomeClass = SomeClass()
Наконец, ниже всей этой работы, нам нужно что-то для питания этой статической функции, нам нужна переменная:
var e:I<SomeClass> = SomeClass()