Chapter 11: Generics
The chapter introduces two Kotlin generics concepts: reified type parameters and the distinction between declaration-site and use-site variance.
After this chapter you will be able to
- Reified Types and Erasure. Explain that reified type parameters let an inline function refer at run time to the specific type used as a type argument, whereas type arguments of normal classes and functions are erased at run time.
- Declaration and Use-Site Variance. Distinguish declaration-site variance from use-site variance: both concern subtype relationships between generic types with different type arguments, but one specifies the relationship on the generic declaration and the other for a particular use.
- Generic parameters and arguments. Explain how a generic type uses type parameters and how specific type arguments describe an instance, such as List<String> or Map<String, Person>.
- Inferred and explicit type arguments. Describe when Kotlin infers a type argument and why creating an empty list requires an explicit type, either on the variable declaration or on the list-creating function.
- Generic Function Type Parameters. Explain how a generic function uses a type parameter to work with lists of different element types, and how a call determines its specific type argument.
- Generic class declaration syntax. Describe how to declare a generic class or interface and where its type parameters can be used.
- Generic base type arguments. Explain what type argument a subclass must provide for a generic base type, contrasting a fixed type with a new type parameter.
- Upper-bound type constraints. Explain how an upper bound restricts a generic type argument and how Kotlin declares one.
- Operations enabled by bounds. Explain why a bound lets generic code use the bound's operations, including comparing two values of type T in max.
- Non-null generic type bounds. Explain why an unconstrained type parameter can accept nullable type arguments and how a non-null upper bound prevents that.
- Definitely non-null use-site types. Distinguish a non-null constraint on the whole type parameter from a definitely non-nullable use of that parameter when implementing a Java interface.
- Runtime loss of type arguments. Explain that JVM generics normally use type erasure, so an instance of a generic class does not preserve its type arguments at run time.
- Inline functions and reified arguments. State that an inline function can be declared so its type arguments are not erased; Kotlin calls those type arguments reified.
- Runtime generic type erasure. Explain that a generic instance retains its base type but not its type arguments at run time, even though the compiler normally enforces those arguments when values are stored.
- Generic runtime type checks. Describe why an is check cannot generally test a particular generic type argument, how List<*> checks only the base type, and why a check such as List<Int> is allowed when the argument is already known at compile time.
- Unchecked generic casts. Trace why an as or as? cast to a generic type produces an unchecked-cast warning and why a wrongly typed list can fail later when its elements are used.
- Inline reification and erasure. Explain why a regular generic function cannot check a value against its type parameter at run time, but an inline function with a reified type parameter can.
- Reified adapters for class parameters. Explain how a reified type parameter lets a wrapper such as loadService accept a service type as a type argument while still supplying the java.lang.Class required by ServiceLoader.
- Reified Type Parameters in Accessors. Explain how marking a generic property inline and its type parameter reified lets an accessor refer to the specific class used as the type argument. Describe how the canonical extension property uses this to return that class’s canonical name.
- Reified Type Parameter Boundaries. Distinguish the permitted uses of a reified type parameter from the operations and declarations this section rules out.
- Inlining Consequences for Lambdas. Explain why using a reified type parameter affects lambdas passed to the function and when noinline is useful.
- Variance and generic type relationships. Explain that variance describes how types with the same base type but different type arguments relate to one another, such as List<String> and List<Any>.
- List argument type safety. Explain why a List<String> can be passed to a function expecting List<Any>, but a MutableList<String> cannot be passed to one expecting MutableList<Any>. Describe the type inconsistency that mutation could cause.
- Classes and constructed types. Distinguish a class from a type: a class name can form both non-null and nullable types, while a generic class needs type arguments to form a type.
- Subtypes and value substitution. Explain the subtype test and how it governs assigning a value or passing an argument to a function.
- Invariant and covariant generics. Distinguish the subtype relationships stated here for invariant MutableList and covariant read-only List.
- Covariant subtype relationship. Explain that a covariant generic class preserves the subtype relationship between its type arguments, and describe why an invariant `Herd<Cat>` cannot be passed where `Herd<Animal>` is expected.
- Out positions and safety. Explain how `out` declares a type parameter covariant and why an externally visible API may produce values of that type but not consume them. Contrast the read-only `List<T>` with `MutableList<T>`.
- Reversed consumer subtyping. Explain why a consumer of a general type can be used where a consumer of a more specific type is required. State the reversed subtyping rule using the comparator or Consumer example.
- Input-only type parameter. Explain what marking a type parameter with in means and how its permitted positions relate to contravariance.
- Declaration and use-site variance. Distinguish variance specified once on a class declaration from variance specified for a particular use of a type parameter, and explain why the latter is useful for an otherwise invariant type.
- Out-projected copy source. Explain why the source of copyData can be out-projected and what operations that projection permits or prohibits.
- In-projected copy destination. Describe how an in projection expresses the destination’s consumer role in copyData and permits a destination whose element type is a supertype of the copied elements.
- Unknown mutable element types. Distinguish MutableList<*> from MutableList<Any?> and explain why code can read elements from the former but cannot add values to it.
- Mixed validator cast risks. Explain why a FieldValidator<*> retrieved from a map cannot directly validate a string, and why an explicit cast does not make a mismatched validator safe.
- Encapsulated validator registry. Describe how enclosing the validator map behind generic registration and retrieval methods makes its public API type-safe despite an internal unchecked cast.
- Type alias syntax and purpose. Explain how to declare a type alias and why one might be useful for a long generic or functional type signature.
- Alias tradeoffs and type safety. Distinguish a type alias from a type-safe new type, and describe the readability tradeoff in introducing an alias.
What it builds on
- Platform types (chapter 7) · The meaning of platform types in Kotlin–Java interoperation.
- Function types specify the parameter types and return values of a lambda (chapter 10) · Function types specify the parameter and return types of a lambda.
- Extension properties (chapter 3) · Extension properties are declarations associated with a receiver type.
- Ordering operators: compareTo (<, >, ⇐, and >=) (chapter 9) · Introduces the comparison convention that translates > to compareTo.
- Nullability and Java (chapter 7) · Java interoperability and nullability annotations.
- Inlining means substituting a function body to each call site (chapter 10) · Introduces inline functions.
- Deciding when to declare functions as inline (chapter 10) · Inlining can provide performance benefits when lambda arguments are inlined.
- Computing properties instead of storing their values: Custom accessors (chapter 2) · Property accessors can provide custom implementations.
Section by section
Introduction
The chapter introduces two Kotlin generics concepts: reified type parameters and the distinction between declaration-site and use-site variance.
- Reified Types and Erasure: Explain that reified type parameters let an inline function refer at run time to the specific type used as a type argument, whereas type arguments of normal classes and functions are erased at run time.
Why it matters: This distinction explains why an inline function with a reified parameter can refer to a type argument at run time when an ordinary generic function cannot. - Declaration and Use-Site Variance: Distinguish declaration-site variance from use-site variance: both concern subtype relationships between generic types with different type arguments, but one specifies the relationship on the generic declaration and the other for a particular use.
Why it matters: The distinction frames why a function may or may not accept a generic value with a different type argument.
Key terms: reified type parameters, type arguments, inline function, type erasure, declaration-site variance, use-site variance, type argument, subtype, Java’s wildcards
11.1 Creating types with type arguments: Generic type parameters
Introduces generic type parameters and arguments, shows when Kotlin can infer type arguments, and explains why Kotlin has no raw types.
- Generic parameters and arguments: Explain how a generic type uses type parameters and how specific type arguments describe an instance, such as List<String> or Map<String, Person>.
Why it matters: Type arguments make the types represented by a generic value explicit. - Inferred and explicit type arguments: Describe when Kotlin infers a type argument and why creating an empty list requires an explicit type, either on the variable declaration or on the list-creating function.
Why it matters: It explains why some generic declarations need a written type while others do not. - Kotlin and Java raw types: Distinguish Kotlin's requirement for defined type arguments from Java's raw types, and state how Kotlin treats a raw-typed value received from Java.
Why it matters: This distinction helps explain what happens when Kotlin encounters older Java generic code.
Key terms: generics, type parameters, type arguments, List<String>, Map<K, V>, type inference, type argument, listOf, raw type, Any!
11.1.1 Functions and properties that work with generic types
This section shows how generic functions and extension properties use type parameters, how the compiler infers those parameters at calls, and why ordinary properties cannot declare them.
- Generic Function Type Parameters: Explain how a generic function uses a type parameter to work with lists of different element types, and how a call determines its specific type argument.
Why it matters: This lets one function retain the element type of whichever list it is called on. - Generic Lambda Parameter Inference: Trace how the compiler determines the lambda parameter type when a generic collection function such as filter is called on a List<String>.
Why it matters: The receiver’s element type can determine the type used inside a lambda without an explicit annotation. - Generic Declaration Sites and Properties: Distinguish where type parameters can be declared, including why a generic extension property is allowed but a generic non-extension property is not.
Why it matters: This distinction helps you recognize which declarations may introduce their own type parameter.
Key terms: generic function, type parameter, type argument, List<T>, slice, type inference, filter, (T) -> Boolean, lambda parameter, List<String>
11.1.2 Generic classes are declared with the angle bracket syntax
This subsection shows how to declare generic classes and interfaces and how to supply type arguments when inheriting from generic types.
- Generic class declaration syntax: Describe how to declare a generic class or interface and where its type parameters can be used.
Why it matters: This is the syntax behind the generic declarations used throughout the chapter. - Generic base type arguments: Explain what type argument a subclass must provide for a generic base type, contrasting a fixed type with a new type parameter.
Why it matters: The chosen argument determines the element types exposed through an inherited generic interface. - Self type as argument: Describe how a class can use its own type as an argument to a generic interface, using Comparable and String as the example.
Why it matters: Comparable shows that a generic argument can name the implementing class itself.
Key terms: generic class, generic interface, type parameter, angle brackets, type argument, generic parameter, base type, StringList, ArrayList, Comparable
11.1.3 Restricting the type a generic class or function can use: Type parameter constraints
This section explains how upper bounds restrict generic type arguments and make operations on those arguments available inside a generic function.
- Upper-bound type constraints: Explain how an upper bound restricts a generic type argument and how Kotlin declares one.
Why it matters: A bound lets a generic function accept the kinds of values it can actually handle. - Operations enabled by bounds: Explain why a bound lets generic code use the bound's operations, including comparing two values of type T in max.
Why it matters: The constraint both makes an operation available in the function and prevents calls with unsuitable types. - Multiple interface constraints: Describe why one type parameter may need multiple constraints and what that permits in the CharSequence and Appendable example.
Why it matters: Multiple bounds let one generic function require both reading and modifying capabilities.
Key terms: type parameter constraint, upper bound, type argument, subtype, Comparable<T>, max, compareTo, multiple constraints, CharSequence, Appendable
11.1.4 Excluding nullable type arguments by explicitly marking type parameters as non-null
This section explains how to exclude nullable generic type arguments and how to require a non-null value at a specific use site when implementing a Java interface.
- Non-null generic type bounds: Explain why an unconstrained type parameter can accept nullable type arguments and how a non-null upper bound prevents that.
Why it matters: It lets you choose whether users of a generic declaration may supply nullable types. - Definitely non-null use-site types: Distinguish a non-null constraint on the whole type parameter from a definitely non-nullable use of that parameter when implementing a Java interface.
Why it matters: It preserves a Java interface’s distinction between a method that requires a non-null value and other uses that allow nullable values.
Key terms: type parameter, type argument, upper bound, Any?, Any, T : Any, definitely non-nullable, use site, T & Any, nullability annotations
11.2 Generics at run time: Erased and reified type parameters
Introduces JVM type erasure and the possibility of retaining a function’s type arguments at run time with reified type parameters in an inline function.
- Runtime loss of type arguments: Explain that JVM generics normally use type erasure, so an instance of a generic class does not preserve its type arguments at run time.
Why it matters: This explains why a generic class instance normally cannot supply its type arguments at run time. - Inline functions and reified arguments: State that an inline function can be declared so its type arguments are not erased; Kotlin calls those type arguments reified.
Why it matters: Reified type arguments are the exception this section introduces to the usual loss of type arguments at run time.
Key terms: type erasure, type arguments, run time, inline function, reified
11.2.1 Limitations to finding type information of a generic class at run time: Type checks and casts
This section explains how erased generic type arguments limit runtime type checks and casts, while allowing checks when the compiler already knows the type argument.
- Runtime generic type erasure: Explain that a generic instance retains its base type but not its type arguments at run time, even though the compiler normally enforces those arguments when values are stored.
Why it matters: Erasure explains why the compiler can enforce a list’s declared element type without making that element type discoverable from the list at run time. - Generic runtime type checks: Describe why an is check cannot generally test a particular generic type argument, how List<*> checks only the base type, and why a check such as List<Int> is allowed when the argument is already known at compile time.
Why it matters: This distinction lets you tell a valid list check from an attempt to inspect an erased element type. - Unchecked generic casts: Trace why an as or as? cast to a generic type produces an unchecked-cast warning and why a wrongly typed list can fail later when its elements are used.
Why it matters: An unchecked-cast warning signals that success at the cast does not guarantee the list’s elements have the requested type.
Key terms: erased, type arguments, run time, List<String>, List<Int>, is checks, star-projection syntax, List<*>, as, as?
11.2.2 Functions with reified type parameters can refer to actual type arguments at run time
Explains how inline functions can reify type parameters so their actual type arguments can be used in run-time checks despite generic type erasure.
- Inline reification and erasure: Explain why a regular generic function cannot check a value against its type parameter at run time, but an inline function with a reified type parameter can.
Why it matters: This explains how a type check such as `value is T` can work in a reified inline function without contradicting type erasure. - Filtering by reified type: Describe how `filterIsInstance<String>` uses its type argument to select values from a collection and determine the result type.
Why it matters: The example makes the run-time use of a reified type argument concrete. - Reified function constraints: Explain why functions with reified type parameters must be inline and cannot be called from Java, and distinguish this use of `inline` from lambda-related performance optimization.
Why it matters: This prevents confusing reification’s need for inlining with the separate performance reason for inlining lambdas.
Key terms: type erasure, inline function, reified type parameter, type argument, filterIsInstance, List<String>, inline, Java code
11.2.3 Avoiding java.lang.Class parameters by replacing class references with reified type parameters
This section shows how a reified type parameter can make a Java API that requires a java.lang.Class easier to call.
- Reified adapters for class parameters: Explain how a reified type parameter lets a wrapper such as loadService accept a service type as a type argument while still supplying the java.lang.Class required by ServiceLoader.
Why it matters: It explains how Kotlin can offer a shorter call to a Java API without changing the class object that API needs.
Key terms: reified type parameter, java.lang.Class, ::class.java, ServiceLoader, loadService
11.2.4 Declaring accessors with reified type parameters
This section shows that an inline property accessor with a reified type parameter can refer to the class supplied as its type argument.
- Reified Type Parameters in Accessors: Explain how marking a generic property inline and its type parameter reified lets an accessor refer to the specific class used as the type argument. Describe how the canonical extension property uses this to return that class’s canonical name.
Why it matters: It lets a property offer convenient access to information about its generic type argument’s class.
Key terms: inline, reified type parameters, property accessor, extension property, canonicalName, T::class.java
11.2.5 Reified type parameters come with restrictions
This section identifies what reified type parameters can and cannot be used for, then explains why their inline-function requirement can make noinline necessary for lambdas.
- Reified Type Parameter Boundaries: Distinguish the permitted uses of a reified type parameter from the operations and declarations this section rules out.
Why it matters: These boundaries help you tell whether a proposed use of a reified type parameter is valid. - Inlining Consequences for Lambdas: Explain why using a reified type parameter affects lambdas passed to the function and when noinline is useful.
Why it matters: The inline-only rule affects how you design a reified function that takes lambdas.
Key terms: reified type parameter, is, !is, as, as?, ::class, inline functions, lambdas, noinline modifier
11.3 Variance describes the subtyping relationship between generic arguments
This section defines variance as the relationship between generic types with different type arguments and explains why that relationship matters when designing APIs.
- Variance and generic type relationships: Explain that variance describes how types with the same base type but different type arguments relate to one another, such as List<String> and List<Any>.
Why it matters: This gives you the question that variance answers before you encounter Kotlin’s specific variance rules. - Variance in API design: Explain why understanding variance matters when writing generic classes or functions: it helps avoid APIs that inconvenience users through unnecessary restrictions or violate their type-safety expectations.
Why it matters: A generic API should be convenient to use without compromising type safety.
Key terms: variance, base type, type arguments, generic classes, generic functions, type-safety expectations
11.3.1 Variance determines whether it is safe to pass an argument to a function
The section uses read-only and mutable lists to show when a list with a more specific element type can safely be passed to a function.
- List argument type safety: Explain why a List<String> can be passed to a function expecting List<Any>, but a MutableList<String> cannot be passed to one expecting MutableList<Any>. Describe the type inconsistency that mutation could cause.
Why it matters: This distinction explains why a function’s choice between List and MutableList affects which arguments callers can safely pass.
Key terms: List<Any>, List<String>, MutableList<Any>, MutableList<String>, read-only list, type inconsistencies
11.3.2 Understanding the differences between classes, types, and subtypes
This section distinguishes classes from types and uses subtyping to explain assignment, nullability, and the basic relationships between generic types.
- Classes and constructed types: Distinguish a class from a type: a class name can form both non-null and nullable types, while a generic class needs type arguments to form a type.
Why it matters: The distinction lets you reason about relationships between specific types rather than just their classes. - Subtypes and value substitution: Explain the subtype test and how it governs assigning a value or passing an argument to a function.
Why it matters: This test gives you a practical way to decide whether a value can be used where another type is expected. - Nullable type subtyping: Explain why a non-null type is a subtype of its nullable version even though both correspond to one class.
Why it matters: Nullability shows why subtype relationships cannot be inferred solely from the class hierarchy. - Invariant and covariant generics: Distinguish the subtype relationships stated here for invariant MutableList and covariant read-only List.
Why it matters: The subtype relationship between type arguments does not by itself determine the relationship between every pair of generic types.
Key terms: class, type, type argument, nullable type, subtype, supertype, assignment, function parameter, non-null type, subclass
11.3.3 Covariance preserves the subtyping relation
Explains how Kotlin’s `out` modifier preserves subtyping for a generic class and why the class’s externally visible uses of its type parameter must be restricted to output positions.
- Covariant subtype relationship: Explain that a covariant generic class preserves the subtype relationship between its type arguments, and describe why an invariant `Herd<Cat>` cannot be passed where `Herd<Animal>` is expected.
Why it matters: Covariance lets a herd of cats be used where code only needs a herd of animals, without an unsafe cast. - Out positions and safety: Explain how `out` declares a type parameter covariant and why an externally visible API may produce values of that type but not consume them. Contrast the read-only `List<T>` with `MutableList<T>`.
Why it matters: The `out` restriction explains why reading an animal from a cat herd is safe but accepting arbitrary animals into it would not be. - Constructor and API exceptions: Distinguish a plain constructor parameter from a constructor parameter declared as a property, and explain why private members do not impose the same variance restriction as externally visible members.
Why it matters: These distinctions help identify which declarations actually prevent a class from being marked `out`.
Key terms: covariant, subtype, invariant, Herd<T>, out, out position, in position, List<T>, MutableList<T>, constructor parameters
11.3.4 Contravariance reverses the subtyping relation
This section explains how contravariance reverses generic subtyping, why input-only type parameters allow it, and how function types combine contravariance with covariance.
- Reversed consumer subtyping: Explain why a consumer of a general type can be used where a consumer of a more specific type is required. State the reversed subtyping rule using the comparator or Consumer example.
Why it matters: This rule lets you recognize when a general-purpose consumer is safe to pass to code expecting a more specific one. - Input-only type parameter: Explain what marking a type parameter with in means and how its permitted positions relate to contravariance.
Why it matters: The input-only restriction explains why Kotlin permits the contravariant subtype relationship. - Function parameter and return variance: Describe how a function type is contravariant in its parameter type and covariant in its return type, using the section’s animal-accepting lambda example.
Why it matters: Function types show that different type parameters of one generic type can have different variance.
Key terms: contravariance, Consumer<T>, Comparator<T>, subtype, in keyword, in positions, type parameter, (P) -> R, Function1<P, R>, in
11.3.5 Specifying variance for type occurrences via use-site variance
This section explains how Kotlin use-site projections express producer or consumer roles for particular uses of otherwise invariant generic types.
- Declaration and use-site variance: Distinguish variance specified once on a class declaration from variance specified for a particular use of a type parameter, and explain why the latter is useful for an otherwise invariant type.
Why it matters: A type that must be invariant overall can still be used more flexibly when a particular function needs only one of its roles. - Out-projected copy source: Explain why the source of copyData can be out-projected and what operations that projection permits or prohibits.
Why it matters: The projection lets the copy function accept a broader range of source and destination element types without allowing unsafe writes to the source. - In-projected copy destination: Describe how an in projection expresses the destination’s consumer role in copyData and permits a destination whose element type is a supertype of the copied elements.
Why it matters: It expresses the destination’s writing role while accepting collections of broader element types.
Key terms: declaration-site variance, use-site variance, type projection, MutableList, out projection, source, copyData, in projection, consumer, destination
11.3.6 Star projection: Using the * character to indicate a lack of information about a generic argument
Explains what star projections permit when a generic argument is unknown and how to safely use a container of validators for different types.
- Unknown mutable element types: Distinguish MutableList<*> from MutableList<Any?> and explain why code can read elements from the former but cannot add values to it.
Why it matters: An unknown element type limits what you can safely do with a mutable collection. - Appropriate star projection use: Describe when a star projection is useful instead of introducing a generic type parameter, and explain the restriction on a star-projected consumer.
Why it matters: It helps you choose concise signatures without implying operations the unknown type cannot safely support. - Mixed validator cast risks: Explain why a FieldValidator<*> retrieved from a map cannot directly validate a string, and why an explicit cast does not make a mismatched validator safe.
Why it matters: An unchecked cast can silence the immediate type error without protecting validation calls. - Encapsulated validator registry: Describe how enclosing the validator map behind generic registration and retrieval methods makes its public API type-safe despite an internal unchecked cast.
Why it matters: Localizing an unchecked operation lets callers use a safe API for a container holding different generic types.
Key terms: star projection, MutableList<*>, MutableList<Any?>, out-projected type, Any?, generic type parameter, Consumer<in T>, <in Nothing>, FieldValidator<*>, unchecked cast
11.3.7 Type aliases
This section shows how type aliases make complex type signatures easier to read while explaining why they do not create distinct, type-safe types.
- Type alias syntax and purpose: Explain how to declare a type alias and why one might be useful for a long generic or functional type signature.
Why it matters: An alias can make a cumbersome signature easier to recognize and reuse. - Alias tradeoffs and type safety: Distinguish a type alias from a type-safe new type, and describe the readability tradeoff in introducing an alias.
Why it matters: A descriptive alias can clarify intent, but it cannot enforce that intent at compile time.
Key terms: type alias, typealias, underlying type, NameCombiner, type safety, inline classes, ValidatedInput
11.4 Summary
Where this is used later
- Member extension functions: Internal DSL for SQL (chapter 13) · Reading generic types such as Column<Int>.
- JSON parsing and object deserialization (chapter 12) · Reified type parameters make actual type arguments available at run time.
- Reflection: Introspecting Kotlin objects at run time (chapter 12) · The discussion of reflection examines class information at run time in more detail.
- The Kotlin reflection API: KClass, KCallable, KFunction, and KProperty (chapter 12) · The Kotlin class-reference use connects to the reflection APIs introduced there.
- Passing classes as annotation parameters to further control behavior (chapter 12) · Assumes the idea of covariance expressed with out.
- Generic classes as annotation parameters (chapter 12) · Star projections for unknown generic arguments.
Concepts explained in this chapter
- type argumentA type argument is an argument supplied to a parameterized construct to specify a type or constrain the kinds of values it accepts.
- genericsA generic function is a function declared with one or more type parameters so it can operate on values of different types.
- invariant generic classAn invariant type does not allow a parameterized type to substitute a subtype or supertype for its type argument.
- subtypingA subtyping relation specifies when one type can be used wherever another type is expected.
- star projectionA star projection is Kotlin syntax that represents a generic type argument whose specific type is unknown while preserving safe variance information.
- type erasureType erasure is an implementation technique in which generic type arguments are removed from compiled representations and are unavailable at run time.
- covarianceCovariance is a generic type relationship in which subtyping between parameterized types preserves the subtyping relationship between their type arguments.
- contravarianceA contravariant type parameter is a generic type parameter that reverses the subtype direction of its type arguments and is restricted to in positions.
- reified type parameterA reified type parameter is an inline-function type parameter whose actual type information is available at runtime for restricted operations such as type checks and casts.
- unchecked castAn unchecked cast is a cast whose generic type compatibility cannot be verified by the compiler or runtime because the relevant type information is unavailable.
- out keywordThe out modifier declares covariant use of a Kotlin type parameter so a parameterized type can accept subtype arguments.
- inline functionAn inline function is a Kotlin function whose body can be substituted at its call sites by the compiler and which can declare reified type parameters.
- declaration-site varianceDeclaration-site variance specifies at a generic type declaration whether different instantiations are related as subtypes or supertypes based on their type arguments.
- use-site varianceUse-site variance specifies a variance constraint for a particular occurrence of a generic type parameter rather than for its declaration.
- in positionAn in position is a type-parameter usage position in which values of the parameterized type are consumed rather than produced.
- out positionAn out position is a type-parameter usage position in which values of the parameterized type are produced rather than consumed.
- superclassA base class is a class from which one or more subclasses inherit members and behavior.
- non-nullable typeA non-nullable type is a Kotlin type whose values are not permitted to be null by the type system.
- type-safe APIA type-safe API is an interface whose operations prevent invalid type combinations through compile-time type checking.
- upper boundAn upper bound is a constraint specifying a supertype that every valid substitution for a type parameter must satisfy.
- type aliasA type alias is a Kotlin declaration that gives an alternative name to an existing type without creating a distinct type.
- FunctionN interfaceA FunctionN interface is a compiler-generated Kotlin interface representing a function value with a specific number of parameters and an invoke operation.
- type checkingA type check is a Kotlin operation that tests whether a value has a specified runtime type.
- ClassCastExceptionClassCastException is a JVM runtime exception thrown when a value is used as an incompatible type.
- type projectionA type projection is a restricted view of a parameterized type that permits only operations allowed by a use-site variance constraint.
- atomic typeA type is a classification that specifies the values an expression or variable can represent and the operations allowed on them.
- classA class is a Kotlin declaration that defines the structure and behavior of objects through members such as properties, functions, and constructors.
- listMutableList is a Kotlin mutable collection type whose elements can be read and modified through its invariant type parameter.
- type inferenceType inference is the compiler's ability to determine expression types without requiring explicit type annotations everywhere.
- extension propertyAn extension property is a Kotlin property that provides property-like access to an existing type without storing state in that type.
- accessor methodA property accessor is a getter or setter that defines how a Kotlin property value is read or changed.
- data conversionData conversion is the transformation of a value or data from one type, format, or representation to another, explicitly or implicitly.
- nullable typeA nullable type is a type whose values may include null and whose unsafe operations are restricted by the type system.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
