본문 바로가기
Java & Kotlin/Kotlin

reified를 통해 generic type 정보 가져오기

by devson 2023. 1. 16.

generic을 사용하여 코드를 작성할 때, generic type의 정보를 사용하고 싶은 경우가 있을 것이다.

 

아래 코드는 generic을 사용하여 파라미터의 타입을 확인하는 함수이다.

fun <T> isInstanceOf(obj: Any): Boolean {
    println("check object(${obj::class}) is instance of ${T::class}")
    return obj is T
}

 

하지만 generic은 compile 후 제거되기 때문에 위 코드와 같이 generic type을 직접적으로 사용하는 코드는 compile error를 낸다.

 

그래서 주로 아래와 같이 추가로 generic type과 같은 Class 타입의 파라미터를 받는 식으로 우회한다.

fun <T> isInstanceOf(obj: Any, type: Class<T>): Boolean {
    println("check object(${obj::class}) is instance of ${type}")
    return type.isInstance(obj)
}

 

 

inlinereified keyword를 사용하면 파라미터를 추가로 받는 방식을 사용하지 않아도 된다.

inline fun <reified T> isInstanceOf(obj: Any): Boolean {
    println("check object(${obj::class}) is instance of ${T::class}")
    return obj is T
}

 

위와 같이 inline, reified keyword를 사용하면, 이 함수를 호출하는 쪽에서 호출 함수의 내용을 그대로 옮겨 generic으로 지정된 type의 class를 사용하여 기능을 실행한다.

 

 

코드로 살펴보자.

아래와 같이 main 함수에서 isInstanceOf 함수를 호출한다고 했을 때

import java.io.File

fun main() {
    isInstanceOf<FileSystemException>(FileAlreadyExistsException(File("/path/to/file")))
}

inline fun <reified T> isInstanceOf(obj: Any): Boolean {
    println("check object(${obj::class}) is instance of ${T::class}")
    return obj is T
}

 

이 Kotlin 코드를 Java로 변환해보면 아래와 같다.

public final class ReifiedExampleKt {
   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
   
   public static final void main() {
      Object obj$iv = new FileAlreadyExistsException(new File("/path/to/file"), (File)null, (String)null, 6, (DefaultConstructorMarker)null);
      String var2 = "check object(" + Reflection.getOrCreateKotlinClass(obj$iv.getClass()) + ") is instance of " + Reflection.getOrCreateKotlinClass(FileSystemException.class);
      System.out.println(var2);

      boolean var10000 = obj$iv instanceof FileSystemException;
   }

   // $FF: synthetic method
   public static final boolean isInstanceOf(Object obj) {
      StringBuilder var10000 = (new StringBuilder()).append("check object(").append(Reflection.getOrCreateKotlinClass(obj.getClass())).append(") is instance of ");
      String var2 = var10000.append(Reflection.getOrCreateKotlinClass(Object.class)).toString();
      System.out.println(var2);
      
      return obj instanceof Object;
   }
}

main 메서드가 isInstanceOf 메서드와 기능적으로 동일한 코드를 갖고 있고,

generic으로 명시된 FileSystemException을 사용하여 기능을 실행하는 것을 볼 수 있다.

 


 

OOP를 사용하면 함수 레벨에서 generic을 쓰기보다는 주로 class 레벨에서 generic을 주로 사용하게 되는데,

reified는 class 레벨에서 사용할 수 없기 때문에 내가 이를 실제로 사용할만한 부분이 있을까 싶다 🤔

 
 

댓글