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에서 Android 어노테이션을 사용하기 위해선 build.gradle에 하단 내용이 추가되어야 한다.
    apply plugin: 'kotlin-kapt'​
  • annotation processor 대신 kapt로 사용 가능
    • annotation processor
      • 어노테이션을 사용하기 위해서는 어노테이션 프로세서가 필요하다.
        • 어노테이션 프로세서를 사용한다는 것을 자바 컴파일러가 알고 있는 상태에서 컴파일을 수행한다.
        • 어노테이션 프로세서들이 각자의 역할에 맞게 구현되어 있는 상태에서 실행되지 않은 어노테이션 프로세서를 실행한다.
        • 어노테이션 프로세서 내부에서 어노테이션에 대한 처리를 한다.자바 컴파일러가 모든 어노테이션 프로세서가 실행 되었는지 검사하고, 모든 어노테이션 프로세서가 실행되지 않았다면 반복한다.
          kapt "com.android.databinding:compiler:$rootProject.dataBindingVersion"​
  • 데이터 바인딩을 사용하기 위해선 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)
    }

}

+ Recent posts