我在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;?
答案 0 :(得分:2)
如何使BASE_URL
成为编译时常量?
interface GithubApi {
companion object {
const val BASE_URL = "https://api.github.com/"
}
}
在字节码级BASE_URL
是GithubApi
接口的静态字段。
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);
}