如何访问kotlin反映的静态字段?

时间:2016-06-21 09:14:40

标签: kotlin

我在java中有这个抽象类:

abstract class AbsApiTestCase<T> {
    T mApi;

    @Before
    public void setUp() throws Exception {
        mApi = instanceApi((Class<T>) (
                  (ParameterizedType) getClass().getGenericSuperclass())
                     .getActualTypeArguments()[0]);
    }

    static <T> T instanceApi(Class<T> clazz) throws Exception {
        return new Retrofit.Builder()
            .baseUrl(clazz.getField("BASE_URL").get(null).toString())
            .addConverterFactory(GsonConverterFactory.create(
                    new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create()))
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .client(getClient())
            .build().create(clazz);

    }
    // some code
}

api看起来像这样:

public interface GithubApi {
    String BASE_URL = "https://api.github.com/";
    // some code
}

可以像这样使用:

public class GithubApiTest extends AbsApiTestCase<GithubApi> {
    // some code
}

但是当我将代码转换为kotlin时,静态字段BASE_URL看起来像这样:

interface GithubApi {
    companion object {
        val BASE_URL = "https://api.github.com/"
    }
    // some code
}

并且无法像上面那样访问BASE_URL。我发现有一个@JvmField注释,但Android工作室说JvmField cannot be applied to a property defined in companion object of interface

有没有办法访问这个&#34;静态字段&#34;?

4 个答案:

答案 0 :(得分:2)

如何使BASE_URL成为编译时常量?

interface GithubApi {
    companion object {
        const val BASE_URL = "https://api.github.com/"
    }
}

在字节码级BASE_URLGithubApi接口的静态字段。

public interface GithubApi {
  public static final GithubApi$Companion Companion;

  public static final java.lang.String BASE_URL;

  static {};
    Code:
       0: new           #26                 // class GithubApi$Companion
       3: dup
       4: aconst_null
       5: invokespecial #30                 // Method GithubApi$Companion."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
       8: putstatic     #32                 // Field Companion:LGithubApi$Companion;
      11: return
}

答案 1 :(得分:1)

@JvmStatic注释将使属性的支持字段成为静态字段。也就是说,如果注释应用于伴随对象中的属性,则将在封闭类中创建新的静态字段。

请注意,Kotlin实际上没有静态概念,并且这个注释仅用于JVM语言的可访问性。

答案 2 :(得分:1)

我看到了四个基本选项:

1)将属性提取到对象中(或不是伴侣):

object GithubApiUrls {
    val BASE_URL = "https://api.github.com/"
}

2)制作包级属性:

package myProgram

val BASE_URL = "https://api.github.com/"

3)如果你需要继承(不知道TBH的用途),请使用类而不是接口:

open class GithubApi {
    val BASE_URL = "https://api.github.com/"
}

4)用接口中的方法替换字段(可以覆盖):

interface GithubApi {
    fun BaseUrl() = "https://api.github.com/"
}

答案 3 :(得分:1)

根本不建议在接口中放置常量。它引入了太多的复杂性而没有实际的价值增益。

尝试从实现接口的实际类中解除保存常量的类。

public class AllUrls {
    public static final String GITHUB_URL = "https://api.github.com/";
}

那将成为

object AllUrls {
    val GITHUB_URL = "https://api.github.com/"
}

并使用它

 static <T> T instanceApi(Class<T> clazz) throws Exception {
    return new Retrofit.Builder()
        .baseUrl(AllUrls.INSTANCE.getGITHUB_URL())
        .addConverterFactory(GsonConverterFactory.create(
                new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create()))
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .client(getClient())
        .build().create(clazz);

}