companion object {// define static method & field here.}
那么你的班级看起来
class Student(var name: String, var city: String, var rollNumber: Double = 0.0) {
// use companion object structurecompanion object {
// below method will work as static methodfun getUniversityName(): String = "MBSTU"
// below field will work as static fieldvar totalStudent = 30}}
然后您可以像这样使用这些静态方法和字段。
println("University : " + Student.getUniversityName() + ", Total Student: " + Student.totalStudent)// Output:// University : MBSTU, Total Student: 30
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"}
}}
Members of the companion object can be called by using simply the class name as the qualifier:
Output:
MyClass.staticField // This is an example of static field Object Decleration
MyClass.getStaticFunction() : // This is an example of static function for Object Decleration
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Javapackage com.frybits
class KotlinClass {companion object {
//This annotation tells Java classes to treat this method as if it was a static to [KotlinClass]@JvmStaticfun 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);}}
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Javapackage 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].@JvmFieldvar 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 insteadconst 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@JvmStaticvar cat: Int = 9}}
Java
package com.frybits;
class JavaClass {
void someFunction() {//Example using @JvmFieldprintln(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 @JvmFieldprintln(KotlinClass.getCat());KotlinClass.setCat(0);}
void println(Object o) {System.out.println(o);}}
//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 variableconst 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 functionsvar foo = 1
//This lets us use direct access now@JvmFieldvar 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 objectfun 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 @JvmFieldprintln(KotlinUtils.bar); //Prints "2". Notice the lack of a getter functionKotlinUtils.bar = 3;
//Since this is a top level variable, no need for annotations to use this//But it looks awkward without the @JvmFieldprintln(KotlinUtils.getGENERATED_VAL());
//This is how accessing a top level function looks likeKotlinUtils.doSomethingAwesome();}
void println(Object o) {System.out.println(o);}}
@file:JvmName("KotlinClass")
//This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Javapackage com.frybits
object KotlinClass { //No need for the 'class' keyword here.
//Direct access to this variableconst val foo: Int = 1
//Tells Java this can be accessed directly from [KotlinClass]@JvmStaticvar cat: Int = 9
//Just a function that returns the class name@JvmStaticfun 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 annotationsKotlinClass.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);}}
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)
class MainActivity : AppCompatActivity() {companion object {const val TEA_NAME = "TEA_NAME"}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)}}
const val MAX_ATTEMPTS = 3private const val DEFAULT_NAME = "Guest"private const val MIN_AGE = 16
data class User(val id: String, val name: String = DEFAULT_NAME)
这类似于Java中的static属性。
当属性完全独立于任何类时,您可以在没有类的单独文件中将它们定义为顶级。
companion object
当属性与类密切相关并且仅在该类中使用时,请在companion object中定义它们:
data class User(val id: String, val name: String = DEFAULT_NAME) {companion object {const val DEFAULT_NAME = "Guest"const val MIN_AGE = 16}}
顶级/companion object用于static方法
顶级
与上面的属性类似,当函数与类有点相关时,将它们定义在类的正上方:
fun getAllUsers() { }
fun getProfileFor(userId: String) { }
data class User(val id: String, val name: String)
用法:
val userList = getAllUsers()
companion object
当函数与类密切相关时,在companion object中定义它们:
data class User(val id: String, val name: String) {
companion object {
fun getAll() { }
fun profileFor(userId: String) { }}}
object UserAccess : UserDao {override fun add(user: User) { }override fun remove(id: String) { }}
还要注意在单例中扩展interface或class是多么容易。
上面的代码,在引擎盖下,在Java中产生以下static INSTANCE单例模式(简化):
public final class UserAccess implements UserDao {public static final UserAccess INSTANCE;
public void add(User user) { }
public void remove(String id) { }
private UserAccess() { }
static { INSTANCE = new UserAccess();}}
companion object
当单例与类密切相关时,使用companion object:
data class User(val id: String, val name: String) {companion object : UserDao {override fun add(user: User) { }override fun remove(id: String) { }}}