Kotlin

Difference between and Any in Kotlin generics

27 September 2026 · 10 min read

Difference between  and Any in Kotlin generics

Kotlin, a modern and concise programming language, provides powerful features for type safety and code reusability through generics. Generics allow you to write code that can work with different types without sacrificing type safety. However, understanding the nuances of wildcard types is crucial for effective use of generics. One common point of confusion for Kotlin developers is the difference between "" and “Any” in Kotlin generics. While both seem to offer flexibility in type handling, their underlying mechanisms and implications differ significantly. Mastering these differences enables developers to write more robust and adaptable Kotlin applications, avoiding potential runtime errors and ensuring code maintainability. This article will delve into the specifics of these two constructs, providing clear explanations, examples, and best practices to help you confidently navigate the complexities of Kotlin generics.

Understanding Any in Kotlin Generics

Any in Kotlin serves as the root of the Kotlin class hierarchy, analogous to Object in Java. When used as a type parameter in generics, Any signifies that the generic type can be any non-nullable type. This is a crucial distinction, as it excludes nullable types by default. For instance, if you define a class Box, you can store instances of String, Int, or any other class in the Box, but you cannot store null directly. This behavior aligns with Kotlin’s emphasis on null safety, helping to prevent null pointer exceptions at runtime. Using Any? would allow nullable types.

Consider a scenario where you are building a data processing pipeline. You might have a function that needs to operate on various data types, such as integers, strings, or custom objects. By using Any as the generic type parameter, you can create a single function that handles all these types, promoting code reuse and reducing redundancy. However, you must remember that within the function, you’ll need to perform type checks or casts to work with the specific data type, as the compiler only knows that it’s dealing with Any. This highlights a key trade-off: flexibility in type acceptance versus the need for explicit type handling within the generic code.

For example, if you have a function like fun <t: any=""> processData(data: T), you can pass any non-nullable type to this function. Inside the function, you might use when expressions or is checks to determine the actual type of data and perform specific operations accordingly. This approach provides a powerful way to create generic algorithms that can adapt to different data types while maintaining type safety to the extent possible.</t:>

Exploring the Power of (Star Projection)

The in Kotlin generics represents what’s known as a star projection. It’s essentially a shorthand for expressing an unknown type. Unlike Any, which specifies that the type can be any non-nullable type, provides a way to handle generic types where you don’t know or don’t care about the specific type argument. It’s especially useful when dealing with classes or interfaces that have generic type parameters, but you only need to interact with the object in a type-agnostic way. Star projection offers a higher level of abstraction compared to Any.

When you use , the compiler infers a safe upper bound and lower bound for the type parameter. If a generic class is declared as class Box, using Box<> means that for all practical purposes, the type parameter T is unknown. You can still access members of Box, but if those members involve the type parameter T, you’ll only be able to access them in a limited way. For example, if Box has a method fun getItem(): T, calling this method on a Box<> will return a value of type Any?, representing the safest upper bound for the unknown type. You can’t add elements to a MutableList<>, because the compiler cannot guarantee type safety.

Consider a scenario where you’re working with a library that returns a List<>. You don’t necessarily need to know the specific type of elements in the list; you might only need to iterate over the list and perform some generic operation on each element. In this case, provides a convenient way to handle the list without having to explicitly specify a type parameter. This can simplify your code and reduce the need for unnecessary type casts. According to Kotlin documentation, star projection is used when the actual type argument is irrelevant, or when providing type safety is not critical in a particular context. Kotlin Generics Documentation

Key Differences: Any vs.

The core difference between "" and “Any” in Kotlin generics lies in their type representation and usage scenarios. Any explicitly states that the generic type can be any non-nullable type, providing a concrete lower bound. In contrast, represents an unknown type, offering a more abstract and flexible approach. When using Any, you’re essentially saying, “I know there’s a type here, and it can be anything non-nullable.” When using , you’re saying, “I don’t know or care about the specific type.” This distinction has significant implications for how you interact with generic types in your code.

One crucial difference manifests in how you can use objects of these types. With Any, you can still perform type checks and casts to work with the underlying type, as the compiler knows that it’s dealing with a non-nullable object. With , you’re more limited in what you can do, as the compiler treats the type as unknown. For example, if you have a List, you can iterate over the list and attempt to cast each element to a specific type. However, if you have a List<>, you can only iterate over the list and treat each element as Any?, requiring more careful handling of potential null values. This difference makes Any more suitable when you need to perform type-specific operations, while is better suited for type-agnostic operations.

Here’s a featured snippet-optimized paragraph summarizing the difference: The key distinction is that Any specifies the type can be any non-nullable type, requiring you to potentially check/cast within the generic function. Conversely, (star projection) indicates the type is unknown or irrelevant, limiting operations to type-agnostic interactions and treating elements as Any?. Therefore, choose Any when you need to work with the underlying type after a check or cast, and when you only need to perform generic operations without specific type knowledge.

Practical Examples and Use Cases

To solidify the understanding of difference between "" and “Any” in Kotlin generics, let’s explore some practical examples and use cases. Suppose you’re building a generic caching system. You might want to create a Cache class that can store objects of any type. If you use Any as the generic type parameter, you can store any non-nullable object in the cache. However, when you retrieve an object from the cache, you’ll need to cast it to the appropriate type before using it. Baeldung Kotlin Generics Tutorial

Consider a scenario where you’re writing a function that needs to log information about objects of different types. You might use Any as the generic type parameter to accept any object. Inside the function, you can use the toString() method to get a string representation of the object and log it. This approach allows you to log information about any object without having to write separate functions for each type. This approach promotes code reuse and simplifies your logging logic.

On the other hand, if you’re working with a data structure that you only need to inspect or iterate over without needing to know the specific type of elements, becomes valuable. For example, if you have a function that needs to count the number of elements in a List, you can use List<> as the parameter type. You don’t need to know the specific type of elements in the list to count them. This approach provides a more abstract and flexible way to handle the list, reducing the need for unnecessary type checks or casts. Real world examples of can also include logging contents of collections without modifying them or working with reflection, according to Effective Kotlin book. Effective Kotlin

  • Using Any allows you to work with any non-nullable type.
  • Using gives you an unknown type, limiting type-specific operations.
Infographic here
Best Practices and Considerations ---------------------------------

When deciding whether to use Any or in Kotlin generics, consider the specific requirements of your code. If you need to perform type-specific operations on the generic type, Any is the better choice. However, if you only need to perform type-agnostic operations, provides a more flexible and concise solution. It’s crucial to weigh the trade-offs between flexibility and type safety to make the right decision. In general, prefer using more specific type parameters when possible to improve type safety and reduce the need for explicit type checks or casts.

Another important consideration is the potential for null values. When using Any, you’re guaranteed that the generic type will be non-nullable. If you need to handle nullable types, you can use Any? instead. With , the inferred type is Any?, so you need to be prepared to handle potential null values. Always be mindful of null safety when working with generics, especially when using . Always use safe calls or null checks when interacting with the unknown types.

Here’s an ordered list of steps to help you choose between Any and :

  1. Determine if you need to perform type-specific operations on the generic type.
  2. If yes, use Any (or Any? if you need to handle nullable types).
  3. If no, consider using for a more flexible and concise solution.
  4. Always be mindful of null safety when working with generics.
  • Prefer more specific type parameters for improved type safety.
  • Consider nullability when choosing between Any and .

FAQ

What is the difference between Any and in Kotlin generics?
Any represents any non-nullable type, while represents an unknown type.
When should I use Any?
Use Any when you need to perform type-specific operations on the generic type.
When should I use ?
Use when you only need to perform type-agnostic operations and don't care about the specific type.
Does allow null values?
Yes, the inferred type for is Any?, so you need to handle potential null values.
Understanding the **difference between "" and "Any" in Kotlin generics** is crucial for writing efficient and type-safe code. By recognizing when to use each construct, you can leverage the full power of Kotlin's generics system. We've explored how Any provides a concrete lower bound, allowing type-specific operations after checking or casting, while offers flexibility by representing an unknown type, suitable for type-agnostic interactions. Choosing the right approach depends on the specific requirements of your code, and a careful consideration of type safety and nullability.

Now that you’ve deepened your understanding of Kotlin generics, consider how you can apply this knowledge to your current projects. Are there areas where you can refactor code to leverage the flexibility of or the type safety of Any? Experiment with these concepts in your own code and see how they can improve your code’s readability, maintainability, and overall robustness. Explore related topics such as variance and reified types to further expand your knowledge of Kotlin generics. You can also read more about advanced Kotlin features to take your development skills to the next level.

Question & Answer :
I am not sure I fully understand the difference between SomeGeneric<*> and SomeGeneric<Any>. I think * represents anything (wild card) and Any represents the object which ALL objects inherit from. So it seems they should be the same, but are they?

It may be helpful to think of the star projection as a way to represent not just any type, but some fixed type which you don’t know what is exactly.

For example, the type MutableList<*> represents the list of something (you don’t know what exactly). So if you try to add something to this list, you won’t succeed. It may be a list of Strings, or a list of Ints, or a list of something else. The compiler won’t allow to put any object in this list at all because it cannot verify that the list accepts objects of this type. However, if you attempt to get an element out of such list, you’ll surely get an object of type Any?, because all objects in Kotlin inherit from Any.

From asco comment below:

Additionally List<*> can contain objects of any type, but only that type, so it can contain Strings (but only Strings), while List<Any> can contain Strings and Integers and whatnot, all in the same list.