Please help me convert this java code to kotlin, I try many times but I can't
ObjectStream<DocumentSample> bin
= ObjectStreamUtils.createObjectStream(categoryStreams.toArray(new ObjectStream[0]));
In Kotlin, you may use toTypedArray() to get an Array from a List:
categoryStreams.toTypedArray() //Array<ObjectStream<DocumentSample>>
Then, you can use spread operator to prefix the array and pass it to ObjectStreamUtils.createObjectStream():
val bin = ObjectStreamUtils.createObjectStream<DocumentSample>(*categoryStreams.toTypedArray())
Assuming the categoryStreams object is one of the Collection type(List, Set, etc.), you can call kotlin's extension method toTypedArray on it to get an array of the ObjectStream:
This should work:
val bin = ObjectStreamUtils.createObjectStream(categoryStreams.toTypedArray())
If the method accepts vararg of ObjectStream, then you can use spread operator * to spread array to vararg:
val bin = ObjectStreamUtils.createObjectStream(*categoryStreams.toTypedArray())
To convert Java file to Kotlin
On the main menu, point to Code menu.
Choose Convert Java File to Kotlin File.
Done.
In your case it converts to:
val bin = ObjectStreamUtils.createObjectStream(categoryStreams.toArray(arrayOfNulls<ObjectStream>(0)))
var bin = ObjectStreamUtils.createObjectStream(categoryStreams.toArray(arrayOfNulls(0)))
the above code is converted your code to kotlin.
It sounds like a type inference problem. Try the code below. I add the declaration for categoryStreams. Not sure how it is declared in your code. But this is a reasonable declaration from looking at the code on github.
val categoryStreams = arrayListOf<ObjectStream<DocumentSample>>()
val bin = ObjectStreamUtils.createObjectStream(categoryStreams.toArray(arrayOfNulls<ObjectStream<DocumentSample>>(0)))
The idea is to provide the correct type for inference (which the converter neglected to provide). The original java did not infer the type, it was an explicit cast.
Related
In my Kotlin code, I have a variable that is the Type interface from
java.lang.reflect
var type: Type
But I need to cast this to:
List<UserInfo>
If I was not casting to a List, I would just do this:
var type = UserInfo::class.java
and this works. But I don't know how to cast it using a List. The closest I found is this:
var type = Array<UserInfo>::class.java
This would compile if my UserInfo was an Array but it's a List.
The issue (as #Miha_x64 says) is type erasure.
The Java Virtual Machine knows nothing about type parameters. So although the source specified a List<UserInfo>, it compiles down to a plain List.
So this works:
var type = List::class.java
(Your Array example works because arrays are a special case: they're directly supported in the JVM, and keep their types at runtime.)
Java's use of type erasure is at least partly for historical reasons; when generics were added to Java 5, they wanted to preserve compatibility with existing source and bytecode. For all the gory details (much of which is inherited by Kotlin), see here.
Maybe its late. Try to use KTypeProjection and createType() with KClass instead. Then get the value in KType or convert it back to java Type.
val kClass = YourClass::class
val kTypeProjection = KTypeProjection.invariant(entity.starProjectedType)
val kType = List::class.createType(listOf(kTypeProjection))
val type = kType.javaType
result:
kType: kotlin.collections.List<YourClass>
type: java.util.List<YourClass>
I try to write a type-safe wrapper for a JavaScript library.
I need to call a method from JavaScript with variable arguments
(e.g. method(args...)).
The Kotlin fun for this should work with variable arguments, too.
Because Kotlin supports a spread operator, I tried to use it, but Kotlin do not want this.
Example code:
val jsLibrary: dynamic = require("library") // library given by node's require here
fun method(vararg args: String) = jsLibrary.method(*args)
Edit: Forgot to write spread operator '*' in code already. Compiler returns error because of the spread operator.
The Kotlin compiler returns the error "Can't apply spread operator in dynamic call".
Any ideas how to implement a wrapper like this, or do I need any workaround?
Thanks for your help!
Use external fun with #JsModule annotation
#JsModule("library")
external fun method(vararg args: String): LibraryMethodReturnType
This will do require("library") for you under the hood. You'll have proper Kotlin types instead of dynamic right away. You'll have no "wrappers", meaning no extra JavaScript call at runtime.
There is a hacky solution if for you want to manually use require and dynamic types: use apply method to pass all the arguments as an array.
val jsLibrary: dynamic = require("library")
fun method(vararg args: String) = jsLibrary.method.apply(null, args)
I was playing with the kotlin-native samples.
I wonder how I could get String from pinned ByteArray. Just want to print it in the console.
If you need a solution for the JVM, since stringFromUtf8 is only available for the native platform, use toString with a Charset as argument:
val byteArray = "Hello World".toByteArray(Charsets.UTF_8)
val str = byteArray.toString(Charsets.UTF_8)
If you specifically only want to target native, use Sin's solution.
It seems that this API has changed
Now just use this: string.toUtf8(start, end)
https://github.com/JetBrains/kotlin-native/commit/cba7319e982ed9ba2dceb517a481cb54ed1b9352#diff-45a5f8d37067266e27b76d1b68f01173
Legacy version:
Use stringFromUtf8
/**
* Converts an UTF-8 array into a [String]. Replaces invalid input sequences with a default character.
*/
fun ByteArray.stringFromUtf8(start: Int = 0, size: Int = this.size) : String =
stringFromUtf8Impl(start, size)
See here.
And if the byteArray is like CPointer<ByteVar> by interoperating C APIs, pleace use .toKString() in Kotlin-Native
The OKIO library has a helper method for this commonToUtf8String
One can simply copy the method code don't need to add the entire lib just for this.
Another solution that could be used everyone but especially makes sense looking for a Kotlin Multiplatform solution and using ktor library already is using io.ktor.utils.io.core.String function directly without adding extra third pary library or extra actual class implementation. For example:
Your build.gradle.kts for all platforms:
implementation("io.ktor:ktor-client-core:${Versions.ktor}")
implementation("io.ktor:ktor-client-android:${Versions.ktor}")
implementation("io.ktor:ktor-client-apache:${Versions.ktor}")
implementation("io.ktor:ktor-client-ios:${Versions.ktor}")
Then use it
io.ktor.utils.io.core.String(byteArray, offset, length, Charsets.UTF_8)
How can I find the variable type in Kotlin?
In Java there is instanceof, but Kotlin does not exist:
val properties = System.getProperties() // Which type?
You can use the is operator to check whether an object is of a specific type:
val number = 5
if(number is Int) {
println("number is of type Int")
}
You can also get the type as String using reflection:
println(Int::class.simpleName) // "Int"
println(Int::class.qualifiedName) // "kotlin.Int"
Please note:
On the Java platform, the runtime component required for using the
reflection features is distributed as a separate JAR file
(kotlin-reflect.jar). This is done to reduce the required size of the
runtime library for applications that do not use reflection features.
If you do use reflection, please make sure that the .jar file is added
to the classpath of your project.
Source: https://kotlinlang.org/docs/reference/reflection.html#bound-class-references-since-11
You can use like this:
val value="value"
println(value::class.java.typeName)
you can get the class name with properties::class.simpleName
Just a minor detail between mentioned answers.
var x = "X"
println(x::class.simpleName) // prints String
This code uses Reflection under the hood when you decompile it to Java bytecode and it looks like this Reflection.getOrCreateKotlinClass(x.getClass()).getSimpleName()
var y = "Y"
println(y.javaClass.simpleName) // prints String
And this would compile down to y.getClass().getSimpleName() and it's about 50 milliseconds faster.
I am trying to use one of my defined functions that accepts a string yet the software won't compile.
fun passes(address: String) = Collections.frequency(addresses, address) <= CONNECTIONS_PER_IP
fun passes(remoteAddress: InetSocketAddress) = passes(remoteAddress.hostName)
I can't even call the string function using a custom string, for example passes("127.0.0.1").
None of the following functions can eb called with the arguments supplied.
passes(String) defined in abendigo.Firewall
passes(InetSocketAddress) defined in abendigo.Firewall
I presume you're using java.lang.String instead of kotlin.String in the Kotlin source code. Please use only kotlin.String instead, this is the type that string literals in Kotlin have (but in the bytecode it's still transformed to java.lang.String).
The issue was an import of java.lang.String. For some reason IntelliJ imported it.