静态编程语言中Java静态方法的等价物是什么?

静态编程语言中没有static关键字。

用静态编程语言表示staticJava方法的最佳方法是什么?

458593 次浏览

您将函数放在“伴随对象”中。

所以java代码是这样的:

class Foo {public static int a() { return 1; }}

将成为

class Foo {companion object {fun a() : Int = 1}}

然后,您可以从静态编程语言代码中使用它

Foo.a();

但是在Java代码中,你需要称它为

Foo.Companion.a();

(这也适用于静态编程语言。

如果您不喜欢指定Companion位,您可以添加@JvmStatic注释或命名您的同伴类。

文档

伴生物体

类中的对象声明可以用companion标记关键字:

class MyClass {companion object Factory {fun create(): MyClass = MyClass()}}

可以通过简单地使用类来调用同伴对象的成员名称作为限定符:

val instance = MyClass.create()

但是,在JVM上,您可以生成同伴对象的成员作为真正的静态方法和字段,如果您使用@JvmStatic注释。有关更多详细信息,请参阅Java互操作性部分。

添加@JvmStatic注释看起来像这样

class Foo {companion object {@JvmStaticfun a() : Int = 1;}}

然后它将作为一个实Java静态函数存在,可从Java和静态编程语言Foo.a().

如果只是不喜欢Companion的名字,那么你也可以为同伴对象提供一个显式名称,如下所示:

class Foo {companion object Blah {fun a() : Int = 1;}}

这将允许您以相同的方式从静态编程语言调用它,但是从java像Foo.Blah.a()(这也将工作在静态编程语言)。

a.Java方式:

  1. 声明companion object以包含静态方法变量

    class Foo{companion object {fun foo() = println("Foo")val bar ="bar"}}
  2. Use :

    Foo.foo()        // Outputs Fooprintln(Foo.bar) // Outputs bar


B. New Kotlin way

  1. Declare directly on file without class on a .kt file.

    fun foo() = println("Foo")val bar ="bar"
  2. Use the methods/variables with their names. (After importing them)

    Use :

    foo()        // Outputs Fooprintln(bar) // Outputs bar

文档建议使用包级函数解决静态函数的大部分需求。它们只需在源代码文件中的类之外声明。文件的包可以在文件的开头使用包关键字指定。

宣言

package foo
fun bar() = {}

用法

import foo.bar

或者

import foo.*

您现在可以使用以下命令调用该函数:

bar()

或者如果您不使用导入关键字:

foo.bar()

如果您不指定包,则可以从根访问该函数。

如果你只有java的经验,这可能看起来有点奇怪。原因是kotlin不是严格的面向对象语言。你可以说它支持类之外的方法。

编辑:他们已经编辑了留档,不再包含关于推荐包级别功能的句子。这个是上面提到的原始版本。

将它们直接写入文件。

Java(丑陋):

package xxx;class XxxUtils {public static final Yyy xxx(Xxx xxx) { return xxx.xxx(); }}

静态编程语言:

@file:JvmName("XxxUtils")package xxxfun xxx(xxx: Xxx): Yyy = xxx.xxx()

这两段代码在编译后相等(即使是编译后的文件名,file:JvmName也用于控制编译后的文件名,应该放在包名声明之前)。

您需要为静态方法传递伴侣对象,因为kotlin没有静态关键字-可以通过简单地使用类名作为限定符来调用伴侣对象的成员:

package xxxclass ClassName {companion object {fun helloWord(str: String): String {return stringValue}}}

使用对象表示val/var/方法来制作静态。您也可以使用对象而不是单例类。如果您想在类内制作静态,您可以使用同伴

object Abc{fun sum(a: Int, b: Int): Int = a + b}

如果您需要从Java调用它:

int z = Abc.INSTANCE.sum(x,y);

在静态编程语言中,忽略实例。

你只需要创建一个伴随对象并将函数放入其中

  class UtilClass {companion object {//        @JvmStaticfun repeatIt5Times(str: String): String = str.repeat(5)}}

要从kotlin类调用方法:

class KotlinClass{fun main(args : Array<String>) {UtilClass.repeatIt5Times("Hello")}}

或使用导入

import Packagename.UtilClass.Companion.repeatIt5Timesclass 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.repeatIt5Timesclass JavaClass{public static void main(String [] args){repeatIt5Times("Hello")}}

静态编程语言没有任何静态关键字。您可以使用下面的代码Java和静态编程语言

 object AppHelper {@JvmStaticfun getAge() : Int = 30}

呼吁Java类

AppHelper.getAge();

静态编程语言课程

AppHelper.getAge()

对我来说很完美谢谢

让,你有一个类学生。你有一个静态方法获取校名和一个静态字段称为总计学生

您应该在类中声明伴生物体块。

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

您可以通过伴生物体实现静态编程语言的静态功能

  • 同伴添加到对象声明允许添加静态功能到一个对象,即使实际的静态静态编程语言中不存在概念。
  • 伴生物体也可以访问类的所有成员,包括私有构造函数。
  • 当类被实例化时,伴生物体被初始化。
  • A伴生物体不能在类外声明。

    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

所有静态成员和函数都应该在同伴块内

  companion object {@JvmStaticfun main(args: Array<String>) {}
fun staticMethod() {}}

这也为我工作

object Bell {@JvmStaticfun ring() { }}

静态编程语言

Bell.ring()

从Java

Bell.ring()

我想在上面的回答中补充一点。

是的,您可以在源代码文件(类外)中定义函数。但如果您在类内使用伴生对象定义静态函数会更好,因为您可以通过利用静态编程语言扩展添加更多静态函数。

class MyClass {companion object {//define static functions here}}
//Adding new static functionfun MyClass.Companion.newStaticFunction() {// ...}

你可以调用上面定义的函数,就像你将调用伴侣对象中的任何函数一样。

object objectName {fun funName() {
}}

有两种方法可以在静态编程语言中应用静态

首先在class下创建一个伴随对象

对于前:

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}}

编码快乐!

使用@JVMStatic注释

companion object {
// TODO: Rename and change types and number of parameters@JvmStaticfun newInstance(param1: String, param2: String) =EditProfileFragment().apply {arguments = Bundle().apply {putString(ARG_PARAM1, param1)putString(ARG_PARAM2, param2)}}}

很多人提到同伴对象,这是正确的。但是,正如你所知道的,你也可以使用任何类型的对象(使用对象关键字,而不是类),即,

object StringUtils {fun toUpper(s: String) : String { ... }}

就像java中的任何静态方法一样使用它:

StringUtils.toUpper("foobar")

然而,这种模式在静态编程语言中有点无用,它的优点之一是它摆脱了对充满静态方法的类的需求。根据你的用例,使用全局、扩展和/或局部函数更合适。在我工作的地方,我们经常在一个单独的平面文件中定义全局扩展函数,命名约定:[class Name]Extensions.kt即FooExtensions.kt.但更典型的是,我们在操作类或对象中编写需要它们的函数。

您可以使用伴侣对象-kotlinlang

它可以通过首先创建该接口来显示

interface I<T> {
}

然后我们必须在该接口中创建一个函数:

fun SomeFunc(): T

然后,我们需要一个类:

class SomeClass {}

在该类中,我们需要该类中的一个配套Object:

companion object : I<SomeClass> {}

在那个伴侣对象中,我们需要那个旧的SomeFunc函数,但我们需要覆盖它:

override fun SomeFunc(): SomeClass = SomeClass()

最后,在所有这些工作的下面,我们需要一些东西来支持静态函数,我们需要一个变量:

var e:I<SomeClass> = SomeClass()

java静态方法到kotlin等效的确切转换如下。例如,这里的util类有一个静态方法,它在java和kotlin中都是等效的。@陈志立的使用很重要。

Java代码:

    class Util{public static String capitalize(String text){return text.toUpperCase();}}

静态编程语言代码:

    class Util {companion object {@JvmStaticfun capitalize(text:String): String {return text.toUpperCase()}}}

尽管这已经有2年多的历史了,并且有很多很好的答案,但我看到一些其他获得“静态”静态编程语言字段的方法缺失了。

场景1:用静态编程语言为Java创建静态方法

静态编程语言

@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);}}

迈克尔·安德森的回答比这更有深度,绝对应该参考这个场景。


下一个场景处理使用静态编程语言创建静态字段,以便Java不必在不需要静态函数的情况下继续调用KotlinClass.foo()

场景2:用静态编程语言为Java创建静态变量

静态编程语言

@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);}}

静态编程语言的一大特点是可以创建顶级函数和变量,这使得创建常量字段和函数的“无类”列表变得非常重要,这些列表又可以用作Java中的static函数/字段。

场景3:从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 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);}}

另一个值得注意的可用于Java“静态”字段的是静态编程语言object类。这些是零参数单例类,在第一次使用时延迟实例化。有关它们的更多信息可以在这里找到:https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations

但是,要访问单例,需要创建一个特殊的INSTANCE对象,处理起来和Companion一样麻烦。以下是如何使用注释在Java中赋予它干净的static感觉:

场景4:使用object

静态编程语言

@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);}}

Java:

public class Constants {public static final long MAX_CLICK_INTERVAL = 1000;}

等效静态编程语言代码:

object  Constants {const val MAX_CLICK_INTERVAL: Long = 1000}

因此Java静态方法的等价物是静态编程语言中的对象类。

简而言之,您可以使用"伴生对象"进入静态编程语言静态世界,例如:

  companion object {const val TAG = "tHomeFragment"fun newInstance() = HomeFragment()}

并在代码中使用"const val"来创建常量字段。但是尽量避免使用静态类,因为它在使用Mockito进行单元测试时会遇到困难!

在Java,我们可以用下面的方式写

class MyClass {public static int myMethod() {return 1;}}

在静态编程语言中,我们可以这样写

class MyClass {companion object {fun myMethod() : Int = 1}}

同伴在静态编程语言中用作静态。

kotlin文档提供者有三种方法可以做到这一点,第一个是在包中定义函数,没有类:

package com.example
fun f() = 1

第二个是use@JvmStatic注释:

package com.example
class A{@JvmStaticfun f() = 1}

第三个是use伴侣对象:

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)

kotlin中没有静态关键字。如果你想遵循DRY,kotlin文档建议使用包级函数。创建一个扩展名为. kt的文件并将您的方法放入其中。

package pfun m(){//fun body}

编译后m将有公共静态最终无效的签名

import p.m

对于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

除了Michael Anderson的回答,我在我的项目中使用了其他两种方式进行编码。

第一:

您可以将所有变量白色化到一个类。创建了一个名为Const

的kotlin文件
object Const {const val FIRST_NAME_1 = "just"const val LAST_NAME_1 = "YuMu"}

您可以在kotlin和java代码中使用它

 Log.d("stackoverflow", Const.FIRST_NAME_1)

第二:

您可以使用静态编程语言的扩展函数
创建了一个名为Ext的kotlin文件,下面的代码是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);

顶级/companion object用于static属性

顶级

当属性与类有些相关时,请在类声明之前将它们定义为顶级属性:

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) { }}}

用法:

val userProfile = User.profileFor("34")

这类似于Java中的static方法。

顶级函数通常更习惯于静态编程语言。在companion object中定义函数的更好理由是当您使用interface扩展companion object时。单例部分显示了一个示例。


static类的嵌套类

当具有相关功能的类属于一起时,可以通过嵌套将它们分组在一起:

class User(val id: String, val name: String) {class UserAccess : UserDao {override fun add(user: User) { }override fun remove(id: String) { }}}

这相当于Java中的static嵌套类。这里的UserAccess类实现了interfaceUserDao

用法:

fun main() {val john = User("34", "John")val userAccess = User.UserAccess()userAccess.add(john)}

Singletonobject forstatic INSTANCE

顶级

当你只想要一个类的单个对象时,你不再需要像Java那样在类中创建static INSTANCE。只需使用顶级object声明:

object UserAccess : UserDao {override fun add(user: User) { }override fun remove(id: String) { }}

还要注意在单例中扩展interfaceclass是多么容易。

上面的代码,在引擎盖下,在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) { }}}

通过这种方式,您可以获得更优雅的命名:User.add(john)。此外,您清楚地表明此单例仅用作User类的实用程序。如果您想要多个单例或函数/属性组,您也可以在类内使用object而不使用companion关键字。


companion objectstatic工厂

Koltin中的工厂函数是使用companion object创建的。当您想要提供多种方法来创建对象时,工厂函数很有用,其中对象构造过程很复杂,或者多个构造函数表达力不够。

例如,以下代码片段中的newInstance()工厂函数通过自动生成id来创建用户:

class User private constructor(val id: Long, val name: String) {companion object {private var currentId = 0L;fun newInstance(name: String) = User(currentId++, name)}}

这相当于Java中的static工厂方法。

constructor保留private,但companion object可以访问constructor

在上面的代码中,保证了下一代id的一致性,因为companion object是单例,只有一个对象会跟踪id,不会有任何重复的id。

还要注意,伴随对象可以具有属性(在本例中为currentId)来表示状态。

用法:

val john = User.newInstance("John")

@JvmStaticJava互操作性

静态编程语言中不存在Java的静态概念。companion object是真正的class的实例,称为Companion。因此,当您从Java调用静态编程语言代码时,Companion类的对象首先在幕后实例化。您需要使用Java中的Companion对象调用该函数:

Profile userProfile = User.Companion.profileFor("34");

对于惯用的Java命名和较少的冗长,对该函数或属性使用@JvmStatic注释:

companion object {@JvmStaticfun profileFor(userId: String): Profile { }}

@JvmStatic注释创建了getProfileFor()函数的一个单独的纯static副本。现在您可以从Java使用常规语法:

Profile userProfile = User.profileFor("34");

就是这样!希望这些例子对你的项目有用。

只需使用此方法

object Foo{fun foo() = println("Foo")val bar ="bar"}
Foo.INSTANCE.foo()