如何在kotlin中使用reflect访问静态字段?
我有一个java抽象类:如何在kotlin中使用reflect访问静态字段?,kotlin,Kotlin,我有一个java抽象类: abstract class AbsApiTestCase<T> { T mApi; @Before public void setUp() throws Exception { mApi = instanceApi((Class<T>) ( (ParameterizedType) getClass().getGenericSuperclass())
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
}
它可以这样使用:
public interface GithubApi {
String BASE_URL = "https://api.github.com/";
// some code
}
public class GithubApiTest extends AbsApiTestCase<GithubApi> {
// some code
}
interface GithubApi {
companion object {
val BASE_URL = "https://api.github.com/"
}
// some code
}
和BASE\u URL
不能像上面那样访问。我发现有一个@JvmField
注释,但是Android studio说JvmField不能应用于接口的伴随对象中定义的属性
有办法访问此“静态字段”吗?JvmStatic
注释将使属性的支持字段成为静态字段。也就是说,如果注释应用于伴生对象中的属性,则将在封闭类中创建一个新的静态字段
请注意,Kotlin实际上没有静态的概念,并且此注释仅用于跨JVM语言的可访问性。将
BASE\u URL
设为编译时常量如何
interface GithubApi {
companion object {
const val BASE_URL = "https://api.github.com/"
}
}
在字节码级别BASE\u 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
}
public class AllUrls {
public static final String GITHUB_URL = "https://api.github.com/";
}
公共接口GithubApi{
公共静态最终GithubApi$Companion Companion;
public static final java.lang.String BASE_URL;
静态{};
代码:
0:new#26//class GithubApi$Companion
3:dup
4:aconst_null
5:invokespecial#30//方法GithubApi$Companion.“:(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
8:putstatic#32//字段同伴:LGithubApi$Companion;
11:返回
}
我看到了四个基本选项: 1) 将属性提取到对象中(是否伴随): 2) 创建包级属性:
package myProgram
val BASE_URL = "https://api.github.com/"
3) 如果需要继承,请使用类而不是接口(不知道继承的目的是什么,待定):
4) 用接口中的方法替换字段(可以重写):
根本不建议在接口中放置常量。它引入了太多的复杂性,而没有真正的价值增益 尝试将保持常量的类与实现接口的实际类分离
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
}
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);
}
静态T instanceApi(类clazz)引发异常{
返回新的改装.Builder()
.baseUrl(AllUrls.INSTANCE.getGITHUB_URL())
.addConverterFactory(GsonConverterFactory.create(
新的GsonBuilder().setDateFormat(“yyyy-MM-dd HH:MM:ss”).create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(getClient())
.build().create(clazz);
}
您计划如何使用GithubApi
?你需要从Java访问吗?@voddan不,我只需要一个url值来创建实例,但我在KClass中找不到它。members
我也尝试了@JvmStatic
,IDE说只有类的命名对象和伴生对象中的函数可以用“@JvmStatic”注释。
中使用了Api接口,它必须是一个接口。如果我用一个函数替换它,要访问它,我需要一个实例,要创建一个实例,我需要url值,这看起来像是一个循环。我的观点是,您不需要将静态信息放入接口中。URL可能存储在接口附近的任何位置(选项1和2)。没错,我可以将其放在映射中,并使用类名访问它(GithubApi不是唯一的这样的接口,它甚至不是我代码中的真实接口,它只是一个示例),但我发布的这些代码只是用于测试用例,代码更少,性能也不那么重要,我确实在真实代码中使用了reformation.Builder().baseUrl(GithubApi.BASE\u URL)
。那么,也许一个伴生对象就是使用AllUrls.INSTANCE.getGITHUB\u URL()
的方法,现在这个方法只能用于GithubApi,这样我们甚至不需要clazz
。我不认为在接口中放入常量是错误的,在android.os.PARCELABLE中有一个整数常量PARCELABLE\u WRITE\u RETURN\u VALUE
。
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);
}