M13 - Generic Java class literal?


#1

How to express Java class literal with generic type?

The following used to work:

val mockedTask = mock(javaClass<Task<String>>())

But how to express the same thing in M13? Task&lt;String&gt;::class.java doesn’t compile.


#2

Java Class object do not contains any generic information due to type erasure, so in Kotlin M12 javaClass<Task<String>>() is strictly equals to javaClass<Task<*>>() If you want generic type information, you probably need a ParameterizedType, I use those in Kodein, have a look at https://github.com/SalomonBrys/Kodein/blob/master/src/main/kotlin/TypeToken.kt Line 18 and 42.


#3

Thanks, but I'm not looking for runtime generic support.

// Create a mocked object with type `Task<String>` in compile time val mockedTask: Task<String> = mock(javaClass<Task<String>>())

`javaClass()` works as eexcepted, now I'm looking the equivalent in M13 since javaClass is deprecated.

 
// Can only get an instance with type `Task<*>` in M13's prefered way
 
val mockedTask: Task<*> = mock(Task::class.java)

#4

What's the signature of the "mock" function?


#5

  

// mock method from Mockito

 
public static <T> T mock(Class<T> classToMock)

#6

T must extends Any


#7

`mock` is a java method from Mockito library, not in Kotlin.


#8

I answered this in  https://youtrack.jetbrains.com/issue/KT-9193 and beyond that it isn't a Kotlin issue as much as a Java reflect issue.  You need to know more about Java reflection to go further.

I gave you a way to get the Java reflect Type in the comments of that issue.  Given a type, and knowing about the 5 different implementations of the Type interface will let you know and do more.

You need to study examples of people that do this (Jackson, Jackson Jr., GSON, and others have good code bases doing this)

Really, think “Java reflect Type” not “Kotlin problem”

A Class<T> is not nearly the same as a Type.  And a Class<T> reference will NEVER contain generic information and nor is it always available at the point at which the code is being compiled.  And if not available at that moment, it can never be seen other than for ancestor classes.  

You can fake making a class used in a call to a reified inline function receive type information so the user doesn’t know you are doing it.  But you cannot use a class literal because that represents Class<T> which erases type information inside the Java VM.

See the issue for comments and an example of getting a Java Type.  Then if you put that inside a function that receives reified generics and call fullType<T>() on that reified type, you would end up with the correct Java Type.  But that assumes it is available at compilation at the point of the method call.  If not, you end up receiving something unexpected.  


#9

I added more sample info to the linked YouTrack issue.


#10

that mock method doesn't need generics passed in, only when casting out.   for example, this works fine:

 
public fun <T: Any> mock(ofClass: Class<T>): T = ofClass.newInstance()

@Suppress(“UNCHECKED_CAST”)
public fun foo() {
  val fake: Map<String, Int> = mock(Map::class.java) as Map<String, Int>
}


 
// but I would do this instead:

 

public inline fun <reified T: Any> mockBetter(): T = T::class.java.newInstance()
public fun foo() {
  val fake: Map<String, Int> = mockBetter()
}

 
// notice how I didn’t even have to pass in the class anymore, 

 
// but I could delegate to the other method that wants a class or not.  

 
// And I don’t have to cast outside my helper.

#11

now that I have your use case, see answer above.  

It is always good to say “Here is my use case, and this isn’t working” instead of jumping to the possible feature that you are looking for.  Because you might not be looking for the right thing.


#12

Thanks for your detailed explaination.

I finally make Intellij attach source codes of Kotlin runtime&stdlib for my gradle project. Now I understand the current implementation of javaClass() is:

  public fun <reified T: Any> javaClass(): Class<T> = T::class.java


I’ll go with a similiar function in my own utility libs as you and Alexander suggested.


#13

You can clear many of your doubts regarding Literals in Java through Merit Campus, visit: http://java.meritcampus.com/core-java-topics/data-types-in-java, http://java.meritcampus.com/core-java-topics/integer-literals-in-java

Not only Literals, we also have each and every topic in Core Java with example for each. You can read lot of sessions and can write many practice tests in Merit Campus Java website. visit: http://java.meritcampus.com/core-java-topics/ to know more.