Project import
Convert
- Java 파일에서 Java 문법으로 작성
- Convert
- ctrl + alt + shift +k
- 코드 블록 중 필요한 부분만 복사 붙여넣기 시 Convert
- Code > Convert Java File to Kotlin File
- Convert 시
- Convert 후 오류 코드 수정
- 문법 상 오류가 많을 수 있으니 차근차근 기본 문법을 기준으로 틀린곳을 수정
- 어느정도 학습 효과가 나타나면 코드 줄이기
- Convert 주의할 점
- 모든 라이브러리가 Kotlin은 아니다
- Java API 사용법을 모른다면 그것부터 익혀야 한다.
- @Nullable에 주의 하자
- Java에서는 언제든 Nullable이 발생할 수 있다.
- 이 경우 NullPointerException이 언제든지 발생 가능
- Null safe방법으로 접근하여 NPE 발생을 줄인다.
- 모든 라이브러리가 Kotlin은 아니다
- Kotlin에서 Android 어노테이션을 사용하기 위해선 build.gradle에 하단 내용이 추가되어야 한다.
apply plugin: 'kotlin-kapt'
- annotation processor 대신 kapt로 사용 가능
- annotation processor
- 어노테이션을 사용하기 위해서는 어노테이션 프로세서가 필요하다.
- 어노테이션 프로세서를 사용한다는 것을 자바 컴파일러가 알고 있는 상태에서 컴파일을 수행한다.
- 어노테이션 프로세서들이 각자의 역할에 맞게 구현되어 있는 상태에서 실행되지 않은 어노테이션 프로세서를 실행한다.
- 어노테이션 프로세서 내부에서 어노테이션에 대한 처리를 한다.자바 컴파일러가 모든 어노테이션 프로세서가 실행 되었는지 검사하고, 모든 어노테이션 프로세서가 실행되지 않았다면 반복한다.
kapt "com.android.databinding:compiler:$rootProject.dataBindingVersion"
- 어노테이션을 사용하기 위해서는 어노테이션 프로세서가 필요하다.
- annotation processor
- 데이터 바인딩을 사용하기 위해선 build.gradle에 하단 내용이 추가되어야 한다.
dataBinding { enabled true }
kapt "com.android.databinding:compiler:$rootProject.dataBindingVersion"
Java -> Kotlin - SearchRepository
원본 java 파일
public class SearchRepository {
private final GitHubService gitHubService;
private static SearchRepository instance;
private SearchRepository(@NotNull GitHubService gitHubService) {
this.gitHubService = gitHubService;
}
public static SearchRepository getInstance(@NotNull GitHubService gitHubService) {
if (instance == null) {
synchronized (SearchRepository.class) {
if (instance == null) {
instance = new SearchRepository(gitHubService);
}
}
}
return instance;
}
private int nowPage = 1;
public Single<List<RepositoriesItem>> searchRepositories(String searchKeyword, String sort, String order, int perPage) {
return gitHubService.searchUser(searchKeyword, sort, order, nowPage, perPage)
.map(new Function<Repositories, List<RepositoriesItem>>() {
@Override
public List<RepositoriesItem> apply(Repositories repositories) throws Exception {
return repositories.getItems();
}
});
}
}
Java -> Kotlin 변환 파일
class SearchRepository private constructor(private val gitHubService: GitHubService) {
private val nowPage = 1
fun searchRepositories(searchKeyword: String?, sort: String?, order: String?, perPage: Int): Single<List<RepositoriesItem>> {
return gitHubService.searchUser(searchKeyword, sort, order, nowPage, perPage)
.map { (_, _, items) -> items }
}
companion object {
private var instance: SearchRepository? = null
@JvmStatic
fun getInstance(gitHubService: GitHubService): SearchRepository? {
if (instance == null) {
synchronized(SearchRepository::class.java) {
if (instance == null) {
instance = SearchRepository(gitHubService)
}
}
}
return instance
/*아래처럼 변경 가능함*/
return instance ?: synchronized(SearchRepository::class.java) {
instance ?: let {
var create = SearchRepository(gitHubService)
instance = create
create
}
}
/*아래처럼 변경 가능함*/
return instance ?: synchronized(SearchRepository::class.java) {
instance ?: SearchRepository(gitHubService).also {
instance = it
}
}
}
}
}
Kotlin Decompile
@Metadata(
mv = {1, 1, 18},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000.\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\b\n\u0000\n\u0002\u0018\u0002\n\u0002\u0010 \n\u0002\u0018\u0002\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0005\u0018\u0000 \u00102\u00020\u0001:\u0001\u0010B\u000f\b\u0002\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J8\u0010\u0007\u001a\u000e\u0012\n\u0012\b\u0012\u0004\u0012\u00020\n0\t0\b2\b\u0010\u000b\u001a\u0004\u0018\u00010\f2\b\u0010\r\u001a\u0004\u0018\u00010\f2\b\u0010\u000e\u001a\u0004\u0018\u00010\f2\u0006\u0010\u000f\u001a\u00020\u0006R\u000e\u0010\u0002\u001a\u00020\u0003X\u0082\u0004¢\u0006\u0002\n\u0000R\u000e\u0010\u0005\u001a\u00020\u0006X\u0082D¢\u0006\u0002\n\u0000¨\u0006\u0011"},
d2 = {"Ltech/thdev/tacademysampleapp/data/source/repositories/SearchRepository;", "", "gitHubService", "Ltech/thdev/tacademysampleapp/network/GitHubService;", "(Ltech/thdev/tacademysampleapp/network/GitHubService;)V", "nowPage", "", "searchRepositories", "Lio/reactivex/Single;", "", "Ltech/thdev/tacademysampleapp/data/RepositoriesItem;", "searchKeyword", "", "sort", "order", "perPage", "Companion", "app_debug"}
)
public final class SearchRepository {
private final int nowPage;
private final GitHubService gitHubService;
private static SearchRepository instance;
@NotNull
public static final SearchRepository.Companion Companion = new SearchRepository.Companion((DefaultConstructorMarker)null);
@NotNull
public final Single searchRepositories(@Nullable String searchKeyword, @Nullable String sort, @Nullable String order, int perPage) {
Single var10000 = this.gitHubService.searchUser(searchKeyword, sort, order, this.nowPage, perPage).map((Function)null.INSTANCE);
Intrinsics.checkExpressionValueIsNotNull(var10000, "gitHubService.searchUser… (_, _, items) -> items }");
return var10000;
}
private SearchRepository(GitHubService gitHubService) {
this.gitHubService = gitHubService;
this.nowPage = 1;
}
// $FF: synthetic method
public SearchRepository(GitHubService gitHubService, DefaultConstructorMarker $constructor_marker) {
this(gitHubService);
}
@JvmStatic
@Nullable
public static final SearchRepository getInstance(@NotNull GitHubService gitHubService) {
return Companion.getInstance(gitHubService);
}
@Metadata(
mv = {1, 1, 18},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0012\u0010\u0005\u001a\u0004\u0018\u00010\u00042\u0006\u0010\u0006\u001a\u00020\u0007H\u0007R\u0010\u0010\u0003\u001a\u0004\u0018\u00010\u0004X\u0082\u000e¢\u0006\u0002\n\u0000¨\u0006\b"},
d2 = {"Ltech/thdev/tacademysampleapp/data/source/repositories/SearchRepository$Companion;", "", "()V", "instance", "Ltech/thdev/tacademysampleapp/data/source/repositories/SearchRepository;", "getInstance", "gitHubService", "Ltech/thdev/tacademysampleapp/network/GitHubService;", "app_debug"}
)
public static final class Companion {
@JvmStatic
@Nullable
public final SearchRepository getInstance(@NotNull GitHubService gitHubService) {
Intrinsics.checkParameterIsNotNull(gitHubService, "gitHubService");
if (SearchRepository.instance == null) {
Class var2 = SearchRepository.class;
synchronized(var2) {
int var3 = false;
if (SearchRepository.instance == null) {
SearchRepository.instance = new SearchRepository(gitHubService, (DefaultConstructorMarker)null);
}
Unit var4 = Unit.INSTANCE;
}
}
return SearchRepository.instance;
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
Kotlin , Java로 Decompile한 소스 비교 - SearchRepository
getInstance 함수 (1)
- kotlin
companion object {
private var instance: SearchRepository? = null
@JvmStatic
fun getInstance(gitHubService: GitHubService): SearchRepository? {
if (instance == null) {
synchronized(SearchRepository::class.java) {
if (instance == null) {
instance = SearchRepository(gitHubService)
}
}
}
return instance
}
}
- Java Decompile
public static final class Companion {
@JvmStatic
@Nullable
public final SearchRepository getInstance(@NotNull GitHubService gitHubService) {
Intrinsics.checkParameterIsNotNull(gitHubService, "gitHubService");
if (SearchRepository.instance == null) {
Class var2 = SearchRepository.class;
synchronized(var2) {
int var3 = false;
if (SearchRepository.instance == null) {
SearchRepository.instance = new SearchRepository(gitHubService, (DefaultConstructorMarker)null);
}
Unit var4 = Unit.INSTANCE;
}
}
return SearchRepository.instance;
}
getInstance 함수 (2)
- kotlin
companion object {
private var instance: SearchRepository? = null
@JvmStatic
fun getInstance(gitHubService: GitHubService): SearchRepository? {
return instance ?: synchronized(SearchRepository::class.java) {
instance ?: let {
var create = SearchRepository(gitHubService)
instance = create
create
}
}
}
}
- Java Decompile
@JvmStatic
@Nullable
public static final SearchRepository getInstance(@NotNull GitHubService gitHubService) {
return Companion.getInstance(gitHubService);
}
public static final class Companion {
@JvmStatic
@Nullable
public final SearchRepository getInstance(@NotNull GitHubService param1) {
// $FF: Couldn't be decompiled
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
getInstance 함수 (3)
- kotlin
companion object {
private var instance: SearchRepository? = null
@JvmStatic
@Synchronized
fun getInstance(gitHubService: GitHubService): SearchRepository? {
return instance ?: synchronized(SearchRepository::class.java) {
instance ?: SearchRepository(gitHubService).also {
instance = it
}
}
}
}
- Java Decompile
@JvmStatic
@Nullable
public static final synchronized SearchRepository getInstance(@NotNull GitHubService gitHubService) {
return Companion.getInstance(gitHubService);
}
public static final class Companion {
@JvmStatic
@Nullable
public final synchronized SearchRepository getInstance(@NotNull GitHubService param1) {
// $FF: Couldn't be decompiled
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
Object 생성
- kotlin
object SampleObject
- Java Decompile
public static final class SampleObject {
@NotNull
public static final SearchRepository.SampleObject INSTANCE;
private SampleObject() {
}
static {
SearchRepository.SampleObject var0 = new SearchRepository.SampleObject();
INSTANCE = var0;
}
}
Java -> Kotlin - GithubAPI
원본 java 파일
public class GithubAPI {
private GitHubService gitHubService;
private GithubAPI() {
gitHubService = RetrofitCreator.createRetrofit(Contract.API, GitHubService.class);
}
private static GithubAPI instance;
public static GithubAPI getInstance() {
if (instance == null) {
synchronized (GithubAPI.class) {
if (instance == null) {
instance = new GithubAPI();
}
}
}
return instance;
}
public GitHubService getGithubService() {
return gitHubService;
}
}
Java -> Kotlin 변환 파일
object GithubAPI {
val githubService: GitHubService
init {
githubService = RetrofitCreator.createRetrofit(API, GitHubService::class.java)
}
}
Kotlin - Lazy 패턴 추가
lateinit
- 테스트 케이스 작성
- private lateinit var name: String을 초기화 하지 않고 사용하여 에러 발생
- 에러 발생을 막기 위하여 ::변수명.isInitialized 사용
@Test fun test() { if(::name.isInitialized) { println("name $name") } }
- 테스트 케이스 디컴파일
public final class Late {
private String a = "";
private String name;
@Test
public final void test() {
StringBuilder var10000 = (new StringBuilder()).append("name ");
String var10001 = this.name;
if (var10001 == null) {
//Exception 발생
Intrinsics.throwUninitializedPropertyAccessException("name");
}
String var1 = var10000.append(var10001).toString();
System.out.println(var1);
}
}
lazy
- 테스트 케이스 작성
- 해당 변수가 호출될 때 초기화 실행
- lazy 블럭은 처음 사용될 때 한 번만 호출되고 그 이상 사용시에는 호출되지 않는다.
Kotlin 변환 파일 - lazy 패턴 적용
object GithubAPI {
val githubService: GitHubService by lazy {
RetrofitCreator.createRetrofit(API, GitHubService::class.java)
}
}
'Back-end > Kotlin' 카테고리의 다른 글
코틀린(Kotlin) 기본 문법 II (상속 / 인터페이스 / 데이터 클래스 / 싱글톤 / 람다) (0) | 2021.12.07 |
---|---|
코틀린(Kotlin) 기본 문법 I (타입 / 변수 (Nullable, Cast, Elvis Operator) / 클래스 (Constructor)) (0) | 2021.12.06 |