2016-06-21 19 views
2

我有这个抽象类中的java:如何访问反映kotlin的静态字段?

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 studio说JvmField cannot be applied to a property defined in companion object of interface

有没有办法访问这个“静态字段”?

+0

你如何计划使用'GithubApi'?你需要从Java访问吗? – voddan

+0

@voddan不,我只需要一个url值来创建实例,而我无法在'KClass .members'中找到它' – user6238994

回答

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

它的工作原理,非常感谢。 – user6238994

0

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

请注意,Kotlin确实没有静态的概念,而且这个注释仅仅是针对JVM语言的可访问性。

+0

我也试过'@ JvmStatic',IDE说'只有函数在命名对象和伴侣类的对象可以用'@ JvmStatic'注解。 – user6238994

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/" 
} 
+0

Api接口用于[Retrofit](http://square.github.io/retrofit/),它必须是一个接口。如果我用一个函数替换它,要访问它,我需要一个实例,创建一个我需要url值的实例,看起来像一个循环。 – user6238994

+0

我的观点是你不需要将你的静态信息放入界面。 URL可以存储在接口附近的任何地方(选项1和2)。 – voddan

+0

确实,我可以把它放在地图中,并用类名访问它(GithubApi不是唯一的接口,它甚至不是我的代码中的真实接口,它只是一个示例),但是我发布的这些代码仅用于测试用例,更少的代码和更少关心性能,我在实际代码中使用'Retrofit.Builder()。baseUrl(GithubApi.BASE_URL)'。 – user6238994

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

} 
+0

使用'AllUrls.INSTANCE.getGITHUB_URL()'使这个方法现在只能用于GithubApi,这种情况我们甚至不需要'clazz'。我不认为在接口中放置常量是错误的,在android.os.Parcelable中有一个整型常量'PARCELABLE_WRITE_RETURN_VALUE'。 – user6238994

相关问题