Kotlin is a modern programming language that offers a powerful type system and concise syntax. Developers coming from Java often look for ways to create arrays using wildcard types such as <?>. While Kotlin handles generics differently, there are several ways to create flexible arrays capable of storing different types of data.
This beginner-friendly guide explains how to create arrays that behave similarly to wildcard arrays in Kotlin and when to use each approach.
Understanding Wildcards in Kotlin
In Java, you might encounter wildcard types such as:
List<?>
Kotlin does not use the ? wildcard syntax in the same way. Instead, it provides:
AnyAny?- Star projections (
*) - Generic type parameters
These features allow developers to achieve the same flexibility while maintaining type safety.
Using Array<Any?>
The simplest approach is to create an array that can store any type of value.
val values: Array<Any?> = arrayOf(
"Hello",
123,
true,
45.67,
null
)
Output
Hello
123
true
45.67
null
This array can contain:
- Strings
- Numbers
- Booleans
- Objects
- Null values
Because Any? is the root type of all nullable objects in Kotlin.
Creating an Empty Generic Array
Sometimes you need an array that will be populated later.
val data: Array<Any?> = arrayOfNulls(5)
This creates:
[null, null, null, null, null]
You can then populate it:
data[0] = "Kotlin"
data[1] = 100
data[2] = false
Creating Arrays with Generic Functions
A more reusable approach is to create a generic function.
inline fun <reified T> createArray(size: Int): Array<T?> {
return arrayOfNulls(size)
}
Usage:
val strings = createArray<String>(3)
val numbers = createArray<Int>(5)
Result:
[String?, String?, String?]
[Int?, Int?, Int?, Int?, Int?]
This allows the same method to create arrays for any data type.
Using Star Projections
Kotlin provides star projections (*) as the closest equivalent to Java wildcards.
Example:
val list: List<*> = listOf(
"Text",
123,
true
)
This means:
A list of unknown type
You can read values safely:
for (item in list) {
println(item)
}
Output:
Text
123
true
Working with Arrays of Unknown Types
You can also declare:
val array: Array<*> = arrayOf(
"Apple",
"Orange",
"Banana"
)
Or:
val mixedArray: Array<*> = arrayOf(
"Hello",
42,
true
)
When using Array<*>, Kotlin allows safe reading but restricts writing because the exact type is unknown.
Difference Between Any? and *
Many developers confuse these two concepts.
Array<Any?>
val arr: Array<Any?> = arrayOf("A", 1, true)
Characteristics:
- Can store any value.
- Allows writing new values.
- Explicitly uses
Any?as the type.
Array<*>
val arr: Array<*> = arrayOf("A", "B", "C")
Characteristics:
- Represents an unknown type.
- Safe for reading.
- Restricts writing operations.
Practical Example
Suppose you are processing data from different sources:
val records: Array<Any?> = arrayOf(
"John",
25,
true,
1500.75
)
for (record in records) {
println(record)
}
Output:
John
25
true
1500.75
This approach is useful when:
- Reading CSV files
- Processing API responses
- Creating dynamic data structures
- Logging heterogeneous data
Common Mistakes
Using Array<String> When Types Differ
Incorrect:
val arr: Array<String> = arrayOf(
"Hello",
123
)
Compilation error occurs because all elements must be strings.
Correct
val arr: Array<Any?> = arrayOf(
"Hello",
123
)
Forgetting Nullability
Incorrect:
val arr: Array<Any> = arrayOf(
"Hello",
null
)
This causes an error because Any cannot hold null values.
Correct
val arr: Array<Any?> = arrayOf(
"Hello",
null
)
Performance Considerations
For primitive values, Kotlin provides specialized arrays:
val numbers = intArrayOf(1, 2, 3)
Instead of:
val numbers = arrayOf(1, 2, 3)
Specialized arrays avoid boxing and typically provide better performance.
Examples:
IntArray
LongArray
DoubleArray
BooleanArray
CharArray
Best Practices
Use Any? When
- Multiple data types must coexist.
- Dynamic structures are required.
- Null values are expected.
Use Generic Arrays When
- Strong typing is important.
- Reusable utility functions are needed.
- Compile-time safety is desired.
Use Star Projections (*) When
- The exact type is unknown.
- You only need read access.
- Working with generic APIs.
Conclusion
Although Kotlin does not use Java-style wildcard syntax such as <?>, it provides several powerful alternatives. Developers can use Any? for mixed-type arrays, generic functions for reusable type-safe arrays, and star projections (*) when working with unknown generic types.
Understanding these options helps create cleaner, safer, and more maintainable Kotlin applications while taking full advantage of Kotlin’s modern type system.


