0% found this document useful (0 votes)
790 views1,158 pages

Kotlin Reference

Uploaded by

seila roger
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
790 views1,158 pages

Kotlin Reference

Uploaded by

seila roger
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1158

Kotlin

Language Documentation 1.5.31


Table of Contents

Kotlin docs 47

Get started with Kotlin 48

Learn Kotlin fundamentals 48

Create your powerful application with Kotlin 48

Is anything missing? 52

Multiplatform programming 53

Use cases 58

What's next? 59

Sample projects 59

Kotlin Multiplatform Mobile 59

Get started with Kotlin Multiplatform Mobile 60

Supported platforms 60

Sample projects 60

Videos 60

Community 60

Security 61

Kotlin for server side 61

Frameworks for server-side development with Kotlin 61

Deploying Kotlin server-side applications 62

Users of Kotlin on the server side 62

Next steps 62

Kotlin for Android 63

Kotlin for JavaScript 63

Use cases for Kotlin/JS 64

Kotlin/JS frameworks 65

Kotlin/JS, Today and Tomorrow 66

2
Get started with Kotlin/JS 67

Hands-on labs for Kotlin/JS 67

New Kotlin/JS IR compiler 67

Join the Kotlin/JS community 67

Kotlin Native 67

Why Kotlin/Native? 68

Target platforms 68

Interoperability 68

Sharing code between platforms 69

How to start 69

Sample projects 69

Kotlin for data science 70

Interactive editors 70

Libraries 72

Kotlin for competitive programming 73

Simple example: Reachable Numbers problem 74

Functional operators example: Long Number problem 75

More tips and tricks 76

Learning Kotlin 77

What's new in Kotlin 1.5.30 77

Language features 78

Kotlin/JVM 83

Kotlin/Native 84

Kotlin Multiplatform 87

Kotlin/JS 89

Gradle 90

Standard library 93

Serialization 1.3.0-RC 97

3
What's new in Kotlin 1.5.20 97

Kotlin/JVM 98

Kotlin/Native 100

Kotlin/JS 101

Gradle 102

Standard library 102

What's new in Kotlin 1.5.0 103

Language features 103

Kotlin/JVM 106

Kotlin/Native 109

Kotlin/JS 110

Kotlin Multiplatform 111

Standard library 111

kotlin-test library 117

kotlinx libraries 120

Migrating to Kotlin 1.5.0 122

What's new in Kotlin 1.4.30 123

Language features 123

Kotlin/JVM 126

Kotlin/Native 127

Kotlin/JS 127

Gradle project improvements 128

Standard library 128

Serialization updates 130

What's new in Kotlin 1.3 131

Coroutines release 131

Kotlin/Native 131

Multiplatform projects 131

Contracts 132

4
Capturing when subject in a variable 134

@JvmStatic and @JvmField in companions of interfaces 134

Nested declarations in annotation classes 134

Parameterless main 135

Functions with big arity 135

Progressive mode 135

Inline classes 136

Unsigned integers 136

@JvmDefault 137

Standard library 138

Tooling 140

What's new in Kotlin 1.2 141

Table of contents 141

Multiplatform projects (experimental) 141

Other language features 142

Standard library 145

JVM backend 148

JavaScript backend 149

Tools 149

What's new in Kotlin 1.1 150

Table of contents 150

JavaScript 150

Coroutines (experimental) 150

Other language features 151

Standard library 157

JVM Backend 161

JavaScript backend 162

What's new in Kotlin for KMM 163

Kotlin 1.5.30 for KMM 163

5
Kotlin 1.5.20 for KMM 164

Kotlin 1.5.0 for KMM 165

Kotlin 1.4.30 for KMM 165

Kotlin 1.4.20 for KMM 166

What's new in Kotlin plugin 2021.2 166

Performance improvements 167

Better debugging experience 167

Remote development support 168

Kotlin plugin in the IntelliJ IDEA repository 169

Other IDE improvements 169

What's new in Kotlin plugin 2021.1 170

Performance improvements 170

Evaluation of custom getters during debugging 171

Improved Change Signature refactoring 171

Code completion for type arguments 172

UML diagrams for Kotlin classes 173

Other platform enhancements 173

What's new in Kotlin plugin 2020.3 174

New types of inline refactorings 174

Structural search and replace 174

EditorConfig support 174

Project templates for Jetpack Compose for Desktop 175

Basic syntax 175

Package definition and imports 176

Program entry point 176

Print to the standard output 176

Functions 177

Variables 178

6
Creating classes and instances 178
Comments 179

String templates 180

Conditional expressions 180

for loop 180

while loop 181

when expression 181

Ranges 182

Collections 183

Nullable values and null checks 184

Type checks and automatic casts 185

Idioms 186

Create DTOs (POJOs/POCOs) 186

Default values for function parameters 187

Filter a list 187

Check the presence of an element in a collection 187

String interpolation 187

Instance checks 187

Read-only list 188

Read-only map 188

Access a map entry 188

Traverse a map or a list of pairs 188

Iterate over a range 188

Lazy property 188

Extension functions 189

Create a singleton 189

Instantiate an abstract class 189

If-not-null shorthand 189

If-not-null-else shorthand 190

7
Execute a statement if null 190

Get first item of a possibly empty collection 190

Execute if not null 190

Map nullable value if not null 190

Return on when statement 190

try-catch expression 191

if expression 191

Builder-style usage of methods that return Unit 191

Single-expression functions 191

Call multiple methods on an object instance (with) 192

Configure properties of an object (apply) 192

Java 7's try-with-resources 192

Generic function that requires the generic type information 193

Nullable Boolean 193

Swap two variables 193

Mark code as incomplete (TODO) 193

What’s next? 193

Coding conventions 194

Configure style in IDE 194

Source code organization 194

Naming rules 195

Formatting 197

Documentation comments 208

Avoid redundant constructs 208

Idiomatic use of language features 209

Coding conventions for libraries 214

Basic types 214

Numbers 214

Booleans 221

8
Characters 222

Strings 222

Arrays 224

Type checks and casts 225

is and !is operators 225

Smart casts 226

"Unsafe" cast operator 227

"Safe" (nullable) cast operator 227

Type erasure and generic type checks 227

Unchecked casts 228

Conditions and loops 229

If expression 229

When expression 230

For loops 232

While loops 233

Break and continue in loops 233

Returns and jumps 233

Break and continue labels 234

Return at labels 234

Exceptions 236

Exception classes 236

Checked exceptions 237

The Nothing type 238

Java interoperability 238

Packages and imports 238

Default imports 239

Imports 239

Visibility of top-level declarations 240

9
Classes 240

Constructors 240

Creating instances of classes 243

Class members 243

Inheritance 244

Abstract classes 244

Companion objects 244

Inheritance 245

Overriding methods 245

Overriding properties 246

Derived class initialization order 246

Calling the superclass implementation 247

Overriding rules 248

Properties 249

Declaring properties 249

Getters and setters 249

Compile-time constants 251

Late-initialized properties and variables 252

Overriding properties 253

Delegated properties 253

Interfaces 253

Implementing interfaces 253

Properties in interfaces 253

Interfaces Inheritance 254

Resolving overriding conflicts 254

Functional (SAM) interfaces 255

SAM conversions 255

Functional interfaces vs. type aliases 256

10
Visibility modifiers 257

Packages 257

Class members 258

Modules 259

Extensions 259

Extension functions 259

Extensions are resolved statically 260

Nullable receiver 261

Extension properties 261

Companion object extensions 262

Scope of extensions 262

Declaring extensions as members 263

Note on visibility 264

Data classes 264

Properties declared in the class body 265

Copying 266

Data classes and destructuring declarations 266

Standard data classes 266

Sealed classes 266

Location of direct subclasses 267

Sealed classes and when expression 268

Generics: in, out, where 268

Variance 269

Type projections 272

Generic functions 273

Generic constraints 274

Type erasure 275

Nested and inner classes 275

11
Inner classes 276

Anonymous inner classes 276

Enum classes 276

Anonymous classes 277

Implementing interfaces in enum classes 277

Working with enum constants 278

Inline classes 278

Members 279

Inheritance 280

Representation 280

Inline classes vs type aliases 282

Object expressions and declarations 282

Object expressions 282

Object declarations 285

Delegation 287

Overriding a member of an interface implemented by delegation 287

Delegated properties 288

Standard delegates 289

Delegating to another property 290

Storing properties in a map 291

Local delegated properties 292

Property delegate requirements 292

Type aliases 296

Functions 297

Function usage 297

Function scope 302

Generic functions 303

12
Tail recursive functions 303

High-order functions and lambdas 304

Higher-order functions 304

Function types 305

Lambda expressions and anonymous functions 308

Inline functions 311

noinline 312

Non-local returns 312

Reified type parameters 314

Inline properties 315

Restrictions for public API inline functions 315

Operator overloading 315

Unary operations 316

Binary operations 317

Infix calls for named functions 321

Type-safe builders 321

How it works 322

Scope control: @DslMarker 324

Full definition of the com.example.html package 325

Null safety 327

Nullable types and non-null types 327

Checking for null in conditions 328

Safe calls 328

Elvis operator 329

The !! operator 330

Safe casts 330

Collections of a nullable type 330

Equality 330

13
Structural equality 331

Referential equality 331

Floating-point numbers equality 331

This expressions 331

Qualified this 332

Implicit this 332

Asynchronous programming techniques 333

Threading 333

Callbacks 334

Futures, promises, and others 334

Reactive extensions 335

Coroutines 335

Coroutines 336

How to start 337

Sample projects 337

Annotations 337

Usage 338

Constructors 338

Lambdas 339

Annotation use-site targets 340

Java annotations 341

Destructuring declarations 342

Example: returning two values from a function 343

Example: destructuring declarations and maps 344

Underscore for unused variables 344

Destructuring in lambdas 344

Reflection 345

JVM dependency 345

14
JVM dependency 345

Class references 346

Callable references 347

Kotlin Multiplatform 351

Tutorials 353

Getting started 353

Get familiar with KMM 353

Start KMM from scratch 353

Make an Android application work on iOS 354

Set up an environment for KMM development 354

Create your first multiplatform application – tutorial 356

Run your application 360

Run tests 365

Update your application 366

Next steps 370

Understand the KMM project structure 371

Root project 372

Shared module 373

Android application 378

iOS application 380

Make your Android application work on iOS – tutorial 383

Prepare an environment for development 383

Make your code cross-platform 384

Make your cross-platform application work on iOS 393

Enjoy the results – update the logic only once 403

What else to share? 407

What's next? 407

Connect to platform-specific APIs 407

15
Examples 408

Add dependencies to KMM modules 413

Multiplatform libraries 414

iOS dependencies 417

Android dependencies 422

Configure SQLDelight for data storage 424

Connect and configure SQLDelight 424

Create an SQLite driver 427

Table operations 428

Transactions 431

SQLDelight plugin for Android Studio 432

Use Ktor for networking 432

Connect Ktor 432

Set up an HTTP client 434

Create HTTP requests 437

Concurrency 439

Close the HTTP client 440

Publish KMM apps 440

Android app 440

iOS app 440

Concurrency overview 441

Rules for state sharing 442

Immutable and frozen state 442

Global state 444

Current and future models 445

Concurrent mutability 445

Atomics 446

Thread-isolated state 448

16
Low-level capabilities 449

Concurrency and coroutines 450

Coroutines 450

Multithreaded coroutines 453

Alternatives to kotlinx-coroutines 453

Samples 454

FAQ 458

What is KMM? 458

What is the KMM plugin? 458

What is Kotlin/Native and how does it relate to KMM? 459

What are the plans for KMM? 460

Can I run an iOS application on Microsoft Windows or Linux? 460

Where can I get complete examples to play with? 460

In which IDE should I work on my cross-platform app? 461

How can I write concurrent code in KMM projects? 461

How can I speed up my KMM module compilation for iOS? 461

Introduce your team to KMM 461

Start with empathy 462

Explain how it works 462

Show the value 462

Offer proof 463

Prepare for questions 463

Be supportive 465

Create a multiplatform library 465

What's next? 468

Discover your project 468

Multiplatform plugin 468

17
Targets 469

Source sets 469

Compilations 471

Share code on platforms 472

Share code on all platforms 473

Share code on similar platforms 473

Connect to platform-specific APIs 480

Rules for expected and actual declarations 482

Set up targets manually 483

Distinguish several targets for one platform 483

Add dependencies 484

Dependency on the standard library 485

Set dependencies on test libraries 485

Set a dependency on a kotlinx library 485

Configure compilations 486

Configure all compilations 487

Configure compilations for one target 488

Configure one compilation 488

Create a custom compilation 489

Include Java sources in JVM compilations 490

Configure interop with native languages 492

Compilation for Android 493

Compilation of the source set hierarchy 494

Run tests 495

Required dependencies 495

Run tests for one or more targets 495

Test shared code 495

18
Publish a multiplatform library 496

Structure of publications 497

Avoid duplicate publications 497

Publish an Android library 498

Create and publish a multiplatform library – tutorial 499

Set up the environment 499

Create a project 500

Write cross-platform code 501

Provide platform-specific implementations 502

Test your library 504

Publish your library to the local Maven repository 506

Add a dependency on the published library 507

Summary 507

What’s next? 508

Build final native binaries 508

Declare binaries 508

Access binaries 510

Export dependencies to binaries 511

Build universal frameworks 513

Build XCFrameworks 514

Supported platforms 516

Multiplatform Gradle DSL reference 517

Id and version 517

Top-level blocks 518

Targets 518

Source sets 527

Compilations 529

Dependencies 532

19
Language settings 534

Migrating multiplatform projects to Kotlin 1.4.0 535

For multiplatform project authors 535

For library authors 537

For build authors 538

For using the Kotlin/JS target 538

Tutorials for Kotlin Multiplatform 540

Get started with Kotlin/JVM 540

Create an application 540

Run the application 543

What's next? 544

Comparison to Java 544

Some Java issues addressed in Kotlin 545

What Java has that Kotlin does not 545

What Kotlin has that Java does not 545

What’s next? 546

Calling Java from Kotlin 546

Getters and setters 546

Methods returning void 547

Escaping for Java identifiers that are keywords in Kotlin 547

Null-safety and platform types 547

Mapped types 554

Java generics in Kotlin 556

Java arrays 557

Java varargs 558

Operators 558

Checked exceptions 558

Object methods 558

20
Inheritance from Java classes 559

Accessing static members 560

Java reflection 560

SAM conversions 560

Using JNI with Kotlin 561

Using Lombok-generated declarations in Kotlin 561

Calling Kotlin from Java 561

Properties 561

Package-level functions 562

Instance fields 563

Static fields 564

Static methods 565

Default methods in interfaces 566

Visibility 568

KClass 568

Handling signature clashes with @JvmName 568

Overloads generation 569

Checked exceptions 569

Null-safety 570

Variant generics 570

Create a RESTful web service with a database using Spring Boot – tutorial 572

Before you start 573

Bootstrap the project 573

Explore the project build file 574

Explore the Spring Boot application 575

Create a data class and a controller 575

Run the application 576

Add database support 578

Configure the database 579

21
Execute HTTP requests 580

What's next? 582

Test code using JUnit in JVM – tutorial 583

Add dependencies 583

Add the code to test it 584

Create a test 584

Run a test 585

What's next 587

Mixing Java and Kotlin in one project – tutorial 587

Adding Java source code to an existing Kotlin project 587

Adding Kotlin source code to an existing Java project 588

Converting an existing Java file to Kotlin with J2K 589

Using Java records in Kotlin 590

Using Java records from Kotlin code 591

Declare records in Kotlin 591

Further discussion 592

Migrating from Java to Kotlin: Strings 592

Concatenate strings 592

Build a string 593

Create a string from collection items 593

Set default value if the string is blank 594

Replace characters at the beginning and end of a string 594

Replace occurrences 595

Split a string 595

Take a substring 596

Use multiline strings 597

What’s next? 598

Get started with Kotlin/JS for React 598

22
Create an application 598
Run the application 600

Update the application 601

What's next? 604

Set up a Kotlin/JS project 605

Execution environments 606

Dependencies 607

run task 609

test task 610

webpack bundling 611

CSS 613

Yarn 614

Distribution target directory 614

Module name 615

package.json customization 615

Troubleshooting 615

Run Kotlin/JS 616

Run the Node.js target 616

Run the browser target 617

Development server and continuous compilation 618

Debug Kotlin/JS code 621

Debug in browser 621

Debug in the IDE 623

Debug in Node.js 626

What's next? 627

If you run into any problems 627

Run tests in Kotlin/JS 627

Kotlin/JS dead code elimination 631

23
Exclude declarations from DCE 632

Disable DCE 632

Kotlin/JS IR compiler 633

Ignoring compilation errors 633

Lazy initialization of top-level properties 634

Preview: generation of TypeScript declaration files (d.ts) 635

Current limitations of the IR compiler 635

Migrating existing projects to the IR compiler 636

Authoring libraries for the IR compiler with backwards compatibility 636

Migrating Kotlin/JS projects to the IR compiler 636

Convert JS- and React-related classes and interfaces to external interfaces 637

Convert properties of external interfaces to var 637

Make boolean properties nullable in external interfaces 638

Convert functions with receivers in external interfaces to regular functions 639

Create plain JS objects for interoperability 639

Replace toString() calls on function references with .name 640

Browser and DOM API 640

Interaction with the DOM 640

Use JavaScript code from Kotlin 641

Inline JavaScript 641

external modifier 642

Dynamic type 645

Use dependencies from npm 646

Use Kotlin code from JavaScript 647

Isolating declarations in a separate JavaScript object in plain mode 647

Package structure 648

Kotlin types in JavaScript 650

24
JavaScript modules
650
Browser targets 651

JavaScript libraries and Node.js files 651

@JsModule annotation 652

Kotlin/JS reflection 654

Class references 654

KType and typeOf() 655

Example 655

Typesafe HTML DSL 656

Generation of external declarations with Dukat 657

Generate external declarations at build time 657

Manually generate external declarations via Gradle task 658

Hands-on labs for Kotlin/JS 658

Get started with Kotlin/Native in IntelliJ IDEA 659

Create a new Kotlin/Native project in IntelliJ IDEA 659

Run the application 660

Update the application 661

What's next? 663

Get started with Kotlin/Native using Gradle 664

Create project files 664

Build the project 665

Open the project in an IDE 666

What's next? 666

Get started with Kotlin/Native using the command-line compiler 666

Obtain the compiler 666

Write "Hello Kotlin/Native" program 666

Compile the code from the console 666

25
Concurrency in Kotlin/Native 667

Workers 667

Object subgraph detachment 668

Raw shared memory 669

Atomic primitives and references 670

Immutability in Kotlin/Native 671

Kotlin/Native libraries 671

Kotlin compiler specifics 671

cinterop tool specifics 672

klib utility 672

Several examples 672

Advanced topics 674

Platform libraries 674

POSIX bindings 674

Popular native libraries 675

Availability by default 675

Examples 675

Kotlin/Native as a dynamic library – tutorial 675

Create a Kotlin library 676

Generated headers file 678

Use generated headers from C 682

Compile and run the example on Linux and macOS 683

Compile and run the example on Windows 683

Next steps 684

Interoperability with C 684

Platform libraries 684

Simple example 685

Create bindings for a new library 685

26
Bindings 687

Mapping primitive data types from C – tutorial 694

Types in C language 694

Example C library 694

Inspect generated Kotlin APIs for a C library 695

Primitive types in kotlin 697

Fix the code 698

Next steps 698

Mapping struct and union types from C – tutorial 699

Mapping struct and union C types 699

Inspect Generated Kotlin APIs for a C library 699

Primitive types in Kotlin 701

Use struct and union types from Kotlin 702

Run the code 704

Next steps 705

Mapping function pointers from C – tutorial 705

Mapping function pointer types from C 706

Inspect generated Kotlin APIs for a C library 706

C function pointers in Kotlin 708

Pass Kotlin function as C function pointer 709

Use the C function pointer from Kotlin 709

Fix the code 709

Next Steps 710

Mapping Strings from C – tutorial 710

Working with C strings 710

Inspect generated Kotlin APIs for a C library 711

Primitive types in Kotlin 713

Pass Kotlin string to C 714

27
Read C Strings in Kotlin 714

Receive C string bytes from Kotlin 714

Fix the Code 715

Next steps 715

Using C Interop and libcurl for an app – tutorial 716

Generate bindings 716

Consume the Kotlin API 719

Compile and link the library 720

Interoperability with Swift/Objective-C 720

Usage 721

Mappings 721

Casting between mapped types 727

Subclassing 728

C features 728

Unsupported 728

CocoaPods integration 729

Install the CocoaPods dependency manager and plugin 729

Add dependencies on Pod libraries 730

Use a Kotlin Gradle project as a CocoaPods dependency 739

Kotlin/Native as an Apple framework – tutorial 742

Create a Kotlin library 742

Generated framework headers 745

Garbage collection and reference counting 748

Use the code from Objective-C 748

Use the code from Swift 749

Xcode and framework dependencies 750

Next steps 750

Debugging Kotlin/Native 750

28
Produce binaries with debug info with Kotlin/Native compiler 751

Breakpoints 751

Stepping 753

Variable inspection 753

Known issues 754

Symbolicating iOS crash reports 755

Producing .dSYM for release Kotlin binaries 755

Make frameworks static when using rebuild from bitcode 755

Decode inlined stack frames 756

Tips for improving Kotlin/Native compilation times 756

General recommendations 757

Gradle configuration 757

Kotlin/Native FAQ 758

How do I run my program? 758

What is Kotlin/Native memory management model? 758

How do I create a shared library? 759

How do I create a static library or an object file? 759

How do I run Kotlin/Native behind a corporate proxy? 759

How do I specify a custom Objective-C prefix/name for my Kotlin framework? 759

How do I rename the iOS framework? 760

How do I enable bitcode for my Kotlin framework? 760

Why do I see InvalidMutabilityException? 761

How do I make a singleton object mutable? 761

How can I compile my project with unreleased versions of Kotlin/Native? 761

Kotlin releases 761

Update to a new release 762

IDE support 762

Release details 762

29
KMM plugin releases 769
Update to the new release 770

Release details 770

Kotlin plugin releases 772

Update to a new release 773

Release details 773

Kotlin roadmap 774

Key priorities 774

Kotlin roadmap by subsystem 774

What's changed since January 2021 779

Collections overview 781

Collection types 781

Constructing collections 786

Construct from elements 786

Empty collections 787

Initializer functions for lists 787

Concrete type constructors 787

Copy 788

Invoke functions on other collections 789

Iterators 790

List iterators 791

Mutable iterators 791

Ranges and progressions 792

Range 793

Progression 794

Sequences 795

Construct 796

Sequence operations 797

30
Sequence processing example 797

Collection operations overview 799

Extension and member functions 799

Common operations 800

Write operations 801

Collection transformation operations 801

Map 802

Zip 802

Associate 803

Flatten 805

String representation 805

Filtering collections 807

Filter by predicate 807

Partition 808

Test predicates 808

Plus and minus operators 809

Grouping 810

Retrieve collection parts 810

Slice 811

Take and drop 811

Chunked 812

Windowed 812

Retrieve single elements 813

Retrieve by position 814

Retrieve by condition 815

Retrieve with selector 816

Random element 816

31
Check element existence 816

Ordering 817

Natural order 819

Custom orders 819

Reverse order 819

Random order 820

Aggregate operations 821

Fold and reduce 822

Collection write operations 824

Adding elements 824

Removing elements 825

Updating elements 826

List-specific operations 826

Retrieve elements by index 826

Retrieve list parts 827

Find element positions 827

List write operations 829

Set-specific operations 831

Map-specific operations 832

Retrieve keys and values 832

Filter 833

Plus and minus operators 833

Map write operations 834

Scope functions 836

Function selection 837

Distinctions 838

Functions 842

32
takeIf and takeUnless 845

Opt-in requirements 847

Opt in to using API 847

Require opt-in for API 851

Opt-in requirements for pre-stable APIs 852

Experimental status of the opt-in requirements 852

Coroutines guide 853

Table of contents 853

Additional references 853

Coroutines basics 854

Your first coroutine 854

Extract function refactoring 855

Scope builder 856

Scope builder and concurrency 856

An explicit job 857

Coroutines ARE light-weight 858

Cancellation and timeouts 858

Cancelling coroutine execution 858

Cancellation is cooperative 859

Making computation code cancellable 860

Closing resources with finally 861

Run non-cancellable block 861

Timeout 862

Asynchronous timeout and resources 863

Composing suspending functions 865

Sequential by default 865

Concurrent using async 866

Lazily started async 867

33
Async-style functions 868

Structured concurrency with async 870

Coroutine context and dispatchers 872

Dispatchers and threads 872

Unconfined vs confined dispatcher 873

Debugging coroutines and threads 874

Jumping between threads 876

Job in the context 877

Children of a coroutine 877

Parental responsibilities 878

Naming coroutines for debugging 879

Combining context elements 880

Coroutine scope 880

Asynchronous Flow 884

Representing multiple values 884

Flows are cold 886

Flow cancellation basics 887

Flow builders 888

Intermediate flow operators 888

Terminal flow operators 891

Flows are sequential 891

Flow context 892

Buffering 895

Composing multiple flows 898

Flattening flows 900

Flow exceptions 903

Exception transparency 905

Flow completion 907

Imperative versus declarative 910

34
Launching flow 910
Flow and Reactive Streams 913

Channels 914

Channel basics 914

Closing and iteration over channels 915

Building channel producers 915

Pipelines 916

Prime numbers with pipeline 917

Fan-out 918

Fan-in 920

Buffered channels 921

Channels are fair 922

Ticker channels 922

Coroutine exceptions handling 924

Exception propagation 924

CoroutineExceptionHandler 925

Cancellation and exceptions 926

Exceptions aggregation 928

Supervision 929

Shared mutable state and concurrency 932

The problem 932

Volatiles are of no help 933

Thread-safe data structures 934

Thread confinement fine-grained 935

Thread confinement coarse-grained 936

Mutual exclusion 937

Actors 938

Select expression (experimental) 940

Selecting from channels 940

35
Selecting from channels 940

Selecting on close 942

Selecting to send 943

Selecting deferred values 945

Switch over a channel of deferred values 946

Debug coroutines using IntelliJ IDEA – tutorial 948

Create coroutines 948

Debug coroutines 949

Debug Kotlin Flow using IntelliJ IDEA – tutorial 951

Create a Kotlin flow 951

Debug the coroutine 953

Add a concurrently running coroutine 955

Debug a Kotlin flow with two coroutines 955

Serialization 956

Libraries 957

Formats 957

Example: JSON serialization 957

Keywords and operators 959

Hard keywords 959

Soft keywords 961

Modifier keywords 962

Special identifiers 963

Operators and special symbols 963

Gradle 965

Plugin and versions 965

Targeting multiple platforms 965

Targeting the JVM 966

Targeting JavaScript 967

Targeting Android 968

36
Configuring dependencies 968

Annotation processing 973

Incremental compilation 973

Gradle build cache support 974

Gradle configuration cache support 974

Compiler options 974

Generating documentation 981

OSGi 981

Using the Gradle Kotlin DSL 981

Kotlin daemon and using it with Gradle 981

Maven 983

Plugin and versions 983

Dependencies 983

Compile Kotlin-only source code 984

Compile Kotlin and Java sources 985

Incremental compilation 986

Annotation processing 986

Jar file 986

Self-contained Jar file 987

Specifying compiler options 987

Generating documentation 989

OSGi 989

Ant 990

Getting the Ant tasks 990

Targeting JVM with Kotlin-only source 990

Targeting JVM with Kotlin-only source and multiple roots 990

Targeting JVM with Kotlin and Java source 991

Targeting JavaScript with single source folder 991

Targeting JavaScript with Prefix, PostFix and sourcemap options 991

37
Targeting JavaScript with single source folder and metaInfo option 992

References 992

Run code snippets – tutorial 993

Scratches and worksheets 994

REPL 996

Migrate to Kotlin code style 997

Kotlin coding conventions and IntelliJ IDEA formatter 997

Differences between "Kotlin coding conventions" and "IntelliJ IDEA default code style" 998

Migration to a new code style discussion 998

Migration to a new code style 999

Store old code style in project 1000

Eclipse IDE 1000

Set up the environment 1001

Create a new project 1002

Run the application 1006

Kotlin command-line compiler 1008

Install the compiler 1008

Create and run an application 1008

Compile a library 1009

Run the REPL 1009

Run scripts 1010

Kotlin compiler options 1010

Compiler options 1011

Common options 1011

Kotlin/JVM compiler options 1013

Kotlin/JS compiler options 1014

Kotlin/Native compiler options 1015

All-open compiler plugin 1018

38
Gradle 1018

Maven 1019

Spring support 1020

Command-line compiler 1021

No-arg compiler plugin 1021

Gradle 1022

Maven 1022

JPA support 1023

Command-line compiler 1023

SAM-with-receiver compiler plugin 1024

Gradle 1024

Maven 1024

Command-line compiler 1025

Using kapt 1025

Using in Gradle 1025

Annotation processor arguments 1026

Gradle build cache support 1027

Improving the speed of builds that use kapt 1027

Compile avoidance for kapt 1028

Incremental annotation processing 1028

Java compiler options 1028

Non-existent type correction 1029

Using in Maven 1029

Using in CLI 1029

Generating Kotlin sources 1030

AP/Javac options encoding 1031

Keeping Java compiler's annotation processors 1031

Lombok compiler plugin 1031

39
Supported annotations 1032

Gradle 1032

Maven 1033

Using with kapt 1034

Kotlin Symbol Processing API 1035

Overview 1035

How KSP looks at source files 1035

SymbolProcessorProvider: The entry point 1036

Resources 1037

Supported libraries 1037

KSP quickstart 1038

Create a processor of your own 1038

Use your own processor in a project 1039

Pass Options to Processors 1041

Make IDE Aware Of Generated Code 1041

Why KSP 1042

KSP makes creating lightweight compiler plugins easier 1042

Comparison to kotlinc compiler plugins 1042

Comparison to reflection 1042

Comparison to KAPT 1043

Limitations 1043

KSP examples 1043

How KSP models Kotlin code 1044

Type and resolution 1045

Java annotation processing to KSP reference 1046

Program elements 1046

Types 1046

Misc 1047

40
Details 1048

AnnotationValue 1049

Element 1049

ExecutableElement 1049

Parameterizable 1050

QualifiedNameable 1050

TypeElement 1050

TypeParameterElement 1051

VariableElement 1051

ArrayType 1051

DeclaredType 1052

ExecutableType 1052

IntersectionType 1052

TypeMirror 1052

TypeVariable 1053

WildcardType 1053

Elements 1053

Types 1054

Incremental processing 1055

Aggregating vs Isolating 1055

Example 1 1056

Example 2 1057

How file dirtiness is determined 1057

Reporting bugs 1058

Multiple round processing 1058

Changes to your processor 1058

Multiple round behavior 1058

Advanced 1060

41
Frequently asked questions 1060

Why KSP? 1060

Why is KSP faster than KAPT? 1061

Is KSP Kotlin-specific? 1061

Kotlin and continuous integration with TeamCity 1061

Gradle, Maven, and Ant 1061

IntelliJ IDEA Build System 1062

Other CI servers 1064

Document Kotlin code: KDoc and Dokka 1064

Generate the documentation 1064

KDoc syntax 1064

Inline markup 1066

Module and package documentation 1067

Kotlin and OSGi 1067

Maven 1068

Gradle 1068

FAQ 1068

Learning materials overview 1069

Kotlin Koans 1069

Kotlin books 1069

Learning Kotlin with EduTools plugin 1074

Teaching Kotlin with EduTools plugin 1074

FAQ 1074

What is Kotlin? 1075

What is the current version of Kotlin? 1075

Is Kotlin free? 1075

42
Is Kotlin an object-oriented language or a functional one? 1075

What advantages does Kotlin give me over the Java programming language? 1075

Is Kotlin compatible with the Java programming language? 1075

What can I use Kotlin for? 1075

Can I use Kotlin for Android development? 1076

Can I use Kotlin for server-side development? 1076

Can I use Kotlin for web development? 1076

Can I use Kotlin for desktop development? 1076

Can I use Kotlin for native development? 1076

What IDEs support Kotlin? 1076

What build tools support Kotlin? 1076

What does Kotlin compile down to? 1077

Which versions of JVM does Kotlin target? 1077

Is Kotlin hard? 1077

What companies are using Kotlin? 1077

Who develops Kotlin? 1077

Where can I learn more about Kotlin? 1077

Are there any books on Kotlin? 1078

Are any online courses available for Kotlin? 1078

Does Kotlin have a community? 1078

Are there Kotlin events? 1078

Is there a Kotlin conference? 1078

Is Kotlin on social media? 1078

Any other online Kotlin resources? 1078

Where can I get an HD Kotlin logo? 1079

Participate in the Kotlin Early Access Preview 1079

Build details 1079

Install the EAP Plugin for IntelliJ IDEA or Android Studio 1080

If you run into any problems 1082

43
Configure your build for EAP 1082

Configure in Gradle 1083

Configure in Maven 1084

Contribution 1085

Participate in Early Access Preview 1085

Contribute to the compiler, standard library, and tooling 1086

Contribute to other libraries and create your own 1086

Contribute to the documentation 1086

Create tutorials or videos 1086

Translate documentation to other languages 1086

Hold events and presentations 1086

Kotlin Evolution 1087

Principles of Pragmatic Evolution 1087

Incompatible changes 1087

Decision making 1089

Feature releases and incremental releases 1089

Libraries 1090

Compiler keys 1090

Compatibility tools 1090

Stability of Kotlin components 1091

Stability levels explained 1092

Stability of subcomponents 1092

Current stability of Kotlin components 1093

Stability of Kotlin components (pre 1.4) 1094

Compatibility guide for Kotlin 1.5 1095

Basic terms 1096

Language and stdlib 1096

Tools 1107

44
Compatibility guide for Kotlin 1.4 1108

Basic terms 1108

Language and stdlib 1109

Tools 1129

Compatibility guide for Kotlin 1.3 1130

Basic terms 1131

Incompatible changes 1131

Compatibility modes 1143

Binary compatibility warnings 1143

Kotlin Foundation 1144

Scope 1144

Structure 1145

Current personnel 1145

Language Committee guidelines 1146

Review process 1146

Scope 1147

Migration aids and deprecation 1147

Changes to these guidelines 1149

Appendix A. Examples of non-issues 1149

Appendix B. Assumptions for pragmatic language evolution 1150

Guide to submitting incompatible changes 1150

Issue template 1151

Classification 1151

Kotlin brand usage guidelines 1154

General goals 1154

Permitted uses 1154

Unpermitted uses 1155

45
Usage guidelines 1155

Example usages 1156

Kotlin Foundation FAQ 1156

How can I contribute or provide feedback to Kotlin? 1156

How can I get more involved with the Kotlin community? 1156

How is the Kotlin Foundation governed? 1156

Do JetBrains and Google contribute financially to the foundation? 1157

Does the foundation generate any revenue? 1157

Can I license the Kotlin trademark? 1157

How can a company or an individual join the foundation? 1157

What resources should I follow to stay up-to-date on Kotlin? 1157

Security 1157

Kotlin documentation as PDF 1158

46
Kotlin
docs
Get started with Kotlin What's new in Kotlin

You can get started with Kotlin using an online editor. If Discover what features are available in the newest Kotlin
you already have an IDE or you are ready to install one, release. You can try out upcoming features in the preview
here are also some ways to begin using Kotlin on your versions before they are released.
local machine.
What's new in Kotlin 1.5.30
Get started with Kotlin
What's new in Kotlin plugin 2021.2
Try Kotlin online
Kotlin public roadmap
Get started with KMM in Android Studio
KMM plugin releases for Android Studio

Basics & concepts Ways to learn

Acquaint yourself with some of the concepts and the Find a way to learn Kotlin that works for you. There are lots
basics of Kotlin. of learning materials available from our team and other
authors.
Basic syntax
Kotlin by example
Basic types
Kotlin Koans
Control flow
Kotlin Basics track on JetBrains Academy
Null safety
Hands-on tutorials
Coroutines
EduTools in IntelliJ IDEA
Coding conventions
Books

47
Kotlin YouTube Channel Stay in touch and contribute

Our YouTube channel is packed with resources for learning If you are interested in what's going with Kotlin, join us on
Kotlin! Subscribe to stay updated for shows, the latest social media, and get involved.
news, and live events!
Contribute to Kotlin
Kotlin in Spring Framework
Participate in Early Access Program
Webinars with Experts
Join Kotlin Slack
Kotlin Multiplatform Multiverse
Follow Kotlin on Twitter
Competitive Programming
Chat on Reddit
Kotlin Standard Library
Participate in Stack Overflow discussions
Talking Kotlin Podcast

Kotlin for Educators

Kotlin Online Event 2020 playlist

Get
started
with
Kotlin
Kotlin is a modern but already mature programming language aimed to make developers happier. It’s concise, safe,
interoperable with Java and other languages, and provides many ways to reuse code between multiple platforms for
productive programming.

Pick it up to start building powerful applications!

Learn
Kotlin
fundamentals
If you're already familiar with one or more programming languages and want to learn Kotlin, start with these Kotlin
learning materials.

If Kotlin is your first programming language, we recommend starting with the Atomic Kotlin book or signing up for the
free Kotlin Basics track on JetBrains Academy.

Create
your
powerful
application
with
Kotlin

Backend app

Here is how you can take the first steps in developing Kotlin server-side applications.

48
1. Install the latest version of IntelliJ IDEA.

2. Create your first backend application:

To start from scratch, create a basic JVM application with the IntelliJ IDEA project wizard.

If you prefer more robust examples, choose one of the frameworks below and create a project:

Spring Ktor

A mature family of frameworks with an established ecosystem A lightweight framework for those who value freedom in making
that is used by millions of developers worldwide. architectural decisions.
Create a RESTful web service with Spring Boot. Create HTTP APIs with Ktor.

Build web applications with Spring Boot and Kotlin. Create a WebSocket chat with Ktor.

Use Spring Boot with Kotlin and RSocket. Create an interactive website with Ktor.

Publish server-side Kotlin applications: Ktor on Heroku.

3. Use Kotlin and third-party libraries in your application. Learn more about adding library and tool dependencies to your project.

The Kotlin standard library offers a lot of useful things such as collections or coroutines.

Take a look at the following third-party frameworks, libs and tools for Kotlin.

4. Learn more about Kotlin for server-side:

How to write your first unit test.

How to mix Kotlin and Java code in your application.

5. Join the Kotlin server-side community:

Slack: get an invite and join the #getting-started, #server, #spring, or #ktor channels.

StackOverflow: subscribe to the “kotlinâ€​, "spring-kotlin", or "ktor" tags.

6. Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

If you've encountered any difficulties or problems, report an issue to ourissue tracker.

Cross-platform mobile app

Here you'll learn how to develop and improve your cross-platform mobile application usingKotlin Multiplatform Mobile (KMM).

1. Set up your environment for cross-platform development.

2. Create your first KMM application:

To start from scratch, create a basic KMM application with the project wizard.

If you have an existing Android application and want to make it cross-platform, complete theMake your Android application work
on iOS tutorial.

If you prefer real-life examples, clone and play with an existing project, for example the networking and data storage project from
the hands-on tutorial or any KMM sample.

3. Use a wide set of multiplatform libraries to implement the required business logic only once in the shared module. Learn more about
adding dependencies.

49
Library Details

Ktor Docs.

Serialization Docs and sample.

Coroutines Docs and sample.

DateTime Docs.

SQLDelight Third-party library. Docs and


sample.

You can also find a multiplatform library in the community-driven list.

4. Learn more about KMM:

Learn more about Kotlin Multiplatform.

Look through KMM samples on GitHub.

Create and publish a multiplatform library.

Learn how KMM is used at Netflix, VWWare, Yandex, and many other companies.

5. Join the Kotlin Multiplatform community:

Slack: get an invite and join the #getting-started and #multiplatform channels.

StackOverflow: Subscribe to the “kotlin-multiplatformâ€​ tag.

6. Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

If you've encountered any difficulties or problems, report an issue to ourissue tracker.

Frontend web app

Kotlin provides an ability to transpile your Kotlin code, the Kotlin standard library, and any compatible dependencies to JavaScript.

Here you'll learn how to develop and improve your frontend web application usingKotlin/JS.

1. Install the latest version of IntelliJ IDEA.

2. Create your first frontend web application:

To start from scratch, create a basic browser application with the IntelliJ IDEA project wizard.

If you prefer more robust examples, complete the Building Web Applications with React and Kotlin/JS hands-on tutorial. It
includes a sample project that can serve as a good starting point for your own projects, and contains useful snippets and
templates.

3. Use libraries in your application. Learn more about adding dependencies.

50
Library Details

stdlib The Kotlin standard library included in all projects by default.

kotlinx.browser The Kotlin library for accessing browser-specific functionality, including typical top-level objects such as
document and window.

kotlinx.html The Kotlin library for generating DOM elements using statically-typed HTML builders.

Ktor The Kotlin multiplatform library for networking.

KVision A third-party object-oriented web framework for Kotlin/JS.

fritz2 A third-party lightweight, high-performance, independent library for building reactive web apps in Kotlin
that are heavily dependent on coroutines and flows.

Doodle A third-party vector-based UI framework that uses browser's capabilities to draw user interfaces.

Compose for Web, a The JetBrains framework that brings Google's Jetpack Compose UI toolkit to the browser (currently with
part of Compose Alpha stability).
Multiplatform

kotlin-wrappers Provide convenient abstractions and deep integrations for one of the most popular JavaScript frameworks.
Kotlin wrappers also provide support for a number of adjacent technologies like react-redux, react-router,
or styled-components.

4. Learn more about Kotlin for frontend web development:

The new Kotlin/JS IR compiler (currently with Beta stability).

Using dependencies from npm.

Using Kotlin code from JavaScript.

5. Join the Kotlin frontend web community:

Slack: get an invite and join the #getting-started and #javascript channels.

StackOverflow: subscribe to the “kotlin-jsâ€​ tag.

6. Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

If you've encountered any difficulties or problems, report an issue to ourissue tracker.

Android app

If you want to start using Kotlin for Android development, readGoogle’s recommendation for getting started with Kotlin on
Android.

If you're new to Android and want to learn to create applications with Kotlin, check outthis Udacity course.

Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

51
Multiplatform library

Support for multiplatform programming is one of Kotlin’s key benefits. It reduces time spent writing and maintaining the same code
for different platforms while retaining the flexibility and benefits of native programming.

Here you'll learn how to develop and publish a multiplatform library:

1. Install the latest version of IntelliJ IDEA.

2. Create a multiplaform library:

To start from scratch, create a basic project.

If you prefer more robust examples, complete the Create and publish a multiplatform library tutorial. It shows how to create a
multiplatform library for JVM, JS, and Native platforms, test it and publish to a local Maven repository.

Build a full stack web application using this hands-on.

3. Use libraries in your application. Learn more about adding dependencies on libraries.

Library Details

Ktor Docs and sample.

Serialization Docs and sample.

Coroutines Docs.

DateTime Docs.

You can also find a multiplatform library in the community-driven list.

4. Learn more about Kotlin Multiplatform programming:

Introduction to Kotlin Multiplatform.

Kotlin Multiplatform supported platforms.

Kotlin Multiplatform programming benefits.

5. Join the Kotlin Multiplatform community:

Slack: get an invite and join the #getting-started and #multiplatform channels.

StackOverflow: Subscribe to the “kotlin-multiplatformâ€​ tag.

6. Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

If you've encountered any difficulties or problems, report an issue to ourissue tracker.

Is
anything
missing?

52
If anything is missing or seems confusing on this page, please share your feedback.

Multiplatform
programming

Multiplatform projects are in Alpha. Language features and tooling may change in future Kotlin versions.

Support for multiplatform programming is one of Kotlin’s key benefits. It reduces time spent writing and maintaining
the same code for different platforms while retaining the flexibility and benefits of native programming.

This is how Kotlin Multiplatform works.

53
Kotlin Multiplatform

Common Kotlin includes the language, core libraries, and basic tools. Code written in common Kotlin works
everywhere on all platforms.

With Kotlin Multiplatform libraries, you can reuse the multiplatform logic in common and platform-specific code.
Common code can rely on a set of libraries that cover everyday tasks such as HTTP, serialization, and managing
coroutines.

To interop with platforms, use platform-specific versions of Kotlin. Platform-specific versions of Kotlin (Kotlin/JVM,
Kotlin/JS, Kotlin/Native) include extensions to the Kotlin language, and platform-specific libraries and tools.

54
Through these platforms you can access the platform native code (JVM, JS, and Native) and leverage all native
capabilities.

With Kotlin Multiplatform, spend less time on writing and maintaining the same code for different platforms – just share
it using the mechanisms Kotlin provides:

Share code among all platforms used in your project. Use it for sharing the common business logic that applies to all
platforms.

Code shared for all platforms

Share code among some platforms included in your project but not all. Do this when you can reuse much of the code
in similar platforms.

55
Hierarchical structure

56
Code shared for iOS targets

If you need to access platform-specific APIs from the shared code, use the Kotlin mechanism of expected and actual
declarations.

With this mechanism, a common source set defines an expected declaration, and platform source sets must provide the
actual declaration that corresponds to the expected declaration. This works for most Kotlin declarations, such as
functions, classes, interfaces, enumerations, properties, and annotations.

57
Expect and actual declarations

//Common
expect fun randomUUID(): String

//Android
import java.util.*
actual fun randomUUID() = UUID.randomUUID().toString()

//iOS
import platform.Foundation.NSUUID
actual fun randomUUID(): String = NSUUID().UUIDString()

Use
cases

Android
—
iOS
Sharing code between mobile platforms is one of the major Kotlin Multiplatform use cases. With Kotlin Multiplatform
Mobile (KMM), you can build multiplatform mobile applications sharing code, such as business logic, connectivity, and
more, between Android and iOS.

See KMM features, case studies and examples

58
Client
—
Server
Another scenario when code sharing may bring benefits is a connected application where the logic can be reused on both
the server and the client side running in the browser. This is covered by Kotlin Multiplatform as well.

The Ktor framework is suitable for building asynchronous servers and clients in connected systems.

What's
next?
New to Kotlin? Visit Getting started with Kotlin.

Documentation
Get started with Kotlin Multiplatform Mobile (KMM)

Create a multiplatform project

Share code on multiple platforms

Connect to platform-specific APIs

Tutorials
Create your first KMM application shows how to create a mobile application that works on Android and iOS with the
help of the KMM plugin for Android Studio. Create, run, and test your first multiplatform mobile application.

Creating a multiplatform Kotlin library teaches how to create a multiplatform library available for JVM, JS, and Native
and which can be used from any other common code (for example, shared with Android and iOS). It also shows how to
write tests which will be executed on all platforms and use an efficient implementation provided by a specific platform.

Building a full stack web app with Kotlin Multiplatform teaches the concepts behind building an application that targets
Kotlin/JVM and Kotlin/JS by building a client-server application that makes use of shared code, serialization, and other
multiplatform paradigms. It also provides a brief introduction to working with Ktor both as a server- and client-side
framework.

Sample
projects
Kotlin Multiplatform Mobile (KMM) samples

KotlinConf app

KotlinConf Spinner app

Kotlin
Multiplatform
Mobile

59
Multiplatform Mobile projects are in Alpha. Language features and tooling may change in future Kotlin versions.

Kotlin Multiplatform Mobile (KMM) is an SDK designed to simplify creating cross-platform mobile applications. With the
help of KMM, you can share common code between iOS and Android apps and write platform-specific code only where
it’s necessary. For example, to implement a native UI or when working with platform-specific APIs.

Get
started
with
Kotlin
Multiplatform
Mobile
Get started with KMM if you're already familiar with the Kotlin language and want to try out Kotlin Multiplatform Mobile
(KMM). If you're new to Kotlin, get started with these tutorials.

If you want to introduce KMM to your team, look through our recommendations.

Supported
platforms
KMM supports the following mobile targets:

Android applications and libraries

Android NDK on ARM32 and ARM64 platforms

Apple iOS on ARM64 (iPhone 5s and newer), ARM32 (earlier models) platforms, and desktop simulators on both Intel-
based and Apple Silicon platforms

Apple watchOS on ARM64 (Apple Watch Series 4 and newer), ARM32 (earlier models) platforms, and desktop
simulators on both Intel-based and Apple Silicon platforms

KMM is built on top of the Kotlin Multiplatform technology, which supports other platforms inlcuding JavaScript, Linux,
WebAssembly, and more.

See supported platforms for Kotlin multiplatform programming.

Sample
projects
Check our list of KMM sample projects for inspiration.

Videos
Learn KMM with Kotlin Multiplatform Multiverse videos on YouTube.

Community

60
Kotlin Slack: Get an invite and join the #multiplatform channel.

StackOverflow: Subscribe to the “kotlin-multiplatformâ€​ tag.

Kotlin issue tracker: Report a new issue.

Security
We do our best to make sure our software is free of security vulnerabilities. To reduce the risk of introducing a
vulnerability, you can follow Kotlin security recommendations.

We are very eager and grateful to hear about any security issues you find. To report vulnerabilities that you discover in any
part of KMM, please post a message directly to our issue tracker or send us an email.

For further information on how our responsible disclosure process works, please check the JetBrains Coordinated
Disclosure Policy.

Kotlin
for
server
side
Kotlin is a great fit for developing server-side applications, allowing you to write concise and expressive code while
maintaining full compatibility with existing Java-based technology stacks and a smooth learning curve:

Expressiveness: Kotlin's innovative language features, such as its support for type-safe builders and delegated
properties, help build powerful and easy-to-use abstractions.

Scalability: Kotlin's support for coroutines helps build server-side applications that scale to massive numbers of clients
with modest hardware requirements.

Interoperability: Kotlin is fully compatible with all Java-based frameworks, which lets you stay on your familiar
technology stack while reaping the benefits of a more modern language.

Migration: Kotlin supports gradual, step by step migration of large codebases from Java to Kotlin. You can start writing
new code in Kotlin while keeping older parts of your system in Java.

Tooling: In addition to great IDE support in general, Kotlin offers framework-specific tooling (for example, for Spring) in
the plugin for IntelliJ IDEA Ultimate.

Learning Curve: For a Java developer, getting started with Kotlin is very easy. The automated Java to Kotlin converter
included in the Kotlin plugin helps with the first steps. Kotlin Koans offer a guide through the key features of the
language with a series of interactive exercises.

Frameworks
for
server-side
development
with
Kotlin
Spring makes use of Kotlin's language features to offer more concise APIs, starting with version 5.0. The online project
generator allows you to quickly generate a new project in Kotlin.

61
Vert.x, a framework for building reactive Web applications on the JVM, offers dedicated support for Kotlin, including
full documentation.

Ktor is a framework built by JetBrains for creating Web applications in Kotlin, making use of coroutines for high
scalability and offering an easy-to-use and idiomatic API.

kotlinx.html is a DSL that can be used to build HTML in a Web application. It serves as an alternative to traditional
templating systems such as JSP and FreeMarker.

Micronaut is a modern, JVM-based, full-stack framework for building modular, easily testable microservice and
serverless applications. It comes with a lot of built-in, handy features.

http4k is the functional toolkit with a tiny footprint for Kotlin HTTP applications, written in pure Kotlin. The library is
based on the "Your Server as a Function" paper from Twitter and represents modeling both HTTP Servers and Clients
as simple Kotlin functions that can be composed together.

Javalin is a very lightweight web framework for Kotlin and Java which supports WebSockets, HTTP2 and async
requests.

The available options for persistence include direct JDBC access, JPA, as well as using NoSQL databases through
their Java drivers. For JPA, the kotlin-jpa compiler plugin adapts Kotlin-compiled classes to the requirements of the
framework.

Deploying
Kotlin
server-side
applications
Kotlin applications can be deployed into any host that supports Java Web applications, including Amazon Web Services,
Google Cloud Platform and more.

To deploy Kotlin applications on Heroku, you can follow the official Heroku tutorial.

AWS Labs provides a sample project showing the use of Kotlin for writing AWS Lambda functions.

Google Cloud Platform offers a series of tutorials for deploying Kotlin applications to GCP, both for Ktor and App Engine
and Spring and App engine. In addition there is an interactive code lab for deploying a Kotlin Spring application.

Users
of
Kotlin
on
the
server
side
Corda is an open-source distributed ledger platform, supported by major banks, and built entirely in Kotlin.

JetBrains Account, the system responsible for the entire license sales and validation process at JetBrains, is written in
100% Kotlin and has been running in production since 2015 with no major issues.

Next
steps
For a more in-depth introduction to the language, check out the Kotlin documentation on this site and Kotlin Koans.

62
Micronaut also has a lot of well-detailed guides, showing how you can build microservices in Kotlin.

http4k provides the CLI to generate fully formed projects, and a starter repo to generate an entire CD pipeline using
GitHub, Travis, and Heroku with a single bash command.

Want to migrate from Java to Kotlin? Learn how to perform typical tasks with strings in Java and Kotlin.

Kotlin
for
Android
Android mobile development has been Kotlin-first since Google I/O in 2019.

Using Kotlin for Android development, you can benefit from:

Less code combined with greater readability. Spend less time writing your code and working to understand the code
of others.

Mature language and environment. Since its creation in 2011, Kotlin has developed continuously, not only as a
language but as a whole ecosystem with robust tooling. Now it's seamlessly integrated in Android Studio and is
actively used by many companies for developing Android applications.

Kotlin support in Android Jetpack and other libraries. KTX extensions add Kotlin language features, such as
coroutines, extension functions, lambdas, and named parameters, to existing Android libraries.

Interoperability with Java. You can use Kotlin along with the Java programming language in your applications without
needing to migrate all your code to Kotlin.

Support for multiplatform development. You can use Kotlin for developing not only Android but also iOS, backend, and
web applications. Enjoy the benefits of sharing the common code among the platforms.

Code safety. Less code and better readability lead to fewer errors. The Kotlin compiler detects these remaining errors,
making the code safe.

Easy learning. Kotlin is very easy to learn, especially for Java developers.

Big community. Kotlin has great support and many contributions from the community, which is growing all over the
world. According to Google, over 60% of the top 1000 apps on the Play Store use Kotlin.

Many startups and Fortune 500 companies have already developed Android applications using Kotlin – see the list at
the Google website for Kotlin developers.

If you want to start using Kotlin for Android development, read Google’s recommendation for getting started with
Kotlin on Android.

If you're new to Android and want to learn to create applications with Kotlin, check out this Udacity course.

Kotlin
for
JavaScript
Kotlin/JS provides the ability to transpile your Kotlin code, the Kotlin standard library, and any compatible dependencies

63
to JavaScript. The current implementation of Kotlin/JS targets ES5.

The recommended way to use Kotlin/JS is via the kotlin.js and kotlin.multiplatform Gradle plugins. They provide a central
and convenient way to set up and control Kotlin projects targeting JavaScript. This includes essential functionality such as
controlling the bundling of your application, adding JavaScript dependencies directly from npm, and more. To get an
overview of the available options, check out the Kotlin/JS project setup documentation.

Use
cases
for
Kotlin/JS
There are numerous ways that Kotlin/JS can be used. To provide you some inspiration, here's a non-exhaustive list of
scenarios in which you can use Kotlin/JS.

Write frontend web applications using Kotlin/JS

Kotlin/JS allows you to leverage powerful browser and web APIs in a type-safe fashion. Create, modify and interact
with elements in the Document Object Model (DOM), use Kotlin code to control the rendering of canvas or WebGL
components, and enjoy access to many more of the features supported in modern browsers.

Write full, type-safe React applications with Kotlin/JS using the kotlin-wrappers provided by JetBrains, which
provide convenient abstractions and deep integrations for one of the most popular JavaScript frameworks. kotlin-
wrappers also provides support for a select number of adjacent technologies like react-redux, react-router, or
styled-components. Interoperability with the JavaScript ecosystem also means that you can also use third-party
React components and component libraries.

Use the Kotlin/JS frameworks that take full advantage of Kotlin concepts, its expressive power and conciseness.

Write server-side and serverless applications using Kotlin/JS

The Node.js target provided by Kotlin/JS enables you to create applications that run on a server or get executed on
serverless infrastructure. You benefit from the same advantages as other applications executing in a JavaScript
runtime, such as faster startup speed and a reduced memory footprint. With kotlinx-nodejs, you have typesafe
access to the Node.js API directly from your Kotlin code.

Use Kotlin's multiplatform projects to share code with other Kotlin targets

All Kotlin/JS functionality can also be accessed when using the Kotlin multiplatform Gradle plugin.

If you have a backend written in Kotlin, you can share common code such as data models or validation logic with a
frontend written in Kotlin/JS, allowing you to write and maintain full-stack web applications.

You could also share business logic between your web interface and mobile apps for Android and iOS, and avoid
duplicating commonly used functionality like providing abstractions around REST API endpoints, user
authentication, or your domain models.

Create libraries for use with JavaScript and TypeScript

You don't have to write your whole application in Kotlin/JS, either – you can also generate libraries from your
Kotlin code that can be consumed as modules from any code base written in JavaScript or TypeScript, regardless
of other frameworks or technologies used. This approach of creating hybrid applications allows you to leverage the

64
competencies that you and your team might already have around web development, while helping you reduce the
amount of duplicated work, and making it easier to keep your web target consistent with other targets of your
application.

Of course, this is not a complete list of how you can use Kotlin/JS to your advantage, but merely a selection of cherry-
picked cases. We invite you to experiment with combinations of these use cases, and find out what works best for your
project.

Regardless of your specific use case, Kotlin/JS projects can use compatible libraries from the Kotlin ecosystem, as well
as third-party libraries from the JavaScript and TypeScript ecosystems. To use the latter from Kotlin code, you can either
provide your own typesafe wrappers, use community-maintained wrappers, or let Dukat automatically generate Kotlin
declarations for you. Using the Kotlin/JS-exclusive dynamic type allows you to loosen the constraints of Kotlin's type
system, allowing you to skip creating detailed library wrappers - at the expense of type safety.

Kotlin/JS is also compatible with the most common module systems: UMD, CommonJS, and AMD. Being able to produce
and consume modules means that you can interact with the JavaScript ecosystem in a structured manner.

Kotlin/JS
frameworks
Modern web development benefits significantly from frameworks that simplify building web applications. Here are
examples of popular web frameworks for Kotlin/JS written by different authors:

KVision
KVision is an object-oriented web framework that makes it possible to write applications in Kotlin/JS with ready-to-use
components that can be used as building blocks for your application’s user interface. You can use both reactive and
imperative programming models to build your frontend, use connectors for Ktor, Spring Boot, and other frameworks to
integrate it with your server-side applications, and share code using Kotlin Multiplatform.

Visit https://kvision.io for documentation, tutorials, and examples.

For updates and discussions about the framework, join #kvision and #javascript channels in the Kotlin Slack.

fritz2
fritz2 is a standalone framework for building reactive web user interfaces. It provides its own type-safe DSL for building
and rendering HTML elements, and it makes use of Kotlin’s coroutines and flows to express components and their
data bindings. It provides state management, validation, routing, and more out of the box, and integrates with Kotlin
Multiplatform projects.

Visit https://www.fritz2.dev for documentation, tutorials, and examples.

For updates and discussions about the framework, join the #fritz2 and #javascript channels in the Kotlin Slack.

Doodle
Doodle is a vector-based UI framework for Kotlin/JS. Doodle applications use the browser’s graphics capabilities to

65
draw user interfaces instead of relying on DOM, CSS, or Javascript. By using this approach, Doodle gives you precise
control over the rendering of arbitrary UI elements, vector shapes, gradients, and custom visualizations.

Visit https://nacular.github.io/doodle/ for documentation, tutorials, and examples.

For updates and discussions about the framework, join #doodle and #javascript channels in the Kotlin Slack.

Compose
for
Web
Compose for Web, a part of Compose Multiplatform brings Google's Jetpack Compose UI toolkit to your browser. It
allows you to build reactive web user interfaces using the concepts introduced by Jetpack Compose. It provides a DOM
API to describe your website, as well as an experimental set of multiplatform layout primitives. Compose for Web also
gives you the option to share parts of your UI code and logic across Android, desktop, and web.

Compose for Web is in Alpha, which means it hasn't reached the final shape yet, but you can already implement a proof-
of-concept for your production applications.

You can find more information about Compose Multiplatform on its landing page.

Join the #compose-web channel on Kotlin Slack to discuss Compose for Web, or #compose for general Compose
Multiplatform discussions.

Kotlin/JS,
Today
and
Tomorrow
Want to know more about Kotlin/JS?

In this video, Kotlin Developer Advocate Sebastian Aigner will explain the main Kotlin/JS benefits to you, share some tips
and use cases, and also tell you about the plans and upcoming features for Kotlin/JS.

Gif

Watch video online.

66
Get
started
with
Kotlin/JS
If you're new to Kotlin, a good first step would be to familiarize yourself with the basic syntax of the language.

To start using Kotlin for JavaScript, please refer to the Set up a Kotlin/JS project, or pick a hands-on lab from the next
section to work through.

Hands-on
labs
for
Kotlin/JS
Hands-on labs are long-form tutorials that help you get to know a technology by guiding you through a self-contained
project related to a specific topic.

They include sample projects, which can serve as jumping-off points for your own projects, and contain useful snippets
and patterns.

For Kotlin/JS, the following hands-on labs are currently available:

Building Web Applications with React and Kotlin/JS guides you through the process of building a simple web
application using the React framework, shows how a typesafe Kotlin DSL for HTML makes it convenient to build
reactive DOM elements, and illustrates how to use third-party React components, and how to obtain information from
APIs, while writing the whole application logic in pure Kotlin/JS.

Building a Full Stack Web App with Kotlin Multiplatform teaches the concepts behind building an application that
targets Kotlin/JVM and Kotlin/JS by building a client-server application that makes use of common code, serialization,
and other multiplatform paradigms. It also provides a brief introduction into working with Ktor both as a server- and
client-side framework.

New
Kotlin/JS
IR
compiler
The new Kotlin/JS IR compiler (currently with Beta stability) comes with a number of improvements over the current
default compiler. For example, it improves the size of generated executables via dead code elimination and makes it
smoother to interoperate with the JavaScript ecosystem and its tooling. By generating TypeScript declaration files (d.ts)
from Kotlin code, the new compiler makes it easier to create “hybridâ€​ applications that mix TypeScript and Kotlin
code, and leverage code-sharing functionality using Kotlin Multiplatform.

To learn more about the available features in the new Kotlin/JS IR compiler and how to try it for your project, visit the
Kotlin/JS IR compiler documentation page and the migration guide.

Join
the
Kotlin/JS
community
You can also join #javascript channel in the official Kotlin Slack and chat with the community and the team.

Kotlin
Native
67
Kotlin/Native is a technology for compiling Kotlin code to native binaries, which can run without a virtual machine. It is an
LLVM based backend for the Kotlin compiler and native implementation of the Kotlin standard library.

Why
Kotlin/Native?
Kotlin/Native is primarily designed to allow compilation for platforms where virtual machines are not desirable or possible,
for example, embedded devices or iOS. It solves the situations when a developer needs to produce a self-contained
program that does not require an additional runtime or virtual machine.

Target
platforms
Kotlin/Native supports the following platforms:

macOS

iOS, tvOS, watchOS

Linux

Windows (MinGW)

Android NDK

The full list of supported targets is available here.

Interoperability
Kotlin/Native supports two-way interoperability with the Native world. On the one hand, the compiler creates:

an executable for many platforms

a static library or dynamic library with C headers for C/C++ projects

an Apple framework for Swift and Objective-C projects

On the other hand, Kotlin/Native supports interoperability to use existing libraries directly from Kotlin/Native:

static or dynamic C Libraries

C, Swift, and Objective-C frameworks

It is easy to include a compiled Kotlin code into existing projects written in C, C++, Swift, Objective-C, and other
languages. It is also easy to use existing native code, static or dynamic C libraries, Swift/Objective-C frameworks,
graphical engines, and anything else directly from Kotlin/Native.

Kotlin/Native libraries help to share Kotlin code between projects. POSIX, gzip, OpenGL, Metal, Foundation, and many
other popular libraries and Apple frameworks are pre-imported and included as Kotlin/Native libraries into the compiler

68
package.

Sharing
code
between
platforms
Multiplatform projects allow sharing common Kotlin code between multiple platforms, including Android, iOS, JVM,
JavaScript, and native. Multiplatform libraries provide required APIs for the common Kotlin code and help develop shared
parts of a project in Kotlin code in one place and share it with all or several target platforms.

You can use Kotlin Multiplatform Mobile (KMM) to create multiplatform mobile applications with code shared between
Android and iOS.

How
to
start

Tutorials
and
documentation
New to Kotlin? Take a look at Getting started with Kotlin.

Recommended documentation:

Kotlin Multiplatform Mobile documentation

Multiplatform documentation

C interop

Swift/Objective-C interop

Recommended tutorials:

Get started with Kotlin/Native

Create your first KMM application

Types mapping between C and Kotlin/Native

Kotlin/Native as a Dynamic Library

Kotlin/Native as an Apple Framework

Sample
projects
Kotlin Multiplatform Mobile samples

Kotlin/Native sources and examples

KotlinConf app

69
KotlinConf Spinner app

Kotlin/Native sources and examples (.tgz)

Kotlin/Native sources and examples (.zip)

Kotlin
for
data
science
From building data pipelines to productionizing machine learning models, Kotlin can be a great choice for working with
data:

Kotlin is concise, readable, and easy to learn.

Static typing and null safety help create reliable, maintainable code that is easy to troubleshoot.

Being a JVM language, Kotlin gives you great performance and an ability to leverage an entire ecosystem of tried and
true Java libraries.

Interactive
editors
Notebooks such as Jupyter Notebook and Apache Zeppelin provide convenient tools for data visualization and
exploratory research. Kotlin integrates with these tools to help you explore data, share your findings with colleagues, or
build up your data science and machine learning skills.

Jupyter
Kotlin
kernel
The Jupyter Notebook is an open-source web application that allows you to create and share documents (aka
"notebooks") that can contain code, visualizations, and markdown text. Kotlin-jupyter is an open source project that
brings Kotlin support to Jupyter Notebook.

70
Kotlin in Jupyter notebook

Check out Kotlin kernel's GitHub repo for installation instructions, documentation, and examples.

Zeppelin
Kotlin
interpreter
Apache Zeppelin is a popular web-based solution for interactive data analytics. It provides strong support for the Apache
Spark cluster computing system, which is particularly useful for data engineering. Starting from version 0.9.0, Apache
Zeppelin comes with bundled Kotlin interpreter.

71
Kotlin in Zeppelin notebook

Libraries
The ecosystem of libraries for data-related tasks created by the Kotlin community is rapidly expanding. Here are some
libraries that you may find useful:

Kotlin
libraries
Multik: multidimensional arrays in Kotlin. The library provides Kotlin-idiomatic, type- and dimension-safe API for
mathematical operations over multidimensional arrays. Multik offers swappable JVM and native computational
engines, and a combination of the two for optimal performance.

KotlinDL is a high-level Deep Learning API written in Kotlin and inspired by Keras. It offers simple APIs for training
deep learning models from scratch, importing existing Keras models for inference, and leveraging transfer learning for
tweaking existing pre-trained models to your tasks.

Kotlin for Apache Spark adds a missing layer of compatibility between Kotlin and Apache Spark. It allows Kotlin
developers to use familiar language features such as data classes, and lambda expressions as simple expressions in
curly braces or method references.

kotlin-statistics is a library providing extension functions for exploratory and production statistics. It supports basic
numeric list/sequence/array functions (from sum to skewness), slicing operators (such as countBy,
simpleRegressionBy), binning operations, discrete PDF sampling, naive bayes classifier, clustering, linear regression,
and much more.

kmath is a library inspired by NumPy. This library supports algebraic structures and operations, array-like structures,
math expressions, histograms, streaming operations, a wrapper around commons-math and koma, and more.

krangl is a library inspired by R's dplyr and Python's pandas. This library provides functionality for data manipulation
using a functional-style API; it also includes functions for filtering, transforming, aggregating, and reshaping tabular
data.

lets-plot is a plotting library for statistical data written in Kotlin. Lets-Plot is multiplatform and can be used not only with

72
JVM, but also with JS and Python.

kravis is another library for the visualization of tabular data inspired by R's ggplot.

londogard-nlp-toolkit is a library that provides utilities when working with natural language processing such as
word/subword/sentence embeddings, word-frequencies, stopwords, stemming, and much more.

Java
libraries
Since Kotlin provides first-class interop with Java, you can also use Java libraries for data science in your Kotlin code.
Here are some examples of such libraries:

DeepLearning4J- a deep learning library for Java

ND4J- an efficient matrix math library for JVM

Dex- a Java-based data visualization tool

Smile- a comprehensive machine learning, natural language processing, linear algebra, graph, interpolation, and
visualization system. Besides Java API, Smile also provides a functional Kotlin API along with Scala and Clojure API.

Smile-NLP-kt- a Kotlin rewrite of the Scala implicits for the natural language processing part of Smile in the format
of extension functions and interfaces.

Apache Commons Math- a general math, statistics, and machine learning library for Java

NM Dev- a Java mathematical library that covers all of classical mathematics.

OptaPlanner- a solver utility for optimization planning problems

Charts- a scientific JavaFX charting library in development

CoreNLP- a natural language processing toolkit

Apache Mahout- a distributed framework for regression, clustering and recommendation

Weka- a collection of machine learning algorithms for data mining tasks

If this list doesn’t cover your needs, you can find more options in the Kotlin Data Science Resources digest from
Thomas Nield.

Kotlin
for
competitive
programming
This tutorial is designed both for competitive programmers that did not use Kotlin before and for Kotlin developers that
did not participate in any competitive programming events before. It assumes the corresponding programming skills.

Competitive programming is a mind sport where contestants write programs to solve precisely specified algorithmic
problems within strict constraints. Problems can range from simple ones that can be solved by any software developer
and require little code to get a correct solution, to complex ones that require knowledge of special algorithms, data

73
structures, and a lot of practice. While not being specifically designed for competitive programming, Kotlin incidentally fits
well in this domain, reducing the typical amount of boilerplate that a programmer needs to write and read while working
with the code almost to the level offered by dynamically-typed scripting languages, while having tooling and performance
of a statically-typed language.

See Get started with Kotlin/JVM on how to set up development environment for Kotlin. In competitive programming, a
single project is usually created and each problem's solution is written in a single source file.

Simple
example:
Reachable
Numbers
problem
Let's take a look at a concrete example.

Codeforces Round 555 was held on April 26th for 3rd Division, which means it had problems fit for any developer to try.
You can use this link to read the problems. The simplest problem in the set is the Problem A: Reachable Numbers. It asks
to implement a straightforward algorithm described in the problem statement.

We'd start solving it by creating a Kotlin source file with an arbitrary name. A.kt will do well. First, we need to implement a
function specified in the problem statement as:

Let's denote a function f(x) in such a way: we add 1 to x, then, while there is at least one trailing zero in the resulting
number, we remove that zero.

Kotlin is a pragmatic and unopinionated language, supporting both imperative and function programming styles without
pushing the developer towards either one. We can implement the function f in functional style, using such Kotlin features
as tail recursion:

tailrec fun removeZeroes(x: Int): Int =


if (x % 10 == 0) removeZeroes(x / 10) else x

fun f(x: Int) = removeZeroes(x + 1)

Alternatively, we can write an imperative implementation of the function f using the traditional while loop and mutable
variables that are denoted in Kotlin with var:

fun f(x: Int): Int {


var cur = x + 1
while (cur % 10 == 0) cur /= 10
return cur
}

Types in Kotlin are optional in many places due to pervasive use of type-inference, but every declaration still has a well-
defined static type that is known at compilation.

Now, all is left is to write the main function that reads the input and implements the rest of the algorithm that the problem
statement asks for — to compute the number of different integers that are produced while repeatedly applying function f
to the initial number n that is given in the standard input.

By default, Kotlin runs on JVM and gives direct access to a rich and efficient collections library with general-purpose

74
collections and data-structures like dynamically-sized arrays (ArrayList), hash-based maps and sets (HashMap/ HashSet),
tree-based ordered maps and sets (TreeMap/ TreeSet), etc. Using a hash-set of integers to track values that were already
reached while applying function f, the straightforward imperative version of a solution to the problem can be written as
shown below:

fun main() {
var n = readLine()!!.toInt() // read integer from the input
val reached = HashSet<Int>() // a mutable hash set
while (reached.add(n)) n = f(n) // iterate function f
println(reached.size) // print answer to the output
}

Note the use of Kotlin's null-assertion operator !! after the readLine() function call. Kotlin's readLine() function is defined to
return a nullable type String? and returns null on the end of the input, which explicitly forces the developer to handle the
case of missing input.

There is no need to handle the case of misformatted input in competitive programming. In competitive programming, an
input format is always precisely specified and the actual input cannot deviate from the input specification in the problem
statement. That's what the null-assertion operator !! essentially does — it asserts that the input string is present and
throws an exception otherwise. Likewise, the String.toInt() function throws an exception if the input string is not an
integer.

All online competitive programming events allow the use of pre-written code, so you can define your own library of utility
functions that are geared towards competitive programming to make your actual solution code somewhat easier to read
and write. You would then use this code as a template for your solutions. For example, you can define the following helper
functions for reading inputs in competitive programming:

private fun readLn() = readLine()!!


private fun readInt() = readLn().toInt()
// etc for other types you'd use in your solutions

Note the use of private visibility modifier here. While the concept of visibility modifier is not relevant for competitive
programming at all, it allows you to place multiple solution files based on the same template without getting an error for
conflicting public declarations in the same package.

Functional
operators
example:
Long
Number
problem
For more complicated problems, Kotlin's extensive library of functional operations on collections comes in handy to
minimize the boilerplate and turn the code into a linear top-to-bottom and left-to-right fluent data transformation pipeline.
For example, the Problem B: Long Number problem takes a simple greedy algorithm to implement and it can be written
using this style without a single mutable variable:

fun main() {
// read input
val n = readLine()!!.toInt()
val s = readLine()!!
val fl = readLine()!!.split(" ").map { it.toInt() }

75
// define local function f
fun f(c: Char) = '0' + fl[c - '1']
// greedily find first and last indices
val i = s.indexOfFirst { c -> f(c) > c }
.takeIf { it >= 0 } ?: s.length
val j = s.withIndex().indexOfFirst { (j, c) -> j > i && f(c) < c }
.takeIf { it >= 0 } ?: s.length
// compose and write the answer
val ans =
s.substring(0, i) +
s.substring(i, j).map { c -> f(c) }.joinToString("") +
s.substring(j)
println(ans)
}

In this dense code, in addition to collection transformations, you can see such handy Kotlin features as local functions
and the elvis operator ?: that allow to express idioms like "take the value if it is positive or else use length" with a concise
and readable expressions like .takeIf { it >= 0 } ?: s.length, yet it is perfectly fine with Kotlin to create additional mutable
variables and express the same code in imperative style, too.

To make reading the input in competitive programming tasks like this more concise, you can have the following list of
helper input-reading functions:

private fun readLn() = readLine()!! // string line


private fun readInt() = readLn().toInt() // single int
private fun readStrings() = readLn().split(" ") // list of strings
private fun readInts() = readStrings().map { it.toInt() } // list of ints

With these helpers, the part of code for reading input becomes simpler, closely following the input specification in the
problem statement line by line:

// read input
val n = readInt()
val s = readLn()
val fl = readInts()

Note that in competitive programming it is customary to give variables shorter names than it is typical in industrial
programming practice, since the code is to be written just once and not supported thereafter. However, these names are
usually still mnemonic — a for arrays, i, j, etc for indices, r, and c for row and column numbers in tables, x and y for
coordinates, etc. It is easier to keep the same names for input data as it is given in the problem statement. However, more
complex problems require more code which leads to using longer self-explanatory variable and function names.

More
tips
and
tricks
Competitive programming problems often have input like this:

The first line of the input contains two integers n and k

In Kotlin this line can be concisely parsed with the following statement using destructuring declaration from a list of
integers:

76
val (n, k) = readInts()

It might be temping to use JVM's java.util.Scanner class to parse less structured input formats. Kotlin is designed to
interoperate well with JVM libraries, so that their use feels quite natural in Kotlin. However, beware that java.util.Scanner is
extremely slow. So slow, in fact, that parsing 10 5 or more integers with it might not fit into a typical 2 second time-limit,
which a simple Kotlin's split(" ").map { it.toInt() } would handle.

Writing output in Kotlin is usually straightforward with println(...) calls and using Kotlin's string templates. However, care
must be taken when output contains on order of 10 5 lines or more. Issuing so many println calls is too slow, since the
output in Kotlin is automatically flushed after each line. A faster way to write many lines from an array or a list is using
joinToString() function with "\n" as the separator, like this:

println(a.joinToString("\n")) // each element of array/list of a separate line

Learning
Kotlin
Kotlin is easy to learn, especially for those who already know Java. A short introduction to the basic syntax of Kotlin for
software developers can be found directly in the reference section of the web site starting from basic syntax.

IDEA has built-in Java-to-Kotlin converter. It can be used by people familiar with Java to learn the corresponding Kotlin
syntactic constructions, but it is not perfect and it is still worth familiarizing yourself with Kotlin and learning the Kotlin
idioms.

A great resource to study Kotlin syntax and API of the Kotlin standard library are Kotlin Koans.

What's
new
in
Kotlin
1.5.30
Release date: 24 August 2021

Kotlin 1.5.30 offers language updates including previews of future changes, various improvements in platform support
and tooling, and new standard library functions.

Here are some major improvements:

Language features, including experimental sealed when statements, changes in using opt-in requirement, and others

Native support for Apple silicon

Kotlin/JS IR backend reaches Beta

Improved Gradle plugin experience

You can also find a short overview of the changes in the release blog post and this video:

77
Gif

Watch video online.

Language
features
Kotlin 1.5.30 is presenting previews of future language changes and bringing improvements to the opt-in requirement
mechanism and type inference:

Exhaustive when statements for sealed and Boolean subjects

Suspending functions as supertypes

Requiring opt-in on implicit usages of experimental APIs

Changes to using opt-in requirement annotations with different targets

Improvements to type inference for recursive generic types

Eliminating builder inference restrictions

Exhaustive
when
statements
for
sealed
and
Boolean
subjects

Support for sealed (exhaustive) when statements is Experimental. It may be dropped or changed at any time.
Opt-in is required (see the details below), and you should use it only for evaluation purposes. We would
appreciate your feedback on it in YouTrack.

An exhaustive when statement contains branches for all possible types or values of its subject or for some types plus an
else branch. In other words, it covers all possible cases.

78
We’re planning to prohibit non-exhaustive when statements soon to make the behavior consistent with when
expressions. To ensure smooth migration, you can configure the compiler to report warnings about non-exhaustive when
statements with a sealed class or a Boolean. Such warnings will appear by default in Kotlin 1.6 and will become errors
later.

Enums already get a warning.

sealed class Mode {


object ON : Mode()
object OFF : Mode()
}

fun main() {
val x: Mode = Mode.ON
when (x) {
Mode.ON -> println("ON")
}
// WARNING: Non exhaustive 'when' statements on sealed classes/interfaces
// will be prohibited in 1.7, add an 'OFF' or 'else' branch instead

val y: Boolean = true


when (y) {
true -> println("true")
}
// WARNING: Non exhaustive 'when' statements on Booleans will be prohibited
// in 1.7, add a 'false' or 'else' branch instead
}

To enable this feature in Kotlin 1.5.30, use language version 1.6. You can also change the warnings to errors by enabling
progressive mode.

Kotlin

kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.6"
//progressiveMode = true // false by default
}
}
}

Groovy

kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.6'
//progressiveMode = true // false by default
}

79
}
}

Suspending
functions
as
supertypes

Support for suspending functions as supertypes is Experimental. It may be dropped or changed at any time.
Opt-in is required (see the details below), and you should use it only for evaluation purposes. We would
appreciate your feedback on it in YouTrack.

Kotlin 1.5.30 provides a preview of the ability to use a suspend functional type as a supertype with some limitations.

class MyClass: suspend () -> Unit {


override suspend fun invoke() { TODO() }
}

Use the -language-version 1.6 compiler option to enable the feature:

Kotlin

kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.6"
}
}
}

Groovy

kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.6'
}
}
}

The feature has the following restrictions:

You can’t mix an ordinary functional type and a suspend functional type as supertype. This is because of the
implementation details of suspend functional types in the JVM backend. They are represented in it as ordinary
functional types with a marker interface. Because of the marker interface, there is no way to tell which of the
superinterfaces are suspended and which are ordinary.

You can't use multiple suspend functional supertypes. If there are type checks, you also can’t use multiple

80
ordinary functional supertypes.

Requiring
opt-in
on
implicit
usages
of
experimental
APIs

The opt-in requirement mechanism is Experimental. It may change at any time. See how to opt-in. Use it only
for evaluation purposes. We would appreciate your feedback on it in YouTrack.

The author of a library can mark an experimental API as requiring opt-in to inform users about its experimental state. The
compiler raises a warning or error when the API is used and requires explicit consent to suppress it.

In Kotlin 1.5.30, the compiler treats any declaration that has an experimental type in the signature as experimental.
Namely, it requires opt-in even for implicit usages of an experimental API. For example, if the function’s return type is
marked as an experimental API element, a usage of the function requires you to opt-in even if the declaration is not
marked as requiring an opt-in explicitly.

// Library code

@RequiresOptIn(message = "This API is experimental.")


@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS)
annotation class MyDateTime // Opt-in requirement annotation

@MyDateTime
class DateProvider // A class requiring opt-in

// Client code

// Warning: experimental API usage


fun createDateSource(): DateProvider { /* ... */ }

fun getDate(): Date {


val dateSource = createDateSource() // Also warning: experimental API usage
// ...
}

Learn more about opt-in requirements.

Changes
to
using
opt-in
requirement
annotations
with
different
targets

The opt-in requirement mechanism is Experimental. It may change at any time. See how to opt-in. Use it only
for evaluation purposes. We would appreciate your feedback on it in YouTrack.

Kotlin 1.5.30 presents new rules for using and declaring opt-in requirement annotations on different targets. The compiler
now reports an error for use cases that are impractical to handle at compile time. In Kotlin 1.5.30:

81
Marking local variables and value parameters with opt-in requirement annotations is forbidden at the use site.

Marking override is allowed only if its basic declaration is also marked.

Marking backing fields and getters is forbidden. You can mark the basic property instead.

Setting TYPE and TYPE_PARAMETER annotation targets is forbidden at the opt-in requirement annotation declaration
site.

Learn more about opt-in requirements.

Improvements
to
type
inference
for
recursive
generic
types
In Kotlin and Java, you can define a recursive generic type, which references itself in its type parameters. In Kotlin 1.5.30,
the Kotlin compiler can infer a type argument based only on upper bounds of the corresponding type parameter if it is a
recursive generic. This makes it possible to create various patterns with recursive generic types that are often used in
Java to make builder APIs.

// Kotlin 1.5.20
val containerA = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13-alpine")).apply
{
withDatabaseName("db")
withUsername("user")
withPassword("password")
withInitScript("sql/schema.sql")
}

// Kotlin 1.5.30
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
.withDatabaseName("db")
.withUsername("user")
.withPassword("password")
.withInitScript("sql/schema.sql")

You can enable the improvements by passing the -Xself-upper-bound-inference or the -language-version 1.6 compiler
options. See other examples of newly supported use cases in this YouTrack ticket.

Eliminating
builder
inference
restrictions
Builder inference is a special kind of type inference that allows you to infer the type arguments of a call based on type
information from other calls inside its lambda argument. This can be useful when calling generic builder functions such as
buildList() or sequence(): buildList { add("string") }.

Inside such a lambda argument, there was previously a limitation on using the type information that the builder inference
tries to infer. This means you can only specify it and cannot get it. For example, you cannot call get() inside a lambda
argument of buildList() without explicitly specified type arguments.

Kotlin 1.5.30 removes these limitations with the -Xunrestricted-builder-inference compiler option. Add this option to
enable previously prohibited calls inside a lambda argument of generic builder functions:

82
@kotlin.ExperimentalStdlibApi
val list = buildList {
add("a")
add("b")
set(1, null)
val x = get(1)
if (x != null) {
removeAt(1)
}
}

@kotlin.ExperimentalStdlibApi
val map = buildMap {
put("a", 1)
put("b", 1.1)
put("c", 2f)
}

Also, you can enable this feature with the -language-version 1.6 compiler option.

Kotlin/JVM
With Kotlin 1.5.30, Kotlin/JVM receives the following features:

Instantiation of annotation classes

Improved nullability annotation support configuration

See the Gradle section for Kotlin Gradle plugin updates on the JVM platform.

Instantiation
of
annotation
classes

Instantiation of annotation classes is Experimental. It may be dropped or changed at any time. Opt-in is
required (see the details below), and you should use it only for evaluation purposes. We would appreciate your
feedback on it in YouTrack.

With Kotlin 1.5.30 you can now call constructors of annotation classes in arbitrary code to obtain a resulting instance. This
feature covers the same use cases as the Java convention that allows the implementation of an annotation interface.

annotation class InfoMarker(val info: String)

fun processInfo(marker: InfoMarker) = ...

fun main(args: Array<String>) {


if (args.size != 0)
processInfo(getAnnotationReflective(args))
else
processInfo(InfoMarker("default"))

83
}

Use the -language-version 1.6 compiler option to enable this feature. Note that all current annotation class limitations,
such as restrictions to define non- val parameters or members different from secondary constructors, remain intact.

Learn more about instantiation of annotation classes in this KEEP

Improved
nullability
annotation
support
configuration
The Kotlin compiler can read various types of nullability annotations to get nullability information from Java. This
information allows it to report nullability mismatches in Kotlin when calling Java code.

In Kotlin 1.5.30, you can specify whether the compiler reports a nullability mismatch based on the information from
specific types of nullability annotations. Just use the compiler option -Xnullability-annotations=@<package-name>:
<report-level>. In the argument, specify the fully qualified nullability annotations package and one of these report levels:

ignore to ignore nullability mismatches

warn to report warnings

strict to report errors.

See the full list of supported nullability annotations along with their fully qualified package names.

Here is an example showing how to enable error reporting for the newly supported RxJava 3 nullability annotations: -
[email protected]:strict. Note that all such nullability mismatches are warnings by
default.

Kotlin/Native
Kotlin/Native has received various changes and improvements:

Apple silicon support

Improved Kotlin DSL for the CocoaPods Gradle plugin

Experimental interoperability with Swift 5.5 async/await

Improved Swift/Objective-C mapping for objects and companion objects

Deprecation of linkage against DLLs without import libraries for MinGW targets

Apple
silicon
support
Kotlin 1.5.30 introduces native support for Apple silicon.

Previously, the Kotlin/Native compiler and tooling required the Rosetta translation environment for working on Apple
silicon hosts. In Kotlin 1.5.30, the translation environment is no longer needed – the compiler and tooling can run on
Apple silicon hardware without requiring any additional actions.

84
We’ve also introduced new targets that make Kotlin code run natively on Apple silicon:

macosArm64

iosSimulatorArm64

watchosSimulatorArm64

tvosSimulatorArm64

They are available on both Intel-based and Apple silicon hosts. All existing targets are available on Apple silicon hosts as
well.

Note that in 1.5.30 we provide only basic support for Apple silicon targets in the kotlin-multiplatform Gradle plugin.
Particularly, the new simulator targets aren’t included in the ios, tvos, and watchos target shortcuts. Learn how to use
Apple silicon targets with the target shortcuts. We will keep working to improve the user experience with the new targets.

Improved
Kotlin
DSL
for
the
CocoaPods
Gradle
plugin

New parameters for Kotlin/Native frameworks


Kotlin 1.5.30 introduces the improved CocoaPods Gradle plugin DSL for Kotlin/Native frameworks. In addition to the
name of the framework, you can specify other parameters in the pod configuration:

Specify the dynamic or static version of the framework

Enable export dependencies explicitly

Enable Bitcode embedding

To use the new DSL, update your project to Kotlin 1.5.30, and specify the parameters in the cocoapods section of your
build.gradle(.kts) file:

cocoapods {
frameworkName = "MyFramework" // This property is deprecated
// and will be removed in future versions
// New DSL for framework configuration:
framework {
// All Framework properties are supported
// Framework name configuration. Use this property instead of
// deprecated 'frameworkName'
baseName = "MyFramework"
// Dynamic framework support
isStatic = false
// Dependency export
export(project(":anotherKMMModule"))
transitiveExport = true
// Bitcode embedding
embedBitcode(BITCODE)
}
}

85
Support custom names for Xcode configuration
The Kotlin CocoaPods Gradle plugin supports custom names in the Xcode build configuration. It will also help you if
you’re using special names for the build configuration in Xcode, for example Staging.

To specify a custom name, use the xcodeConfigurationToNativeBuildType parameter in the cocoapods section of your
build.gradle(.kts) file:

cocoapods {
// Maps custom Xcode configuration to NativeBuildType
xcodeConfigurationToNativeBuildType["CUSTOM_DEBUG"] = NativeBuildType.DEBUG
xcodeConfigurationToNativeBuildType["CUSTOM_RELEASE"] = NativeBuildType.RELEASE
}

This parameter will not appear in the podspec file. When Xcode runs the Gradle build process, the Kotlin CocoaPods
Gradle plugin will select the necessary native build type.

There’s no need to declare the Debug and Release configurations because they are supported by default.

Experimental
interoperability
with
Swift
5.5
async/await

Concurrency interoperability with Swift async/await is Experimental. It may be dropped or changed at any time.
You should use it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

We added support for calling Kotlin’s suspending functions from Objective-C and Swift in 1.4.0, and now we’re
improving it to keep up with a new Swift 5.5 feature – concurrency with async and await modifiers.

The Kotlin/Native compiler now emits the _Nullable_result attribute in the generated Objective-C headers for suspending
functions with nullable return types. This makes it possible to call them from Swift as async functions with the proper
nullability.

Note that this feature is experimental and can be affected in the future by changes in both Kotlin and Swift. For now,
we’re offering a preview of this feature that has certain limitations, and we are eager to hear what you think. Learn
more about its current state and leave your feedback in this YouTrack issue.

Improved
Swift/Objective-C
mapping
for
objects
and
companion
objects
Getting objects and companion objects can now be done in a way that is more intuitive for native iOS developers. For
example, if you have the following objects in Kotlin:

object MyObject {
val x = "Some value"
}

class MyClass {

86
companion object {
val x = "Some value"
}
}

To access them in Swift, you can use the shared and companion properties:

MyObject.shared
MyObject.shared.x
MyClass.companion
MyClass.Companion.shared

Learn more about Swift/Objective-C interoperability.

Deprecation
of
linkage
against
DLLs
without
import
libraries
for
MinGW
targets
LLD is a linker from the LLVM project, which we plan to start using in Kotlin/Native for MinGW targets because of its
benefits over the default ld.bfd – primarily its better performance.

However, the latest stable version of LLD doesn’t support direct linkage against DLL for MinGW (Windows) targets.
Such linkage requires using import libraries. Although they aren’t needed with Kotlin/Native 1.5.30, we’re adding a
warning to inform you that such usage is incompatible with LLD that will become the default linker for MinGW in the
future.

Please share your thoughts and concerns about the transition to the LLD linker in this YouTrack issue.

Kotlin
Multiplatform
1.5.30 brings the following notable updates to Kotlin Multiplatform:

Ability to use custom cinterop libraries in shared native code

Support for XCFrameworks

New default publishing setup for Android artifacts

Ability
to
use
custom
cinterop
libraries
in
shared
native
code
Kotlin Multiplatform gives you an option to use platform-dependent interop libraries in shared source sets. Before 1.5.30,
this worked only with platform libraries shipped with Kotlin/Native distribution. Starting from 1.5.30, you can use it with
your custom cinterop libraries. To enable this feature, add the kotlin.mpp.enableCInteropCommonization=true property in
your gradle.properties:

kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.enableCInteropCommonization=true

87
Support
for
XCFrameworks
All Kotlin Multiplatform projects can now have XCFrameworks as an output format. Apple introduced XCFrameworks as a
replacement for universal (fat) frameworks. With the help of XCFrameworks you:

Can gather logic for all the target platforms and architectures in a single bundle.

Don't need to remove all unnecessary architectures before publishing the application to the App Store.

XCFrameworks is useful if you want to use your KMM framework for devices and simulators on Apple M1.

To use XCFrameworks, update your build.gradle(.kts) script:

Kotlin

import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework

plugins {
kotlin("multiplatform")
}

kotlin {
val xcf = XCFramework()

ios {
binaries.framework {
baseName = "shared"
xcf.add(this)
}
}
watchos {
binaries.framework {
baseName = "shared"
xcf.add(this)
}
}
tvos {
binaries.framework {
baseName = "shared"
xcf.add(this)
}
}
}

Groovy

import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFrameworkConfig

plugins {
id 'org.jetbrains.kotlin.multiplatform'
}

kotlin {
def xcf = XCFrameworkConfig(project)

ios {

88
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
watchos {
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
tvos {
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
}

When you declare XCFrameworks, these new Gradle tasks will be registered:

assembleXCFramework

assembleDebugXCFramework (additionally debug artifact that contains dSYMs)

assembleReleaseXCFramework

Learn more about XCFrameworks in this WWDC video.

New
default
publishing
setup
for
Android
artifacts
Using the maven-publish Gradle plugin, you can publish your multiplatform library for the Android target by specifying
Android variant names in the build script. The Kotlin Gradle plugin will generate publications automatically.

Before 1.5.30, the generated publication metadata included the build type attributes for every published Android variant,
making it compatible only with the same build type used by the library consumer. Kotlin 1.5.30 introduces a new default
publishing setup:

If all Android variants that the project publishes have the same build type attribute, then the published variants won't
have the build type attribute and will be compatible with any build type.

If the published variants have different build type attributes, then only those with the release value will be published
without the build type attribute. This makes the release variants compatible with any build type on the consumer side,
while non-release variants will only be compatible with the matching consumer build types.

To opt-out and keep the build type attributes for all variants, you can set this Gradle property:
kotlin.android.buildTypeAttribute.keep=true.

Kotlin/JS
Two major improvements are coming to Kotlin/JS with 1.5.30:

89
JS IR compiler backend reaches Beta

Better debugging experience for applications with the Kotlin/JS IR backend

JS
IR
compiler
backend
reaches
Beta
The IR-based compiler backend for Kotlin/JS, which was introduced in 1.4.0 in Alpha, has reached Beta.

Previously, we published the migration guide for the JS IR backend to help you migrate your projects to the new backend.
Now we would like to present the Kotlin/JS Inspection Pack IDE plugin, which displays the required changes directly in
IntelliJ IDEA.

Better
debugging
experience
for
applications
with
the
Kotlin/JS
IR
backend
Kotlin 1.5.30 brings JavaScript source map generation for the Kotlin/JS IR backend. This will improve the Kotlin/JS
debugging experience when the IR backend is enabled, with full debugging support that includes breakpoints, stepping,
and readable stack traces with proper source references.

Learn more about how to debug Kotlin/JS in the browser or IntelliJ IDEA Ultimate.

Gradle
As a part of our mission to improve the Kotlin Gradle plugin user experience, we’ve implemented the following
features:

Support for Java toolchains, which includes an ability to specify a JDK home with the UsesKotlinJavaToolchain
interface for older Gradle versions

An easier way to explicitly specify the Kotlin daemon’s JVM arguments

Support
for
Java
toolchains
Gradle 6.7 introduced the "Java toolchains support" feature. Using this feature, you can:

Run compilations, tests, and executables using JDKs and JREs that are different from the Gradle ones.

Compile and test code with an unreleased language version.

With toolchains support, Gradle can autodetect local JDKs and install missing JDKs that Gradle requires for the build.
Now Gradle itself can run on any JDK and still reuse the build cache feature.

The Kotlin Gradle plugin supports Java toolchains for Kotlin/JVM compilation tasks. A Java toolchain:

Sets the jdkHome option available for JVM targets.

The ability to set the jdkHome option directly has been deprecated.

90
Sets the kotlinOptions.jvmTarget to the toolchain's JDK version if the user didn’t set the jvmTarget option
explicitly. If the toolchain is not configured, the jvmTarget field uses the default value. Learn more about JVM target
compatibility.

Affects which JDK kapt workers are running on.

Use the following code to set a toolchain. Replace the placeholder <MAJOR_JDK_VERSION> with the JDK version you
would like to use:

Kotlin

kotlin {
jvmToolchain {
(this as
JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // “8â€​
}
}

Groovy

kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // “8â€​
}
}

Note that setting a toolchain via the kotlin extension will update the toolchain for Java compile tasks as well.

You can set a toolchain via the java extension, and Kotlin compilation tasks will use it:

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // “8â€​
}
}

For information about setting any JDK version for KotlinCompile tasks, look through the docs about setting the JDK
version with the Task DSL.

For Gradle versions from 6.1 to 6.6, use the UsesKotlinJavaToolchain interface to set the JDK home.

Ability
to
specify
JDK
home
with
UsesKotlinJavaToolchain
interface
All Kotlin tasks that support setting the JDK via kotlinOptions now implement the UsesKotlinJavaToolchain interface. To
set the JDK home, put a path to your JDK and replace the <JDK_VERSION> placeholder:

Kotlin

91
project.tasks
.withType<UsesKotlinJavaToolchain>()
.configureEach {
it.kotlinJavaToolchain.jdk.use(
"/path/to/local/jdk",
JavaVersion.<LOCAL_JDK_VERSION>
)
}

Groovy

project.tasks
.withType(UsesKotlinJavaToolchain.class)
.configureEach {
it.kotlinJavaToolchain.jdk.use(
'/path/to/local/jdk',
JavaVersion.<LOCAL_JDK_VERSION>
)
}

Use the UsesKotlinJavaToolchain interface for Gradle versions from 6.1 to 6.6. Starting from Gradle 6.7, use the Java
toolchains instead.

When using this feature, note that kapt task workers will only use process isolation mode, and the kapt.workers.isolation
property will be ignored.

Easier
way
to
explicitly
specify
Kotlin
daemon
JVM
arguments
In Kotlin 1.5.30, there’s a new logic for the Kotlin daemon’s JVM arguments. Each of the options in the following
list overrides the ones that came before it:

If nothing is specified, the Kotlin daemon inherits arguments from the Gradle daemon (as before). For example, in the
gradle.properties file:

org.gradle.jvmargs=-Xmx1500m -Xms=500m

If the Gradle daemon’s JVM arguments have the kotlin.daemon.jvm.options system property, use it as before:

org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m -Xms=500m

You can add the kotlin.daemon.jvmargs property in the gradle.properties file:

kotlin.daemon.jvmargs=-Xmx1500m -Xms=500m

You can specify arguments in the kotlin extension:

92
Kotlin

kotlin {
kotlinDaemonJvmArgs = listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC")
}

Groovy

kotlin {
kotlinDaemonJvmArgs = ["-Xmx486m", "-Xms256m", "-XX:+UseParallelGC"]
}

You can specify arguments for a specific task:

Kotlin

tasks
.matching { it.name == "compileKotlin" && it is CompileUsingKotlinDaemon }
.configureEach {
(this as CompileUsingKotlinDaemon).kotlinDaemonJvmArguments.set(listOf("-Xmx486m", "-
Xms256m", "-XX:+UseParallelGC"))
}

Groovy

tasks
.matching {
it.name == "compileKotlin" && it instanceof CompileUsingKotlinDaemon
}
.configureEach {
kotlinDaemonJvmArguments.set(["-Xmx1g", "-Xms512m"])
}

In this case a new Kotlin daemon instance can start on task execution. Learn more about the Kotlin
daemon’s interactions with JVM arguments.

For more information about the Kotlin daemon, see the Kotlin daemon and using it with Gradle.

Standard
library
Kotlin 1.5.30 is bringing improvements to the standard library’s Duration and Regex APIs:

Changing Duration.toString() output

93
Parsing Duration from String

Matching with Regex at a particular position

Splitting Regex to a sequence

Changing
Duration.toString()
output

The Duration API is Experimental. It may be dropped or changed at any time. Use it only for evaluation
purposes. We would appreciate hearing your feedback on it in YouTrack.

Before Kotlin 1.5.30, the Duration.toString() function would return a string representation of its argument expressed in the
unit that yielded the most compact and readable number value. From now on, it will return a string value expressed as a
combination of numeric components, each in its own unit. Each component is a number followed by the unit’s
abbreviated name: d, h, m, s. For example:

Example of function call Previous output Current output

Duration.days(45).toString() 45.0d 45d

Duration.days(1.5).toString() 36.0h 1d 12h

Duration.minutes(1230).toString() 20.5h 20h 30m

Duration.minutes(2415).toString() 40.3h 1d 16h 15m

Duration.minutes(920).toString() 920m 15h 20m

Duration.seconds(1.546).toString() 1.55s 1.546s

Duration.milliseconds(25.12).toString() 25.1ms 25.12ms

The way negative durations are represented has also been changed. A negative duration is prefixed with a minus sign (-),
and if it consists of multiple components, it is surrounded with parentheses: -12m and -(1h 30m).

Note that small durations of less than one second are represented as a single number with one of the subsecond units.
For example, ms (milliseconds), us (microseconds), or ns (nanoseconds): 140.884ms, 500us, 24ns. Scientific notation is
no longer used to represent them.

If you want to express duration in a single unit, use the overloaded Duration.toString(unit, decimals) function.

94
We recommend using Duration.toIsoString() in certain cases, including serialization and interchange.
Duration.toIsoString() uses the stricter ISO-8601 format instead of Duration.toString().

Parsing
Duration
from
String

The Duration API is Experimental. It may be dropped or changed at any time. Use it only for evaluation
purposes. We would appreciate hearing your feedback on it in this issue.

In Kotlin 1.5.30, there are new functions in the Duration API:

parse(), which supports parsing the outputs of:


toString().

toString(unit, decimals).

toIsoString().

parseIsoString(), which only parses from the format produced by toIsoString().

parseOrNull() and parseIsoStringOrNull(), which behave like the functions above but return null instead of throwing
IllegalArgumentException on invalid duration formats.

Here are some examples of parse() and parseOrNull() usages:

import kotlin.time.Duration
import kotlin.time.ExperimentalTime

@ExperimentalTime
fun main() {
//sampleStart
val isoFormatString = "PT1H30M"
val defaultFormatString = "1h 30m"
val singleUnitFormatString = "1.5h"
val invalidFormatString = "1 hour 30 minutes"
println(Duration.parse(isoFormatString)) // "1h 30m"
println(Duration.parse(defaultFormatString)) // "1h 30m"
println(Duration.parse(singleUnitFormatString)) // "1h 30m"
//println(Duration.parse(invalidFormatString)) // throws exception
println(Duration.parseOrNull(invalidFormatString)) // "null"
//sampleEnd
}

And here are some examples of parseIsoString() and parseIsoStringOrNull() usages:

import kotlin.time.Duration
import kotlin.time.ExperimentalTime

@ExperimentalTime

95
fun main() {
//sampleStart
val isoFormatString = "PT1H30M"
val defaultFormatString = "1h 30m"
println(Duration.parseIsoString(isoFormatString)) // "1h 30m"
//println(Duration.parseIsoString(defaultFormatString)) // throws exception
println(Duration.parseIsoStringOrNull(defaultFormatString)) // "null"
//sampleEnd
}

Matching
with
Regex
at
a
particular
position

Regex.matchAt() and Regex.matchesAt() functions are Experimental. They may be dropped or changed at any
time. Use them only for evaluation purposes. We would appreciate hearing your feedback on them in YouTrack.

The new Regex.matchAt() and Regex.matchesAt() functions provide a way to check whether a regex has an exact match
at a particular position in a String or CharSequence.

matchesAt() returns a boolean result:

fun main(){
//sampleStart
val releaseText = "Kotlin 1.5.30 is released!"
// regular expression: one digit, dot, one digit, dot, one or more digits
val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()
println(versionRegex.matchesAt(releaseText, 0)) // "false"
println(versionRegex.matchesAt(releaseText, 7)) // "true"
//sampleEnd
}

matchAt() returns the match if one is found or null if one isn’t:

fun main(){
//sampleStart
val releaseText = "Kotlin 1.5.30 is released!"
val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()
println(versionRegex.matchAt(releaseText, 0)) // "null"
println(versionRegex.matchAt(releaseText, 7)?.value) // "1.5.30"
//sampleEnd
}

Splitting
Regex
to
a
sequence

96
Regex.splitToSequence() and CharSequence.splitToSequence(Regex) functions are Experimental. They may be
dropped or changed at any time. Use them only for evaluation purposes. We would appreciate hearing your
feedback on them in YouTrack.

The new Regex.splitToSequence() function is a lazy counterpart of split(). It splits the string around matches of the given
regex, but it returns the result as a Sequence so that all operations on this result are executed lazily.

fun main(){
//sampleStart
val colorsText = "green, red , brown&blue, orange, pink&green"
val regex = "[,\\s]+".toRegex()
val mixedColor = regex.splitToSequence(colorsText)
.onEach { println(it) }
.firstOrNull { it.contains('&') }
println(mixedColor) // "brown&blue"
//sampleEnd
}

A similar function was also added to CharSequence:

val mixedColor = colorsText.splitToSequence(regex)

Serialization
1.3.0-RC
kotlinx.serialization 1.3.0-RC is here with new JSON serialization capabilities:

Java IO streams serialization

Property-level control over default values

An option to exclude null values from serialization

Custom class discriminators in polymorphic serialization

Learn more in the changelog.

What's
new
in
Kotlin
1.5.20
Release date: 24 June 2021

Kotlin 1.5.20 has fixes for issues discovered in the new features of 1.5.0, and it also includes various tooling
improvements.

You can find an overview of the changes in the release blog post and this video:

97
Gif

Watch video online.

Kotlin/JVM
Kotlin 1.5.20 is receiving the following updates on the JVM platform:

String concatenation via invokedynamic

Support for JSpecify nullness annotations

Support for calling Java’s Lombok-generated methods within modules that have Kotlin and Java code

String
concatenation
via
invokedynamic
Kotlin 1.5.20 compiles string concatenations into dynamic invocations (invokedynamic) on JVM 9+ targets, thereby
keeping up with modern Java versions. More precisely, it uses StringConcatFactory.makeConcatWithConstants() for
string concatenation.

To switch back to concatenation via StringBuilder.append() used in previous versions, add the compiler option -Xstring-
concat=inline.

Learn how to add compiler options in Gradle, Maven, and the command-line compiler.

Support
for
JSpecify
nullness
annotations
The Kotlin compiler can read various types of nullability annotations to pass nullability information from Java to Kotlin.
Version 1.5.20 introduces support for the JSpecify project, which includes the standard unified set of Java nullness
annotations.

With JSpecify, you can provide more detailed nullability information to help Kotlin keep null-safety interoperating with

98
Java. You can set default nullability for the declaration, package, or module scope, specify parametric nullability, and
more. You can find more details about this in the JSpecify user guide.

Here is the example of how Kotlin can handle JSpecify annotations:

// JavaClass.java
import *;

@NullMarked
public class JavaClass {
public String notNullableString() { return ""; }
public @Nullable String nullableString() { return ""; }
}

// Test.kt
fun kotlinFun() = with(JavaClass()) {
notNullableString().length // OK
nullableString().length // Warning: receiver nullability mismatch
}

In 1.5.20, all nullability mismatches according to the JSpecify-provided nullability information are reported as warnings.
Use the -Xjspecify-annotations=strict and -Xtype-enhancement-improvements-strict-mode compiler options to enable
strict mode (with error reporting) when working with JSpecify. Please note that the JSpecify project is under active
development. Its API and implementation can change significantly at any time.

Learn more about null-safety and platform types.

Support
for
calling
Java’s
Lombok-generated
methods
within
modules
that
have
Kotlin
and
Java
code

The Lombok compiler plugin is Experimental. It may be dropped or changed at any time. Use it only for
evaluation purposes. We would appreciate your feedback on it in YouTrack.

Kotlin 1.5.20 introduces an experimental Lombok compiler plugin. This plugin makes it possible to generate and use
Java’s Lombok declarations within modules that have Kotlin and Java code. Lombok annotations work only in Java
sources and are ignored if you use them in Kotlin code.

The plugin supports the following annotations:

@Getter, @Setter

@NoArgsConstructor, @RequiredArgsConstructor, and @AllArgsConstructor

@Data

@With

@Value

99
We're continuing to work on this plugin. To find out the detailed current state, visit the Lombok compiler plugin's
README.

Currently, we don't have plans to support the @Builder annotation. However, we can consider this if you vote for @Builder
in YouTrack.

Learn how to configure the Lombok compiler plugin.

Kotlin/Native
Kotlin/Native 1.5.20 offers a preview of the new feature and the tooling improvements:

Opt-in export of KDoc comments to generated Objective-C headers

Compiler bug fixes

Improved performance of Array.copyInto() inside one array

Opt-in
export
of
KDoc
comments
to
generated
Objective-C
headers

The ability to export KDoc comments to generated Objective-C headers is Experimental. It may be dropped or
changed at any time. Opt-in is required (see the details below), and you should use it only for evaluation
purposes. We would appreciate your feedback on it in YouTrack.

You can now set the Kotlin/Native compiler to export the documentation comments (KDoc) from Kotlin code to the
Objective-C frameworks generated from it, making them visible to the frameworks’ consumers.

For example, the following Kotlin code with KDoc:

/**
* Prints the sum of the arguments.
* Properly handles the case when the sum doesn't fit in 32-bit integer.
*/
fun printSum(a: Int, b: Int) = println(a.toLong() + b)

produces the following Objective-C headers:

/**
* Prints the sum of the arguments.
* Properly handles the case when the sum doesn't fit in 32-bit integer.
*/
+ (void)printSumA:(int32_t)a b:(int32_t)b __attribute__((swift_name("printSum(a:b:)")));

This also works well with Swift.

To try out this ability to export KDoc comments to Objective-C headers, use the -Xexport-kdoc compiler option. Add the

100
following lines to build.gradle(.kts) of the Gradle projects you want to export comments from:

Kotlin

kotlin {
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
compilations.get("main").kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
}
}

Groovy

kotlin {
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget) {
compilations.get("main").kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
}
}

We’d be very grateful if you would share your feedback with us using this YouTrack ticket.

Compiler
bug
fixes
The Kotlin/Native compiler has received multiple bug fixes in 1.5.20. You can find the complete list in the changelog.

There is an important bug fix that affects compatibility: in previous versions, string constants that contained incorrect UTF
surrogate pairs were losing their values during compilation. Now such values are preserved. Application developers can
safely update to 1.5.20 – nothing will break. However, libraries compiled with 1.5.20 are incompatible with earlier
compiler versions. See this YouTrack issue for details.

Improved
performance
of
Array.copyInto()
inside
one
array
We’ve improved the way Array.copyInto() works when its source and destination are the same array. Now such
operations finish up to 20 times faster (depending on the number of objects being copied) due to memory management
optimizations for this use case.

Kotlin/JS
With 1.5.20, we’re publishing a guide that will help you migrate your projects to the new IR-based backend for
Kotlin/JS.

Migration
guide
for
the
JS
IR
backend
The new migration guide for the JS IR backend identifies issues you may encounter during migration and provides
solutions for them. If you find any issues that aren’t covered in the guide, please report them to our issue tracker.

101
Gradle
Kotlin 1.5.20 introduces the following features that can improve the Gradle experience:

Caching for annotation processors classloaders in kapt

Deprecation of the kotlin.parallel.tasks.in.project build property

Caching
for
annotation
processors'
classloaders
in
kapt

Caching for annotation processors' classloaders in kapt is Experimental. It may be dropped or changed at any
time. Use it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

There is now a new experimental feature that makes it possible to cache the classloaders of annotation processors in
kapt. This feature can increase the speed of kapt for consecutive Gradle runs.

To enable this feature, use the following properties in your gradle.properties file:

# positive value will enable caching


# use the same value as the number of modules that use kapt
kapt.classloaders.cache.size=5

# disable for caching to work


kapt.include.compile.classpath=false

Learn more about kapt.

Deprecation
of
the
kotlin.parallel.tasks.in.project
build
property
With this release, Kotlin parallel compilation is controlled by the Gradle parallel execution flag --parallel. Using this flag,
Gradle executes tasks concurrently, increasing the speed of compiling tasks and utilizing the resources more efficiently.

You no longer need to use the kotlin.parallel.tasks.in.project property. This property has been deprecated and will be
removed in the next major release.

Standard
library
Kotlin 1.5.20 changes the platform-specific implementations of several functions for working with characters and as a
result brings unification across platforms:

Support for all Unicode digits in Char.digitToInt() for Kotlin/Native and Kotlin/JS.

Unification of Char.isLowerCase()/isUpperCase() implementations across platforms.

102
Support
for
all
Unicode
digits
in
Char.digitToInt()
in
Kotlin/Native
and
Kotlin/JS
Char.digitToInt() returns the numeric value of the decimal digit that the character represents. Before 1.5.20, the function
supported all Unicode digit characters only for Kotlin/JVM: implementations on the Native and JS platforms supported
only ASCII digits.

From now, both with Kotlin/Native and Kotlin/JS, you can call Char.digitToInt() on any Unicode digit character and get its
numeric representation.

fun main() {
//sampleStart
val ten = '\u0661'.digitToInt() + '\u0039'.digitToInt() // ARABIC-INDIC DIGIT ONE + DIGIT
NINE
println(ten)
//sampleEnd
}

Unification
of
Char.isLowerCase()/isUpperCase()
implementations
across
platforms
The functions Char.isUpperCase() and Char.isLowerCase() return a boolean value depending on the case of the character.
For Kotlin/JVM, the implementation checks both the General_Category and the Other_Uppercase/ Other_Lowercase
Unicode properties.

Prior to 1.5.20, implementations for other platforms worked differently and considered only the general category. In
1.5.20, implementations are unified across platforms and use both properties to determine the character case:

fun main() {
//sampleStart
val latinCapitalA = 'A' // has "Lu" general category
val circledLatinCapitalA = 'â’¶' // has "Other_Uppercase" property
println(latinCapitalA.isUpperCase() && circledLatinCapitalA.isUpperCase())
//sampleEnd
}

What's
new
in
Kotlin
1.5.0
Release date: 5 May 2021

Kotlin 1.5.0 introduces new language features, stable IR-based JVM compiler backend, performance improvements, and
evolutionary changes such as stabilizing experimental features and deprecating outdated ones.

You can also find an overview of the changes in the release blog post.

Language
features
Kotlin 1.5.0 brings stable versions of the new language features presented for preview in 1.4.30:

103
JVM records support

Sealed interfaces and sealed class improvements

Inline classes

Detailed descriptions of these features are available in this blog post and the corresponding pages of Kotlin
documentation.

JVM
records
support
Java is evolving fast, and to make sure Kotlin remains interoperable with it, we’ve introduced support for one of its
latest features – record classes.

Kotlin’s support for JVM records includes bidirectional interoperability:

In Kotlin code, you can use Java record classes like you would use typical classes with properties.

To use a Kotlin class as a record in Java code, make it a data class and mark it with the @JvmRecord annotation.

@JvmRecord
data class User(val name: String, val age: Int)

Learn more about using JVM records in Kotlin.

Gif

Watch video online.

Sealed
interfaces
Kotlin interfaces can now have the sealed modifier, which works on interfaces in the same way it works on classes: all
implementations of a sealed interface are known at compile time.

104
sealed interface Polygon

You can rely on that fact, for example, to write exhaustive when expressions.

fun draw(polygon: Polygon) = when (polygon) {


is Rectangle -> // ...
is Triangle -> // …
// else is not needed - all possible implementations are covered
}

Additionally, sealed interfaces enable more flexible restricted class hierarchies because a class can directly inherit more
than one sealed interface.

class FilledRectangle: Polygon, Fillable

Learn more about sealed interfaces.

Gif

Watch video online.

Package-wide
sealed
class
hierarchies
Sealed classes can now have subclasses in all files of the same compilation unit and the same package. Previously, all
subclasses had to appear in the same file.

Direct subclasses may be top-level or nested inside any number of other named classes, named interfaces, or named
objects.

105
The subclasses of a sealed class must have a name that is properly qualified – they cannot be local or anonymous
objects.

Learn more about sealed class hierarchies.

Inline
classes
Inline classes are a subset of value-based classes that only hold values. You can use them as wrappers for a value of a
certain type without the additional overhead that comes from using memory allocations.

Inline classes can be declared with the value modifier before the name of the class:

value class Password(val s: String)

The JVM backend also requires a special @JvmInline annotation:

@JvmInline
value class Password(val s: String)

The inline modifier is now deprecated with a warning.

Learn more about inline classes.

Gif

Watch video online.

Kotlin/JVM
Kotlin/JVM has received a number of improvements, both internal and user-facing. Here are the most notable among

106
them:

Stable JVM IR backend

New default JVM target: 1.8

SAM adapters via invokedynamic

Lambdas via invokedynamic

Deprecation of @JvmDefault and old Xjvm-default modes

Improvements to handling nullability annotations

Stable
JVM
IR
backend
The IR-based backend for the Kotlin/JVM compiler is now Stable and enabled by default.

Starting from Kotlin 1.4.0, early versions of the IR-based backend were available for preview, and it has now become the
default for language version 1.5. The old backend is still used by default for earlier language versions.

You can find more details about the benefits of the IR backend and its future development in this blog post.

If you need to use the old backend in Kotlin 1.5.0, you can add the following lines to the project’s configuration file:

In Gradle:

Kotlin

tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions.useOldBackend = true
}

Groovy

tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) {
kotlinOptions.useOldBackend = true
}

In Maven:

<configuration>
<args>
<arg>-Xuse-old-backend</arg>
</args>
</configuration>

107
New
default
JVM
target:
1.8
The default target version for Kotlin/JVM compilations is now 1.8. The 1.6 target is deprecated.

If you need a build for JVM 1.6, you can still switch to this target. Learn how:

in Gradle

in Maven

in the command-line compiler

SAM
adapters
via
invokedynamic
Kotlin 1.5.0 now uses dynamic invocations (invokedynamic) for compiling SAM (Single Abstract Method) conversions:

Over any expression if the SAM type is a Java interface

Over lambda if the SAM type is a Kotlin functional interface

The new implementation uses LambdaMetafactory.metafactory() and auxiliary wrapper classes are no longer generated
during compilation. This decreases the size of the application’s JAR, which improves the JVM startup performance.

To roll back to the old implementation scheme based on anonymous class generation, add the compiler option -Xsam-
conversions=class.

Learn how to add compiler options in Gradle, Maven, and the command-line compiler.

Lambdas
via
invokedynamic

Compiling plain Kotlin lambdas into invokedynamic is Experimental. It may be dropped or changed at any time.
Opt-in is required (see details below), and you should use it only for evaluation purposes. We would appreciate
hearing your feedback on it in YouTrack.

Kotlin 1.5.0 is introducing experimental support for compiling plain Kotlin lambdas (which are not converted to an
instance of a functional interface) into dynamic invocations (invokedynamic). The implementation produces lighter
binaries by using LambdaMetafactory.metafactory(), which effectively generates the necessary classes at runtime.
Currently, it has three limitations compared to ordinary lambda compilation:

A lambda compiled into invokedynamic is not serializable.

Calling toString() on such a lambda produces a less readable string representation.

Experimental reflect API does not support lambdas created with LambdaMetafactory.

To try this feature, add the -Xlambdas=indy compiler option. We’d be grateful if you could share your feedback on it
using this YouTrack ticket.

Learn how to add compiler options in Gradle, Maven, and command-line compiler.

108
Deprecation
of
@JvmDefault
and
old
Xjvm-default
modes
Prior to Kotlin 1.4.0, there was the @JvmDefault annotation along with -Xjvm-default=enable and -Xjvm-
default=compatibility modes. They served to create the JVM default method for any particular non-abstract member in the
Kotlin interface.

In Kotlin 1.4.0, we introduced the new Xjvm-default modes, which switch on default method generation for the whole
project.

In Kotlin 1.5.0, we are deprecating @JvmDefault and the old Xjvm-default modes: -Xjvm-default=enable and -Xjvm-
default=compatibility.

Learn more about default methods in the Java interop.

Improvements
to
handling
nullability
annotations
Kotlin supports handling type nullability information from Java with nullability annotations. Kotlin 1.5.0 introduces a
number of improvements for the feature:

It reads nullability annotations on type arguments in compiled Java libraries that are used as dependencies.

It supports nullability annotations with the TYPE_USE target for:


Arrays

Varargs

Fields

Type parameters and their bounds

Type arguments of base classes and interfaces

If a nullability annotation has multiple targets applicable to a type, and one of these targets is TYPE_USE, then
TYPE_USE is preferred. For example, the method signature @Nullable String[] f() becomes fun f(): Array<String?>! if
@Nullable supports both TYPE_USE and METHOD as targets.

For these newly supported cases, using the wrong type nullability when calling Java from Kotlin produces warnings. Use
the -Xtype-enhancement-improvements-strict-mode compiler option to enable strict mode for these cases (with error
reporting).

Learn more about null-safety and platform types.

Kotlin/Native
Kotlin/Native is now more performant and stable. The notable changes are:

Performance improvements

109
Deactivation of the memory leak checker

Performance
improvements
In 1.5.0, Kotlin/Native is receiving a set of performance improvements that speed up both compilation and execution.

Compiler caches are now supported in debug mode for linuxX64 (only on Linux hosts) and iosArm64 targets. With
compiler caches enabled, most debug compilations complete much faster, except for the first one. Measurements
showed about a 200% speed increase on our test projects.

To use compiler caches for new targets, opt in by adding the following lines to the project’s gradle.properties:

For linuxX64: kotlin.native.cacheKind.linuxX64=static

For iosArm64: kotlin.native.cacheKind.iosArm64=static

If you encounter any issues after enabling the compiler caches, please report them to our issue tracker YouTrack.

Other improvements speed up the execution of Kotlin/Native code:

Trivial property accessors are inlined.

trimIndent() on string literals is evaluated during the compilation.

Deactivation
of
the
memory
leak
checker
The built-in Kotlin/Native memory leak checker has been disabled by default.

It was initially designed for internal use, and it is able to find leaks only in a limited number of cases, not all of them.
Moreover, it later turned out to have issues that can cause application crashes. So we’ve decided to turn off the
memory leak checker.

The memory leak checker can still be useful for certain cases, for example, unit testing. For these cases, you can enable it
by adding the following line of code:

Platform.isMemoryLeakCheckerActive = true

Note that enabling the checker for the application runtime is not recommended.

Kotlin/JS
Kotlin/JS is receiving evolutionary changes in 1.5.0. We’re continuing our work on moving the JS IR compiler backend
towards stable and shipping other updates:

Upgrade of webpack to version 5

Frameworks and libraries for the IR compiler

110
Upgrade
to
webpack
5
The Kotlin/JS Gradle plugin now uses webpack 5 for browser targets instead of webpack 4. This is a major webpack
upgrade that brings incompatible changes. If you’re using a custom webpack configuration, be sure to check the
webpack 5 release notes.

Learn more about bundling Kotlin/JS projects with webpack.

Frameworks
and
libraries
for
the
IR
compiler

The Kotlin/JS IR compiler is in Alpha. It may change incompatibly and require manual migration in the future.
We would appreciate your feedback on it in YouTrack.

Along with working on the IR-based backend for Kotlin/JS compiler, we encourage and help library authors to build their
projects in both mode. This means they are able to produce artifacts for both Kotlin/JS compilers, therefore growing the
ecosystem for the new compiler.

Many well-known frameworks and libraries are already available for the IR backend: KVision, fritz2, doodle, and others. If
you’re using them in your project, you can already build it with the IR backend and see the benefits it brings.

If you’re writing your own library, compile it in the 'both' mode so that your clients can also use it with the new
compiler.

Kotlin
Multiplatform
In Kotlin 1.5.0, choosing a testing dependency for each platform has been simplified and it is now done automatically by
the Gradle plugin.

A new API for getting a char category is now available in multiplatform projects.

Standard
library
The standard library has received a range of changes and improvements, from stabilizing experimental parts to adding
new features:

Stable unsigned integer types

Stable locale-agnostic API for uppercase/lowercase text

Stable Char-to-integer conversion API

Stable Path API

Floored division and the mod operator

111
Duration API changes

New API for getting a char category now available in multiplatform code

New collections function firstNotNullOf()

Strict version of String?.toBoolean()

You can learn more about the standard library changes in this blog post.

Gif

Watch video online.

Stable
unsigned
integer
types
The UInt, ULong, UByte, UShort unsigned integer types are now Stable. The same goes for operations on these types,
ranges, and progressions of them. Unsigned arrays and operations on them remain in Beta.

Learn more about unsigned integer types.

Stable
locale-agnostic
API
for
upper/lowercasing
text
This release brings a new locale-agnostic API for uppercase/lowercase text conversion. It provides an alternative to the
toLowerCase(), toUpperCase(), capitalize(), and decapitalize() API functions, which are locale-sensitive. The new API helps
you avoid errors due to different locale settings.

Kotlin 1.5.0 provides the following fully Stable alternatives:

For String functions:

Earlier
versions 1.5.0
alternative

112
Earlier
versions 1.5.0
alternative

String.toUpperCase() String.uppercase()

String.toLowerCase() String.lowercase()

String.capitalize() String.replaceFirstChar { it.uppercase()


}

String.decapitalize() String.replaceFirstChar { it.lowercase() }

For Char functions:

Earlier
versions 1.5.0
alternative

Char.toUpperCase() Char.uppercaseChar():
Char
Char.uppercase(): String

Char.toLowerCase() Char.lowercaseChar(): Char


Char.lowercase(): String

Char.toTitleCase() Char.titlecaseChar(): Char


Char.titlecase(): String

For Kotlin/JVM, there are also overloaded uppercase(), lowercase(), and titlecase() functions with an explicit
Locale parameter.

The old API functions are marked as deprecated and will be removed in a future release.

See the full list of changes to the text processing functions in KEEP.

Stable
char-to-integer
conversion
API
Starting from Kotlin 1.5.0, new char-to-code and char-to-digit conversion functions are Stable. These functions replace
the current API functions, which were often confused with the similar string-to-Int conversion.

The new API removes this naming confusion, making the code behavior more transparent and unambiguous.

This release introduces Char conversions that are divided into the following sets of clearly named functions:

Functions to get the integer code of Char and to construct Char from the given code:

fun Char(code: Int): Char


fun Char(code: UShort): Char

113
val Char.code: Int

Functions to convert Char to the numeric value of the digit it represents:

fun Char.digitToInt(radix: Int): Int


fun Char.digitToIntOrNull(radix: Int): Int?

An extension function for Int to convert the non-negative single digit it represents to the corresponding Char
representation:

fun Int.digitToChar(radix: Int): Char

The old conversion APIs, including Number.toChar() with its implementations (all except Int.toChar()) and Char extensions
for conversion to a numeric type, like Char.toInt(), are now deprecated.

Learn more about the char-to-integer conversion API in KEEP.

Stable
Path
API
The experimental Path API with extensions for java.nio.file.Path is now Stable.

// construct path with the div (/) operator


val baseDir = Path("/base")
val subDir = baseDir / "subdirectory"

// list files in a directory


val kotlinFiles: List<Path> = Path("/home/user").listDirectoryEntries("*.kt")

Learn more about the Path API.

Floored
division
and
the
mod
operator
New operations for modular arithmetics have been added to the standard library:

floorDiv() returns the result of floored division. It is available for integer types.

mod() returns the remainder of floored division (modulus). It is available for all numeric types.

These operations look quite similar to the existing division of integers and rem() function (or the % operator), but they work
differently on negative numbers:

a.floorDiv(b) differs from a regular / in that floorDiv rounds the result down (towards the lesser integer), whereas /
truncates the result to the integer closer to 0.

a.mod(b) is the difference between a and a.floorDiv(b) * b. It’s either zero or has the same sign as b, while a % b
can have a different one.

fun main() {

114
//sampleStart
println("Floored division -5/3: ${(-5).floorDiv(3)}")
println( "Modulus: ${(-5).mod(3)}")

println("Truncated division -5/3: ${-5 / 3}")
println( "Remainder: ${-5 % 3}")
//sampleEnd
}

Duration
API
changes

The Duration API is Experimental. It may be dropped or changed at any time. Use it only for evaluation
purposes. We would appreciate hearing your feedback on it in YouTrack.

There is an experimental Duration class for representing duration amounts in different time units. In 1.5.0, the Duration
API has received the following changes:

Internal value representation now uses Long instead of Double to provide better precision.

There is a new API for conversion to a particular time unit in Long. It comes to replace the old API, which operates with
Double values and is now deprecated. For example, Duration.inWholeMinutes returns the value of the duration
expressed as Long and replaces Duration.inMinutes.

There are new companion functions for constructing a Duration from a number. For example, Duration.seconds(Int)
creates a Duration object representing an integer number of seconds. Old extension properties like Int.seconds are
now deprecated.

import kotlin.time.Duration
import kotlin.time.ExperimentalTime

@ExperimentalTime
fun main() {
//sampleStart
val duration = Duration.milliseconds(120000)
println("There are ${duration.inWholeSeconds} seconds in ${duration.inWholeMinutes} minutes")
//sampleEnd
}

New
API
for
getting
a
char
category
now
available
in
multiplatform
code
Kotlin 1.5.0 introduces the new API for getting a character’s category according to Unicode in multiplatform projects.
Several functions are now available in all the platforms and in the common code.

Functions for checking whether a char is a letter or a digit:

Char.isDigit()

Char.isLetter()

115
Char.isLetterOrDigit()

fun main() {
//sampleStart
val chars = listOf('a', '1', '+')
val (letterOrDigitList, notLetterOrDigitList) = chars.partition { it.isLetterOrDigit() }
println(letterOrDigitList) // [a, 1]
println(notLetterOrDigitList) // [+]
//sampleEnd
}

Functions for checking the case of a char:

Char.isLowerCase()

Char.isUpperCase()

Char.isTitleCase()

fun main() {
//sampleStart
val chars = listOf('Dž', 'Lj', 'Nj', 'Dz', '1', 'A', 'a', '+')
val (titleCases, notTitleCases) = chars.partition { it.isTitleCase() }
println(titleCases) // [Dž, Lj, Nj, Dz]
println(notTitleCases) // [1, A, a, +]
//sampleEnd
}

Some other functions:

Char.isDefined()

Char.isISOControl()

The property Char.category and its return type enum class CharCategory, which indicates a char's general category
according to Unicode, are now also available in multiplatform projects.

Learn more about characters.

New
collections
function
firstNotNullOf()
The new firstNotNullOf() and firstNotNullOfOrNull() functions combine mapNotNull() with first() or firstOrNull(). They map
the original collection with the custom selector function and return the first non-null value. If there is no such value,
firstNotNullOf() throws an exception, and firstNotNullOfOrNull() returns null.

fun main() {
//sampleStart
val data = listOf("Kotlin", "1.5")
println(data.firstNotNullOf(String::toDoubleOrNull))
println(data.firstNotNullOfOrNull(String::toIntOrNull))
//sampleEnd
}

116
Strict
version
of
String?.toBoolean()
Two new functions introduce case-sensitive strict versions of the existing String?.toBoolean():

String.toBooleanStrict() throws an exception for all inputs except the literals true and false.

String.toBooleanStrictOrNull() returns null for all inputs except the literals true and false.

fun main() {
//sampleStart
println("true".toBooleanStrict())
println("1".toBooleanStrictOrNull())
// println("1".toBooleanStrict()) // Exception
//sampleEnd
}

kotlin-test
library
The kotlin-test library introduces some new features:

Simplified test dependencies usage in multiplatform projects

Automatic selection of a testing framework for Kotlin/JVM source sets

Assertion function updates

Simplified
test
dependencies
usage
in
multiplatform
projects
Now you can use the kotlin-test dependency to add dependencies for testing in the commonTest source set, and the
Gradle plugin will infer the corresponding platform dependencies for each test source set:

kotlin-test-junit for JVM source sets, see automatic choice of a testing framework for Kotlin/JVM source sets

kotlin-test-js for Kotlin/JS source sets

kotlin-test-common and kotlin-test-annotations-common for common source sets

No extra artifact for Kotlin/Native source sets

Additionally, you can use the kotlin-test dependency in any shared or platform-specific source set.

An existing kotlin-test setup with explicit dependencies will continue to work both in Gradle and in Maven.

Learn more about setting dependencies on test libraries.

Automatic
selection
of
a
testing
framework
for
Kotlin/JVM
source
sets
The Gradle plugin now chooses and adds a dependency on a testing framework automatically. All you need to do is add

117
the dependency kotlin-test in the common source set.

Gradle uses JUnit 4 by default. Therefore, the kotlin("test") dependency resolves to the variant for JUnit 4, namely kotlin-
test-junit:

Kotlin

kotlin {
sourceSets {
val commonTest by getting {
dependencies {
implementation(kotlin("test")) // This brings the dependency
// on JUnit 4 transitively
}
}
}
}

Groovy

kotlin {
sourceSets {
commonTest {
dependencies {
implementation kotlin("test") // This brings the dependency
// on JUnit 4 transitively
}
}
}
}

You can choose JUnit 5 or TestNG by calling useJUnitPlatform() or useTestNG() in the test task:

tasks {
test {
// enable TestNG support
useTestNG()
// or
// enable JUnit Platform (a.k.a. JUnit 5) support
useJUnitPlatform()
}
}

You can disable automatic testing framework selection by adding the line kotlin.test.infer.jvm.variant=false to the
project’s gradle.properties.

Learn more about setting dependencies on test libraries.

Assertion
function
updates
This release brings new assertion functions and improves the existing ones.

118
The kotlin-test library now has the following features:

Checking the type of a value

You can use the new assertIs<T> and assertIsNot<T> to check the type of a value:

@Test
fun testFunction() {
val s: Any = "test"
assertIs<String>(s) // throws AssertionError mentioning the actual type of s if the
assertion fails
// can now print s.length because of contract in assertIs
println("${s.length}")
}

Because of type erasure, this assert function only checks whether the value is of the List type in the following example
and doesn't check whether it's a list of the particular String element type: assertIs<List<String>>(value).

Comparing the container content for arrays, sequences, and arbitrary iterables

There is a new set of overloaded assertContentEquals() functions for comparing content for different collections that
don’t implement structural equality:

@Test
fun test() {
val expectedArray = arrayOf(1, 2, 3)
val actualArray = Array(3) { it + 1 }
assertContentEquals(expectedArray, actualArray)
}

New overloads to assertEquals() and assertNotEquals() for Double and Float numbers

There are new overloads for the assertEquals() function that make it possible to compare two Double or Float numbers
with absolute precision. The precision value is specified as the third parameter of the function:

@Test
fun test() {
val x = sin(PI)

// precision parameter
val tolerance = 0.000001

assertEquals(0.0, x, tolerance)
}

New functions for checking the content of collections and elements

You can now check whether the collection or element contains something with the assertContains() function. You can
use it with Kotlin collections and elements that have the contains() operator, such as IntRange, String, and others:

@Test

119
fun test() {
val sampleList = listOf<String>("sample", "sample2")
val sampleString = "sample"
assertContains(sampleList, sampleString) // element in collection
assertContains(sampleString, "amp") // substring in string
}

assertTrue(), assertFalse(), expect() functions are now inline

From now on, you can use these as inline functions, so it's possible to call suspend functions inside a lambda
expression:

@Test
fun test() = runBlocking<Unit> {
val deferred = async { "Kotlin is nice" }
assertTrue("Kotlin substring should be present") {
deferred.await() .contains("Kotlin")
}
}

kotlinx
libraries
Along with Kotlin 1.5.0, we are releasing new versions of the kotlinx libraries:

kotlinx.coroutines 1.5.0-RC

kotlinx.serialization 1.2.1

kotlinx-datetime 0.2.0

Coroutines
1.5.0-RC
kotlinx.coroutines 1.5.0-RC is here with:

New channels API

Stable reactive integrations

And more

Starting with Kotlin 1.5.0, experimental coroutines are disabled and the -Xcoroutines=experimental flag is no longer
supported.

Learn more in the changelog and the kotlinx.coroutines 1.5.0 release blog post.

120
Gif

Watch video online.

Serialization
1.2.1
kotlinx.serialization 1.2.1 is here with:

Improvements to JSON serialization performance

Support for multiple names in JSON serialization

Experimental .proto schema generation from @Serializable classes

And more

Learn more in the changelog and the kotlinx.serialization 1.2.1 release blog post.

121
Gif

Watch video online.

dateTime
0.2.0
kotlinx-datetime 0.2.0 is here with:

@Serializable Datetime objects

Normalized API of DateTimePeriod and DatePeriod

And more

Learn more in the changelog and the kotlinx-datetime 0.2.0 release blog post.

Migrating
to
Kotlin
1.5.0
IntelliJ IDEA and Android Studio will suggest updating the Kotlin plugin to 1.5.0 once it is available.

To migrate existing projects to Kotlin 1.5.0, just change the Kotlin version to 1.5.0 and re-import your Gradle or Maven
project. Learn how to update to Kotlin 1.5.0.

To start a new project with Kotlin 1.5.0, update the Kotlin plugin and run the Project Wizard from File | New | Project.

The new command-line compiler is available for downloading on the GitHub release page.

Kotlin 1.5.0 is a feature release and therefore can bring incompatible changes to the language. Find the detailed list of
such changes in the Compatibility Guide for Kotlin 1.5.

122
What's
new
in
Kotlin
1.4.30
Release date: 3 February 2021

Kotlin 1.4.30 offers preview versions of new language features, promotes the new IR backend of the Kotlin/JVM compiler
to Beta, and ships various performance and functional improvements.

You can also learn about new features in this blog post.

Language
features
Kotlin 1.5.0 is going to deliver new language features – JVM records support, sealed interfaces, and Stable inline
classes. In Kotlin 1.4.30, you can try these features and improvements in preview mode. We’d be very grateful if you
share your feedback with us in the corresponding YouTrack tickets, as that will allow us to address it before the release
of 1.5.0.

JVM records support

Sealed interfaces and sealed class improvements

Improved inline classes

To enable these language features and improvements in preview mode, you need to opt in by adding specific compiler
options. See the sections below for details.

Learn more about the new features preview in this blog post.

JVM
records
support

The JVM records feature is Experimental. It may be dropped or changed at any time. Opt-in is required (see the
details below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in
YouTrack.

The JDK 16 release includes plans to stabilize a new Java class type called record. To provide all the benefits of Kotlin
and maintain its interoperability with Java, Kotlin is introducing experimental record class support.

You can use record classes that are declared in Java just like classes with properties in Kotlin. No additional steps are
required.

Starting with 1.4.30, you can declare the record class in Kotlin using the @JvmRecord annotation for a data class:

@JvmRecord
data class User(val name: String, val age: Int)

123
To try the preview version of JVM records, add the compiler options -Xjvm-enable-preview and -language-version 1.5.

We’re continuing to work on JVM records support and we’d be very grateful if you would share your feedback
with us using this YouTrack ticket.

Learn more about implementation, restrictions, and the syntax in KEEP.

Sealed
interfaces

Sealed interfaces are Experimental. They may be dropped or changed at any time. Opt-in is required (see the
details below), and you should use them only for evaluation purposes. We would appreciate your feedback on
them in YouTrack.

In Kotlin 1.4.30, we’re shipping the prototype of sealed interfaces. They complement sealed classes and make it
possible to build more flexible restricted class hierarchies.

They can serve as “internalâ€​ interfaces that cannot be implemented outside the same module. You can rely on that
fact, for example, to write exhaustive when expressions.

sealed interface Polygon

class Rectangle(): Polygon


class Triangle(): Polygon

// when() is exhaustive: no other polygon implementations can appear


// after the module is compiled
fun draw(polygon: Polygon) = when (polygon) {
is Rectangle -> // ...
is Triangle -> // ...
}

Another use-case: with sealed interfaces, you can inherit a class from two or more sealed superclasses.

sealed interface Fillable {


fun fill()
}
sealed interface Polygon {
val vertices: List<Point>
}

class Rectangle(override val vertices: List<Point>): Fillable, Polygon {


override fun fill() { /*...*/ }
}

To try the preview version of sealed interfaces, add the compiler option -language-version 1.5. Once you switch to this
version, you’ll be able to use the sealed modifier on interfaces. We’d be very grateful if you would share your
feedback with us using this YouTrack ticket.

124
Learn more about sealed interfaces.

Package-wide
sealed
class
hierarchies

Package-wide hierarchies of sealed classes are Experimental. They may be dropped or changed at any time.
Opt-in is required (see the details below), and you should use them only for evaluation purposes. We would
appreciate your feedback on them in YouTrack.

Sealed classes can now form more flexible hierarchies. They can have subclasses in all files of the same compilation unit
and the same package. Previously, all subclasses had to appear in the same file.

Direct subclasses may be top-level or nested inside any number of other named classes, named interfaces, or named
objects. The subclasses of a sealed class must have a name that is properly qualified – they cannot be local nor
anonymous objects.

To try package-wide hierarchies of sealed classes, add the compiler option -language-version 1.5. We’d be very
grateful if you would share your feedback with us using this YouTrack ticket.

Learn more about package-wide hierarchies of sealed classes.

Improved
inline
classes

Inline value classes are in Beta. They are almost stable, but migration steps may be required in the future. We'll
do our best to minimize any changes you have to make. We would appreciate your feedback on the inline
classes feature in YouTrack.

Kotlin 1.4.30 promotes inline classes to Beta and brings the following features and improvements to them:

Since inline classes are value-based, you can define them using the value modifier. The inline and value modifiers are
now equivalent to each other. In future Kotlin versions, we’re planning to deprecate the inline modifier.

From now on, Kotlin requires the @JvmInline annotation before a class declaration for the JVM backend:

inline class Name(private val s: String)

value class Name(private val s: String)

// For JVM backends


@JvmInline
value class Name(private val s: String)

Inline classes can have init blocks. You can add code to be executed right after the class is instantiated:

125
@JvmInline
value class Negative(val x: Int) {
init {
require(x < 0) { }
}
}

Calling functions with inline classes from Java code: before Kotlin 1.4.30, you couldn't call functions that accept inline
classes from Java because of mangling. From now on, you can disable mangling manually. To call such functions from
Java code, you should add the @JvmName annotation before the function declaration:

inline class UInt(val x: Int)

fun compute(x: Int) { }

@JvmName("computeUInt")
fun compute(x: UInt) { }

In this release, we’ve changed the mangling scheme for functions to fix the incorrect behavior. These changes led
to ABI changes.

Starting with 1.4.30, the Kotlin compiler uses a new mangling scheme by default. Use the -Xuse-14-inline-classes-
mangling-scheme compiler flag to force the compiler to use the old 1.4.0 mangling scheme and preserve binary
compatibility.

Kotlin 1.4.30 promotes inline classes to Beta and we are planning to make them Stable in future releases. We’d be
very grateful if you would share your feedback with us using this YouTrack ticket.

To try the preview version of inline classes, add the compiler option -Xinline-classes or -language-version 1.5.

Learn more about the mangling algorithm in KEEP.

Learn more about inline classes.

Kotlin/JVM

JVM
IR
compiler
backend
reaches
Beta
The IR-based compiler backend for Kotlin/JVM, which was presented in 1.4.0 in Alpha, has reached Beta. This is the last
pre-stable level before the IR backend becomes the default for the Kotlin/JVM compiler.

We’re now dropping the restriction on consuming binaries produced by the IR compiler. Previously, you could use
code compiled by the new JVM IR backend only if you had enabled the new backend. Starting from 1.4.30, there is no
such limitation, so you can use the new backend to build components for third-party use, such as libraries. Try the Beta
version of the new backend and share your feedback in our issue tracker.

To enable the new JVM IR backend, add the following lines to the project’s configuration file:

In Gradle:

126
Kotlin

tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile::class) {
kotlinOptions.useIR = true
}

Groovy

tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) {
kotlinOptions.useIR = true
}

In Maven:

<configuration>
<args>
<arg>-Xuse-ir</arg>
</args>
</configuration>

Learn more about the changes that the JVM IR backend brings in this blog post.

Kotlin/Native

Performance
improvements
Kotlin/Native has received a variety of performance improvements in 1.4.30, which has resulted in faster compilation
times. For example, the time required to rebuild the framework in the KMM Networking and Data Storage sample has
decreased from 9.5 seconds (in 1.4.10) to 4.5 seconds (in 1.4.30).

Apple
watchOS
64-bit
simulator
target
The x86 simulator target has been deprecated for watchOS since version 7.0. To keep up with the latest watchOS
versions, Kotlin/Native has the new target watchosX64 for running the simulator on 64-bit architecture.

Support
for
Xcode
12.2
libraries
We have added support for the new libraries delivered with Xcode 12.2. You can now use them from Kotlin code.

Kotlin/JS

127
Lazy
initialization
of
top-level
properties

Lazy initialization of top-level properties is Experimental. It may be dropped or changed at any time. Opt-in is
required (see the details below), and you should use it only for evaluation purposes. We would appreciate your
feedback on it in YouTrack.

The IR backend for Kotlin/JS is receiving a prototype implementation of lazy initialization for top-level properties. This
reduces the need to initialize all top-level properties when the application starts, and it should significantly improve
application start-up times.

We’ll keep working on the lazy initialization, and we ask you to try the current prototype and share your thoughts and
results in this YouTrack ticket or the #javascript channel in the official Kotlin Slack (get an invite here).

To use the lazy initialization, add the -Xir-property-lazy-initialization compiler option when compiling the code with the JS
IR compiler.

Gradle
project
improvements

Support
the
Gradle
configuration
cache
Starting with 1.4.30, the Kotlin Gradle plugin supports the configuration cache feature. It speeds up the build process:
once you run the command, Gradle executes the configuration phase and calculates the task graph. Gradle caches the
result and reuses it for subsequent builds.

To start using this feature, you can use the Gradle command or set up the IntelliJ based IDE.

Standard
library

Locale-agnostic
API
for
upper/lowercasing
text

The locale-agnostic API feature is Experimental. It may be dropped or changed at any time. Use it only for
evaluation purposes. We would appreciate your feedback on it in YouTrack.

This release introduces the experimental locale-agnostic API for changing the case of strings and characters. The current
toLowerCase(), toUpperCase(), capitalize(), decapitalize() API functions are locale-sensitive. This means that different
platform locale settings can affect code behavior. For example, in the Turkish locale, when the string “kotlinâ€​ is
converted using toUpperCase, the result is "KOTLİN", not "KOTLIN".

// current API
println("Needs to be capitalized".toUpperCase()) // NEEDS TO BE CAPITALIZED

128
// new API
println("Needs to be capitalized".uppercase()) // NEEDS TO BE CAPITALIZED

Kotlin 1.4.30 provides the following alternatives:

For String functions:

Earlier
versions 1.4.30
alternative

String.toUpperCase() String.uppercase()

String.toLowerCase() String.lowercase()

String.capitalize() String.replaceFirstChar { it.uppercase()


}

String.decapitalize() String.replaceFirstChar { it.lowercase() }

For Char functions:

Earlier
versions 1.4.30
alternative

Char.toUpperCase() Char.uppercaseChar():
Char
Char.uppercase(): String

Char.toLowerCase() Char.lowercaseChar(): Char


Char.lowercase(): String

Char.toTitleCase() Char.titlecaseChar(): Char


Char.titlecase(): String

For Kotlin/JVM, there are also overloaded uppercase(), lowercase(), and titlecase() functions with an explicit
Locale parameter.

See the full list of changes to the text processing functions in KEEP.

Clear
Char-to-code
and
Char-to-digit
conversions

The unambiguous API for the Char conversion feature is Experimental. It may be dropped or changed at any
time. Use it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

129
The current Char to numbers conversion functions, which return UTF-16 codes expressed in different numeric types, are
often confused with the similar String-to-Int conversion, which returns the numeric value of a string:

"4".toInt() // returns 4
'4'.toInt() // returns 52
// and there was no common function that would return the numeric value 4 for Char '4'

To avoid this confusion we've decided to separate Char conversions into two following sets of clearly named functions:

Functions to get the integer code of Char and to construct Char from the given code:

fun Char(code: Int): Char


fun Char(code: UShort): Char
val Char.code: Int

Functions to convert Char to the numeric value of the digit it represents:

fun Char.digitToInt(radix: Int): Int


fun Char.digitToIntOrNull(radix: Int): Int?

An extension function for Int to convert the non-negative single digit it represents to the corresponding Char
representation:

fun Int.digitToChar(radix: Int): Char

See more details in KEEP.

Serialization
updates
Along with Kotlin 1.4.30, we are releasing kotlinx.serialization 1.1.0-RC, which includes some new features:

Inline classes serialization support

Unsigned primitive type serialization support

Inline
classes
serialization
support
Starting with Kotlin 1.4.30, you can make inline classes serializable:

@Serializable
inline class Color(val rgb: Int)

The feature requires the new 1.4.30 IR compiler.

130
The serialization framework does not box serializable inline classes when they are used in other serializable classes.

Learn more in the kotlinx.serialization docs.

Unsigned
primitive
type
serialization
support
Starting from 1.4.30, you can use standard JSON serializers of kotlinx.serialization for unsigned primitive types: UInt,
ULong, UByte, and UShort:

@Serializable
class Counter(val counted: UByte, val description: String)
fun main() {
val counted = 239.toUByte()
println(Json.encodeToString(Counter(counted, "tries")))
}

Learn more in the kotlinx.serialization docs.

What's
new
in
Kotlin
1.3
Release date: 29 October 2018

Coroutines
release
After some long and extensive battle testing, coroutines are now released! It means that from Kotlin 1.3 the language
support and the API are fully stable. Check out the new coroutines overview page.

Kotlin 1.3 introduces callable references on suspend-functions and support of coroutines in the reflection API.

Kotlin/Native
Kotlin 1.3 continues to improve and polish the Native target. See the Kotlin/Native overview for details.

Multiplatform
projects
In 1.3, we've completely reworked the model of multiplatform projects in order to improve expressiveness and flexibility,
and to make sharing common code easier. Also, Kotlin/Native is now supported as one of the targets!

The key differences to the old model are:

In the old model, common and platform-specific code needed to be placed in separate modules, linked by expectedBy
dependencies. Now, common and platform-specific code is placed in different source roots of the same module,
making projects easier to configure.

131
There is now a large number of preset platform configurations for different supported platforms.

The dependencies configuration has been changed; dependencies are now specified separately for each source root.

Source sets can now be shared between an arbitrary subset of platforms (for example, in a module that targets JS,
Android and iOS, you can have a source set that is shared only between Android and iOS).

Publishing multiplatform libraries is now supported.

For more information, please refer to the multiplatform programming documentation.

Contracts
The Kotlin compiler does extensive static analysis to provide warnings and reduce boilerplate. One of the most notable
features is smartcasts — with the ability to perform a cast automatically based on the performed type checks:

fun foo(s: String?) {


if (s != null) s.length // Compiler automatically casts 's' to 'String'
}

However, as soon as these checks are extracted in a separate function, all the smartcasts immediately disappear:

fun String?.isNotNull(): Boolean = this != null

fun foo(s: String?) {


if (s.isNotNull()) s.length // No smartcast :(
}

To improve the behavior in such cases, Kotlin 1.3 introduces experimental mechanism called contracts.

Contracts allow a function to explicitly describe its behavior in a way which is understood by the compiler. Currently, two
wide classes of cases are supported:

Improving smartcasts analysis by declaring the relation between a function's call outcome and the passed arguments
values:

fun require(condition: Boolean) {


// This is a syntax form which tells the compiler:
// "if this function returns successfully, then the passed 'condition' is true"
contract { returns() implies condition }
if (!condition) throw IllegalArgumentException(...)
}

fun foo(s: String?) {


require(s is String)
// s is smartcast to 'String' here, because otherwise
// 'require' would have thrown an exception
}

Improving the variable initialization analysis in the presence of high-order functions:

132
fun synchronize(lock: Any?, block: () -> Unit) {
// It tells the compiler:
// "This function will invoke 'block' here and now, and exactly one time"
contract { callsInPlace(block, EXACTLY_ONCE) }
}

fun foo() {
val x: Int
synchronize(lock) {
x = 42 // Compiler knows that lambda passed to 'synchronize' is called
// exactly once, so no reassignment is reported
}
println(x) // Compiler knows that lambda will be definitely called, performing
// initialization, so 'x' is considered to be initialized here
}

Contracts
in
stdlib
stdlib already makes use of contracts, which leads to improvements in the analyses described above. This part of
contracts is stable, meaning that you can benefit from the improved analysis right now without any additional opt-ins:

//sampleStart
fun bar(x: String?) {
if (!x.isNullOrEmpty()) {
println("length of '$x' is ${x.length}") // Yay, smartcast to not-null!
}
}
//sampleEnd
fun main() {
bar(null)
bar("42")
}

Custom
contracts
It is possible to declare contracts for your own functions, but this feature is experimental, as the current syntax is in a
state of early prototype and will most probably be changed. Also please note that currently the Kotlin compiler does not
verify contracts, so it's the responsibility of the programmer to write correct and sound contracts.

Custom contracts are introduced by a call to contract stdlib function, which provides DSL scope:

fun String?.isNullOrEmpty(): Boolean {


contract {
returns(false) implies (this@isNullOrEmpty != null)
}
return this == null || isEmpty()
}

See the details on the syntax as well as the compatibility notice in the KEEP.

133
Capturing
when
subject
in
a
variable
In Kotlin 1.3, it is now possible to capture the when subject into a variable:

fun Request.getBody() =
when (val response = executeRequest()) {
is Success -> response.body
is HttpError -> throw HttpException(response.status)
}

While it was already possible to extract this variable just before when, val in when has its scope properly restricted to the
body of when, and so preventing namespace pollution. See the full documentation on when here.

@JvmStatic
and
@JvmField
in
companions
of
interfaces
With Kotlin 1.3, it is possible to mark members of a companion object of interfaces with annotations @JvmStatic and
@JvmField. In the classfile, such members will be lifted to the corresponding interface and marked as static.

For example, the following Kotlin code:

interface Foo {
companion object {
@JvmField
val answer: Int = 42

@JvmStatic
fun sayHello() {
println("Hello, world!")
}
}
}

It is equivalent to this Java code:

interface Foo {
public static int answer = 42;
public static void sayHello() {
// ...
}
}

Nested
declarations
in
annotation
classes
In Kotlin 1.3, it is possible for annotations to have nested classes, interfaces, objects, and companions:

annotation class Foo {


enum class Direction { UP, DOWN, LEFT, RIGHT }

134
annotation class Bar

companion object {
fun foo(): Int = 42
val bar: Int = 42
}
}

Parameterless
main
By convention, the entry point of a Kotlin program is a function with a signature like main(args: Array<String>), where args
represent the command-line arguments passed to the program. However, not every application supports command-line
arguments, so this parameter often ends up not being used.

Kotlin 1.3 introduced a simpler form of main which takes no parameters. Now “Hello, Worldâ€​ in Kotlin is 19
characters shorter!

fun main() {
println("Hello, world!")
}

Functions
with
big
arity
In Kotlin, functional types are represented as generic classes taking a different number of parameters: Function0<R>,
Function1<P0, R>, Function2<P0, P1, R>, ... This approach has a problem in that this list is finite, and it currently ends
with Function22.

Kotlin 1.3 relaxes this limitation and adds support for functions with bigger arity:

fun trueEnterpriseComesToKotlin(block: (Any, Any, ... /* 42 more */, Any) -> Any) {
block(Any(), Any(), ..., Any())
}

Progressive
mode
Kotlin cares a lot about stability and backward compatibility of code: Kotlin compatibility policy says that breaking
changes (e.g., a change which makes the code that used to compile fine, not compile anymore) can be introduced only in
the major releases (1.2, 1.3, etc.).

We believe that a lot of users could use a much faster cycle where critical compiler bug fixes arrive immediately, making
the code more safe and correct. So, Kotlin 1.3 introduces the progressive compiler mode, which can be enabled by
passing the argument -progressive to the compiler.

In the progressive mode, some fixes in language semantics can arrive immediately. All these fixes have two important
properties:

135
They preserve backward compatibility of source code with older compilers, meaning that all the code which is
compilable by the progressive compiler will be compiled fine by non-progressive one.

They only make code safer in some sense — e.g., some unsound smartcast can be forbidden, behavior of the
generated code may be changed to be more predictable/stable, and so on.

Enabling the progressive mode can require you to rewrite some of your code, but it shouldn't be too much — all the fixes
enabled under progressive are carefully handpicked, reviewed, and provided with tooling migration assistance. We expect
that the progressive mode will be a nice choice for any actively maintained codebases which are updated to the latest
language versions quickly.

Inline
classes

Inline classes are in Alpha. They may change incompatibly and require manual migration in the future. We
appreciate your feedback on it in YouTrack. See details in the reference.

Kotlin 1.3 introduces a new kind of declaration — inline class. Inline classes can be viewed as a restricted version of the
usual classes, in particular, inline classes must have exactly one property:

inline class Name(val s: String)

The Kotlin compiler will use this restriction to aggressively optimize runtime representation of inline classes and substitute
their instances with the value of the underlying property where possible removing constructor calls, GC pressure, and
enabling other optimizations:

inline class Name(val s: String)


//sampleStart
fun main() {
// In the next line no constructor call happens, and
// at the runtime 'name' contains just string "Kotlin"
val name = Name("Kotlin")
println(name.s)
}
//sampleEnd

See reference for inline classes for details.

Unsigned
integers

Unsigned integers are in Beta. Their implementation is almost stable, but migration steps may be required in the
future. We'll do our best to minimize any changes you will have to make.

136
Kotlin 1.3 introduces unsigned integer types:

kotlin.UByte: an unsigned 8-bit integer, ranges from 0 to 255

kotlin.UShort: an unsigned 16-bit integer, ranges from 0 to 65535

kotlin.UInt: an unsigned 32-bit integer, ranges from 0 to 2^32 - 1

kotlin.ULong: an unsigned 64-bit integer, ranges from 0 to 2^64 - 1

Most of the functionality of signed types are supported for unsigned counterparts too:

fun main() {
//sampleStart
// You can define unsigned types using literal suffixes
val uint = 42u
val ulong = 42uL
val ubyte: UByte = 255u

// You can convert signed types to unsigned and vice versa via stdlib extensions:
val int = uint.toInt()
val byte = ubyte.toByte()
val ulong2 = byte.toULong()

// Unsigned types support similar operators:


val x = 20u + 22u
val y = 1u shl 8
val z = "128".toUByte()
val range = 1u..5u
//sampleEnd
println("ubyte: $ubyte, byte: $byte, ulong2: $ulong2")
println("x: $x, y: $y, z: $z, range: $range")
}

See reference for details.

@JvmDefault

@JvmDefault is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes.
We appreciate your feedback on it in YouTrack.

Kotlin targets a wide range of the Java versions, including Java 6 and Java 7, where default methods in the interfaces are
not allowed. For your convenience, the Kotlin compiler works around that limitation, but this workaround isn't compatible
with the default methods, introduced in Java 8.

This could be an issue for Java-interoperability, so Kotlin 1.3 introduces the @JvmDefault annotation. Methods annotated
with this annotation will be generated as default methods for JVM:

interface Foo {

137
// Will be generated as 'default' method
@JvmDefault
fun foo(): Int = 42
}

Warning! Annotating your API with @JvmDefault has serious implications on binary compatibility. Make sure to
carefully read the reference page before using @JvmDefault in production.

Standard
library

Multiplatform
random
Prior to Kotlin 1.3, there was no uniform way to generate random numbers on all platforms — we had to resort to
platform-specific solutions like java.util.Random on JVM. This release fixes this issue by introducing the class
kotlin.random.Random, which is available on all platforms:

import kotlin.random.Random

fun main() {
//sampleStart
val number = Random.nextInt(42) // number is in range [0, limit)
println(number)
//sampleEnd
}

isNullOrEmpty
and
orEmpty
extensions
isNullOrEmpty and orEmpty extensions for some types are already present in stdlib. The first one returns true if the
receiver is null or empty, and the second one falls back to an empty instance if the receiver is null. Kotlin 1.3 provides
similar extensions on collections, maps, and arrays of objects.

Copy
elements
between
two
existing
arrays
The array.copyInto(targetArray, targetOffset, startIndex, endIndex) functions for the existing array types, including the
unsigned arrays, make it easier to implement array-based containers in pure Kotlin.

fun main() {
//sampleStart
val sourceArr = arrayOf("k", "o", "t", "l", "i", "n")
val targetArr = sourceArr.copyInto(arrayOfNulls<String>(6), 3, startIndex = 3, endIndex = 6)
println(targetArr.contentToString())

sourceArr.copyInto(targetArr, startIndex = 0, endIndex = 3)
println(targetArr.contentToString())
//sampleEnd
}

138
associateWith
It is quite a common situation to have a list of keys and want to build a map by associating each of these keys with some
value. It was possible to do it before with the associate { it to getValue(it) } function, but now we’re introducing a more
efficient and easy to explore alternative: keys.associateWith { getValue(it) }.

fun main() {
//sampleStart
val keys = 'a'..'f'
val map = keys.associateWith { it.toString().repeat(5).capitalize() }
map.forEach { println(it) }
//sampleEnd
}

ifEmpty
and
ifBlank
functions
Collections, maps, object arrays, char sequences, and sequences now have an ifEmpty function, which allows specifying
a fallback value that will be used instead of the receiver if it is empty:

fun main() {
//sampleStart
fun printAllUppercase(data: List<String>) {
val result = data
.filter { it.all { c -> c.isUpperCase() } }
.ifEmpty { listOf("<no uppercase>") }
result.forEach { println(it) }
}

printAllUppercase(listOf("foo", "Bar"))
printAllUppercase(listOf("FOO", "BAR"))
//sampleEnd
}

Char sequences and strings in addition have an ifBlank extension that does the same thing as ifEmpty but checks for a
string being all whitespace instead of empty.

fun main() {
//sampleStart
val s = " \n"
println(s.ifBlank { "<blank>" })
println(s.ifBlank { null })
//sampleEnd
}

Sealed
classes
in
reflection
We’ve added a new API to kotlin-reflect that can be used to enumerate all the direct subtypes of a sealed class,
namely KClass.sealedSubclasses.

Smaller
changes

139
Boolean type now has companion.

Any?.hashCode() extension that returns 0 for null.

Char now provides MIN_VALUE and MAX_VALUE constants.

SIZE_BYTES and SIZE_BITS constants in primitive type companions.

Tooling

Code
style
support
in
IDE
Kotlin 1.3 introduces support for the recommended code style in IntelliJ IDEA. Check out this page for the migration
guidelines.

kotlinx.serialization
kotlinx.serialization is a library which provides multiplatform support for (de)serializing objects in Kotlin. Previously, it was
a separate project, but since Kotlin 1.3, it ships with the Kotlin compiler distribution on par with the other compiler
plugins. The main difference is that you don't need to manually watch out for the Serialization IDE Plugin being
compatible with the Kotlin IDE plugin version you're using: now the Kotlin IDE plugin already includes serialization!

See here for details.

Even though kotlinx.serialization now ships with the Kotlin Compiler distribution, it is still considered to be an
experimental feature in Kotlin 1.3.

Scripting
update

Scripting is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes. We
appreciate your feedback on it in YouTrack.

Kotlin 1.3 continues to evolve and improve scripting API, introducing some experimental support for scripts
customization, such as adding external properties, providing static or dynamic dependencies, and so on.

For additional details, please consult the KEEP-75.

Scratches
support
Kotlin 1.3 introduces support for runnable Kotlin scratch files. Scratch file is a kotlin script file with the .kts extension that
you can run and get evaluation results directly in the editor.

140
Consult the general Scratches documentation for details.

What's
new
in
Kotlin
1.2
Release date: 28 November 2017

Table
of
contents
Multiplatform projects

Other language features

Standard library

JVM backend

JavaScript backend

Multiplatform
projects
(experimental)
Multiplatform projects are a new experimental feature in Kotlin 1.2, allowing you to reuse code between target platforms
supported by Kotlin – JVM, JavaScript, and (in the future) Native. In a multiplatform project, you have three kinds of
modules:

A common module contains code that is not specific to any platform, as well as declarations without implementation
of platform-dependent APIs.

A platform module contains implementations of platform-dependent declarations in the common module for a specific
platform, as well as other platform-dependent code.

A regular module targets a specific platform and can either be a dependency of platform modules or depend on
platform modules.

When you compile a multiplatform project for a specific platform, the code for both the common and platform-specific
parts is generated.

A key feature of the multiplatform project support is the possibility to express dependencies of common code on
platform-specific parts through expected and actual declarations. An expected declaration specifies an API (class,
interface, annotation, top-level declaration etc.). An actual declaration is either a platform-dependent implementation of
the API or a typealias referring to an existing implementation of the API in an external library. Here's an example:

In the common code:

// expected platform-specific API:


expect fun hello(world: String): String

141
fun greet() {
// usage of the expected API:
val greeting = hello("multiplatform world")
println(greeting)
}

expect class URL(spec: String) {


open fun getHost(): String
open fun getPath(): String
}

In the JVM platform code:

actual fun hello(world: String): String =


"Hello, $world, on the JVM platform!"

// using existing platform-specific implementation:


actual typealias URL = java.net.URL

See the multiplatform programming documentation for details and steps to build a multiplatform project.

Other
language
features

Array
literals
in
annotations
Starting with Kotlin 1.2, array arguments for annotations can be passed with the new array literal syntax instead of the
arrayOf function:

@CacheConfig(cacheNames = ["books", "default"])


public class BookRepositoryImpl {
// ...
}

The array literal syntax is constrained to annotation arguments.

Lateinit
top-level
properties
and
local
variables
The lateinit modifier can now be used on top-level properties and local variables. The latter can be used, for example,
when a lambda passed as a constructor argument to one object refers to another object which has to be defined later:

class Node<T>(val value: T, val next: () -> Node<T>)

fun main(args: Array<String>) {


// A cycle of three nodes:
lateinit var third: Node<Int>

val second = Node(2, next = { third })


val first = Node(1, next = { second })

142
third = Node(3, next = { first })

val nodes = generateSequence(first) { it.next() }


println("Values in the cycle: ${nodes.take(7).joinToString { it.value.toString() }}, ...")
}

Check
whether
a
lateinit
var
is
initialized
You can now check whether a lateinit var has been initialized using isInitialized on the property reference:

class Foo {
lateinit var lateinitVar: String

fun initializationLogic() {
//sampleStart
println("isInitialized before assignment: " + this::lateinitVar.isInitialized)
lateinitVar = "value"
println("isInitialized after assignment: " + this::lateinitVar.isInitialized)
//sampleEnd
}
}

fun main(args: Array<String>) {


Foo().initializationLogic()
}

Inline
functions
with
default
functional
parameters
Inline functions are now allowed to have default values for their inlined functional parameters:

//sampleStart
inline fun <E> Iterable<E>.strings(transform: (E) -> String = { it.toString() }) =
map { transform(it) }

val defaultStrings = listOf(1, 2, 3).strings()


val customStrings = listOf(1, 2, 3).strings { "($it)" }
//sampleEnd

fun main(args: Array<String>) {


println("defaultStrings = $defaultStrings")
println("customStrings = $customStrings")
}

Information
from
explicit
casts
is
used
for
type
inference
The Kotlin compiler can now use information from type casts in type inference. If you’re calling a generic method that
returns a type parameter T and casting the return value to a specific type Foo, the compiler now understands that T for
this call needs to be bound to the type Foo.

This is particularly important for Android developers, since the compiler can now correctly analyze generic findViewById
calls in Android API level 26:

143
val button = findViewById(R.id.button) as Button

Smart
cast
improvements
When a variable is assigned from a safe call expression and checked for null, the smart cast is now applied to the safe
call receiver as well:

fun countFirst(s: Any): Int {


//sampleStart
val firstChar = (s as? CharSequence)?.firstOrNull()
if (firstChar != null)
return s.count { it == firstChar } // s: Any is smart cast to CharSequence

val firstItem = (s as? Iterable<*>)?.firstOrNull()


if (firstItem != null)
return s.count { it == firstItem } // s: Any is smart cast to Iterable<*>
//sampleEnd
return -1
}

fun main(args: Array<String>) {


val string = "abacaba"
val countInString = countFirst(string)
println("called on \"$string\": $countInString")

val list = listOf(1, 2, 3, 1, 2)


val countInList = countFirst(list)
println("called on $list: $countInList")
}

Also, smart casts in a lambda are now allowed for local variables that are only modified before the lambda:

fun main(args: Array<String>) {


//sampleStart
val flag = args.size == 0
var x: String? = null
if (flag) x = "Yahoo!"

run {
if (x != null) {
println(x.length) // x is smart cast to String
}
}
//sampleEnd
}

Support
for
::foo
as
a
shorthand
for
this::foo
A bound callable reference to a member of this can now be written without explicit receiver, ::foo instead of this::foo. This
also makes callable references more convenient to use in lambdas where you refer to a member of the outer receiver.

144
Breaking
change:
sound
smart
casts
after
try
blocks
Earlier, Kotlin used assignments made inside a try block for smart casts after the block, which could break type- and null-
safety and lead to runtime failures. This release fixes this issue, making the smart casts more strict, but breaking some
code that relied on such smart casts.

To switch to the old smart casts behavior, pass the fallback flag -Xlegacy-smart-cast-after-try as the compiler argument.
It will become deprecated in Kotlin 1.3.

Deprecation:
data
classes
overriding
copy
When a data class derived from a type that already had the copy function with the same signature, the copy
implementation generated for the data class used the defaults from the supertype, leading to counter-intuitive behavior, or
failed at runtime if there were no default parameters in the supertype.

Inheritance that leads to a copy conflict has become deprecated with a warning in Kotlin 1.2 and will be an error in Kotlin
1.3.

Deprecation:
nested
types
in
enum
entries
Inside enum entries, defining a nested type that is not an inner class has been deprecated due to issues in the
initialization logic. This causes a warning in Kotlin 1.2 and will become an error in Kotlin 1.3.

Deprecation:
single
named
argument
for
vararg
For consistency with array literals in annotations, passing a single item for a vararg parameter in the named form
(foo(items = i)) has been deprecated. Please use the spread operator with the corresponding array factory functions:

foo(items = *intArrayOf(1))

There is an optimization that removes redundant arrays creation in such cases, which prevents performance degradation.
The single-argument form produces warnings in Kotlin 1.2 and is to be dropped in Kotlin 1.3.

Deprecation:
inner
classes
of
generic
classes
extending
Throwable
Inner classes of generic types that inherit from Throwable could violate type-safety in a throw-catch scenario and thus
have been deprecated, with a warning in Kotlin 1.2 and an error in Kotlin 1.3.

Deprecation:
mutating
backing
field
of
a
read-only
property
Mutating the backing field of a read-only property by assigning field = ... in the custom getter has been deprecated, with a
warning in Kotlin 1.2 and an error in Kotlin 1.3.

Standard
library

145
Kotlin
standard
library
artifacts
and
split
packages
The Kotlin standard library is now fully compatible with the Java 9 module system, which forbids split packages (multiple
jar files declaring classes in the same package). In order to support that, new artifacts kotlin-stdlib-jdk7 and kotlin-stdlib-
jdk8 are introduced, which replace the old kotlin-stdlib-jre7 and kotlin-stdlib-jre8.

The declarations in the new artifacts are visible under the same package names from the Kotlin point of view, but have
different package names for Java. Therefore, switching to the new artifacts will not require any changes to your source
code.

Another change made to ensure compatibility with the new module system is removing the deprecated declarations in the
kotlin.reflect package from the kotlin-reflect library. If you were using them, you need to switch to using the declarations in
the kotlin.reflect.full package, which is supported since Kotlin 1.1.

windowed,
chunked,
zipWithNext
New extensions for Iterable<T>, Sequence<T>, and CharSequence cover such use cases as buffering or batch
processing (chunked), sliding window and computing sliding average (windowed) , and processing pairs of subsequent
items (zipWithNext):

fun main(args: Array<String>) {


//sampleStart
val items = (1..9).map { it * it }

val chunkedIntoLists = items.chunked(4)


val points3d = items.chunked(3) { (x, y, z) -> Triple(x, y, z) }
val windowed = items.windowed(4)
val slidingAverage = items.windowed(4) { it.average() }
val pairwiseDifferences = items.zipWithNext { a, b -> b - a }
//sampleEnd

println("items: $items\n")

println("chunked into lists: $chunkedIntoLists")


println("3D points: $points3d")
println("windowed by 4: $windowed")
println("sliding average by 4: $slidingAverage")
println("pairwise differences: $pairwiseDifferences")
}

fill,
replaceAll,
shuffle/shuffled
A set of extension functions was added for manipulating lists: fill, replaceAll and shuffle for MutableList, and shuffled for
read-only List:

fun main(args: Array<String>) {


//sampleStart
val items = (1..5).toMutableList()

items.shuffle()
println("Shuffled items: $items")

items.replaceAll { it * 2 }

146
println("Items doubled: $items")

items.fill(5)
println("Items filled with 5: $items")
//sampleEnd
}

Math
operations
in
kotlin-stdlib
Satisfying the longstanding request, Kotlin 1.2 adds the kotlin.math API for math operations that is common for JVM and
JS and contains the following:

Constants: PI and E

Trigonometric: cos, sin, tan and inverse of them: acos, asin, atan, atan2

Hyperbolic: cosh, sinh, tanh and their inverse: acosh, asinh, atanh

Exponentation: pow (an extension function), sqrt, hypot, exp, expm1

Logarithms: log, log2, log10, ln, ln1p

Rounding:
ceil, floor, truncate, round (half to even) functions

roundToInt, roundToLong (half to integer) extension functions

Sign and absolute value:


abs and sign functions

absoluteValue and sign extension properties

withSign extension function

max and min of two values

Binary representation:
ulp extension property

nextUp, nextDown, nextTowards extension functions

toBits, toRawBits, Double.fromBits (these are in the kotlin package)

The same set of functions (but without constants) is also available for Float arguments.

Operators
and
conversions
for
BigInteger
and
BigDecimal
Kotlin 1.2 introduces a set of functions for operating with BigInteger and BigDecimal and creating them from other
numeric types. These are:

toBigInteger for Int and Long

147
toBigDecimal for Int, Long, Float, Double, and BigInteger

Arithmetic and bitwise operator functions:


Binary operators +, -, *, /, % and infix functions and, or, xor, shl, shr

Unary operators -, ++, --, and a function inv

Floating
point
to
bits
conversions
New functions were added for converting Double and Float to and from their bit representations:

toBits and toRawBits returning Long for Double and Int for Float

Double.fromBits and Float.fromBits for creating floating point numbers from the bit representation

Regex
is
now
serializable
The kotlin.text.Regex class has become Serializable and can now be used in serializable hierarchies.

Closeable.use
calls
Throwable.addSuppressed
if
available
The Closeable.use function calls Throwable.addSuppressed when an exception is thrown during closing the resource
after some other exception.

To enable this behavior you need to have kotlin-stdlib-jdk7 in your dependencies.

JVM
backend

Constructor
calls
normalization
Ever since version 1.0, Kotlin supported expressions with complex control flow, such as try-catch expressions and inline
function calls. Such code is valid according to the Java Virtual Machine specification. Unfortunately, some bytecode
processing tools do not handle such code quite well when such expressions are present in the arguments of constructor
calls.

To mitigate this problem for the users of such bytecode processing tools, we’ve added a command-line compiler
option (-Xnormalize-constructor-calls=MODE) that tells the compiler to generate more Java-like bytecode for such
constructs. Here MODE is one of:

disable (default) – generate bytecode in the same way as in Kotlin 1.0 and 1.1.

enable – generate Java-like bytecode for constructor calls. This can change the order in which the classes are
loaded and initialized.

preserve-class-initialization – generate Java-like bytecode for constructor calls, ensuring that the class initialization
order is preserved. This can affect overall performance of your application; use it only if you have some complex state
shared between multiple classes and updated on class initialization.

148
The “manualâ€​ workaround is to store the values of sub-expressions with control flow in variables, instead of
evaluating them directly inside the call arguments. It’s similar to -Xnormalize-constructor-calls=enable.

Java-default
method
calls
Before Kotlin 1.2, interface members overriding Java-default methods while targeting JVM 1.6 produced a warning on
super calls: Super calls to Java default methods are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'. In
Kotlin 1.2, there's an error instead, thus requiring any such code to be compiled with JVM target 1.8.

Breaking
change:
consistent
behavior
of
x.equals(null)
for
platform
types
Calling x.equals(null) on a platform type that is mapped to a Java primitive (Int!, Boolean!, Short!, Long!, Float!, Double!,
Char!) incorrectly returned true when x was null. Starting with Kotlin 1.2, calling x.equals(...) on a null value of a platform
type throws an NPE (but x == ... does not).

To return to the pre-1.2 behavior, pass the flag -Xno-exception-on-explicit-equals-for-boxed-null to the compiler.

Breaking
change:
fix
for
platform
null
escaping
through
an
inlined
extension
receiver
Inline extension functions that were called on a null value of a platform type did not check the receiver for null and would
thus allow null to escape into the other code. Kotlin 1.2 forces this check at the call sites, throwing an exception if the
receiver is null.

To switch to the old behavior, pass the fallback flag -Xno-receiver-assertions to the compiler.

JavaScript
backend

TypedArrays
support
enabled
by
default
The JS typed arrays support that translates Kotlin primitive arrays, such as IntArray, DoubleArray, into JavaScript typed
arrays, that was previously an opt-in feature, has been enabled by default.

Tools

Warnings
as
errors
The compiler now provides an option to treat all warnings as errors. Use -Werror on the command line, or the following
Gradle snippet:

compileKotlin {
kotlinOptions.allWarningsAsErrors = true
}

149
What's
new
in
Kotlin
1.1
Release date: 15 February 2016

Table
of
contents
Coroutines

Other language features

Standard library

JVM backend

JavaScript backend

JavaScript
Starting with Kotlin 1.1, the JavaScript target is no longer considered experimental. All language features are supported,
and there are many new tools for integration with the frontend development environment. See below for a more detailed
list of changes.

Coroutines
(experimental)
The key new feature in Kotlin 1.1 is coroutines, bringing the support of async/ await, yield, and similar programming
patterns. The key feature of Kotlin's design is that the implementation of coroutine execution is part of the libraries, not
the language, so you aren't bound to any specific programming paradigm or concurrency library.

A coroutine is effectively a light-weight thread that can be suspended and resumed later. Coroutines are supported
through suspending functions: a call to such a function can potentially suspend a coroutine, and to start a new coroutine
we usually use an anonymous suspending functions (i.e. suspending lambdas).

Let's look at async/ await which is implemented in an external library, kotlinx.coroutines:

// runs the code in the background thread pool


fun asyncOverlay() = async(CommonPool) {
// start two async operations
val original = asyncLoadImage("original")
val overlay = asyncLoadImage("overlay")
// and then apply overlay to both results
applyOverlay(original.await(), overlay.await())
}

// launches new coroutine in UI context


launch(UI) {
// wait for async overlay to complete
val image = asyncOverlay().await()

150
// and then show it in UI
showImage(image)
}

Here, async { ... } starts a coroutine and, when we use await(), the execution of the coroutine is suspended while the
operation being awaited is executed, and is resumed (possibly on a different thread) when the operation being awaited
completes.

The standard library uses coroutines to support lazily generated sequences with yield and yieldAll functions. In such a
sequence, the block of code that returns sequence elements is suspended after each element has been retrieved, and
resumed when the next element is requested. Here's an example:

import kotlin.coroutines.experimental.*

fun main(args: Array<String>) {


val seq = buildSequence {
for (i in 1..5) {
// yield a square of i
yield(i * i)
}
// yield a range
yieldAll(26..28)
}

// print the sequence


println(seq.toList())
}

Run the code above to see the result. Feel free to edit it and run again!

For more information, please refer to the coroutines documentation and tutorial.

Note that coroutines are currently considered an experimental feature, meaning that the Kotlin team is not committing to
supporting the backwards compatibility of this feature after the final 1.1 release.

Other
language
features

Type
aliases
A type alias allows you to define an alternative name for an existing type. This is most useful for generic types such as
collections, as well as for function types. Here is an example:

//sampleStart
typealias OscarWinners = Map<String, String>

fun countLaLaLand(oscarWinners: OscarWinners) =


oscarWinners.count { it.value.contains("La La Land") }

// Note that the type names (initial and the type alias) are interchangeable:
fun checkLaLaLandIsTheBestMovie(oscarWinners: Map<String, String>) =
oscarWinners["Best picture"] == "La La Land"

151
//sampleEnd

fun oscarWinners(): OscarWinners {


return mapOf(
"Best song" to "City of Stars (La La Land)",
"Best actress" to "Emma Stone (La La Land)",
"Best picture" to "Moonlight" /* ... */)
}

fun main(args: Array<String>) {


val oscarWinners = oscarWinners()

val laLaLandAwards = countLaLaLand(oscarWinners)


println("LaLaLandAwards = $laLaLandAwards (in our small example), but actually it's 6.")

val laLaLandIsTheBestMovie = checkLaLaLandIsTheBestMovie(oscarWinners)


println("LaLaLandIsTheBestMovie = $laLaLandIsTheBestMovie")
}

See the type aliases documentation and KEEP for more details.

Bound
callable
references
You can now use the :: operator to get a member reference pointing to a method or property of a specific object instance.
Previously this could only be expressed with a lambda. Here's an example:

//sampleStart
val numberRegex = "\\d+".toRegex()
val numbers = listOf("abc", "123", "456").filter(numberRegex::matches)
//sampleEnd

fun main(args: Array<String>) {


println("Result is $numbers")
}

Read the documentation and KEEP for more details.

Sealed
and
data
classes
Kotlin 1.1 removes some of the restrictions on sealed and data classes that were present in Kotlin 1.0. Now you can
define subclasses of a top-level sealed class on the top level in the same file, and not just as nested classes of the sealed
class. Data classes can now extend other classes. This can be used to define a hierarchy of expression classes nicely and
cleanly:

//sampleStart
sealed class Expr

data class Const(val number: Double) : Expr()


data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

fun eval(expr: Expr): Double = when (expr) {


is Const -> expr.number

152
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
}
val e = eval(Sum(Const(1.0), Const(2.0)))
//sampleEnd

fun main(args: Array<String>) {


println("e is $e") // 3.0
}

Read the sealed classes documentation or KEEPs for sealed class and data class for more detail.

Destructuring
in
lambdas
You can now use the destructuring declaration syntax to unpack the arguments passed to a lambda. Here's an example:

fun main(args: Array<String>) {


//sampleStart
val map = mapOf(1 to "one", 2 to "two")
// before
println(map.mapValues { entry ->
val (key, value) = entry
"$key -> $value!"
})
// now
println(map.mapValues { (key, value) -> "$key -> $value!" })
//sampleEnd
}

Read the destructuring declarations documentation and KEEP for more details.

Underscores
for
unused
parameters
For a lambda with multiple parameters, you can use the _ character to replace the names of the parameters you don't
use:

fun main(args: Array<String>) {


val map = mapOf(1 to "one", 2 to "two")

//sampleStart
map.forEach { _, value -> println("$value!") }
//sampleEnd
}

This also works in destructuring declarations:

data class Result(val value: Any, val status: String)

fun getResult() = Result(42, "ok").also { println("getResult() returns $it") }

fun main(args: Array<String>) {


//sampleStart

153
val (_, status) = getResult()
//sampleEnd
println("status is '$status'")
}

Read the KEEP for more details.

Underscores
in
numeric
literals
Just as in Java 8, Kotlin now allows to use underscores in numeric literals to separate groups of digits:

//sampleStart
val oneMillion = 1_000_000
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010
//sampleEnd

fun main(args: Array<String>) {


println(oneMillion)
println(hexBytes.toString(16))
println(bytes.toString(2))
}

Read the KEEP for more details.

Shorter
syntax
for
properties
For properties with the getter defined as an expression body, the property type can now be omitted:

//sampleStart
data class Person(val name: String, val age: Int) {
val isAdult get() = age >= 20 // Property type inferred to be 'Boolean'
}
//sampleEnd
fun main(args: Array<String>) {
val akari = Person("Akari", 26)
println("$akari.isAdult = ${akari.isAdult}")
}

Inline
property
accessors
You can now mark property accessors with the inline modifier if the properties don't have a backing field. Such accessors
are compiled in the same way as inline functions.

//sampleStart
public val <T> List<T>.lastIndex: Int
inline get() = this.size - 1
//sampleEnd

fun main(args: Array<String>) {


val list = listOf('a', 'b')

154
// the getter will be inlined
println("Last index of $list is ${list.lastIndex}")
}

You can also mark the entire property as inline- then the modifier is applied to both accessors.

Read the inline functions documentation and KEEP for more details.

Local
delegated
properties
You can now use the delegated property syntax with local variables. One possible use is defining a lazily evaluated local
variable:

import java.util.Random

fun needAnswer() = Random().nextBoolean()

fun main(args: Array<String>) {


//sampleStart
val answer by lazy {
println("Calculating the answer...")
42
}
if (needAnswer()) { // returns the random value
println("The answer is $answer.") // answer is calculated at this point
}
else {
println("Sometimes no answer is the answer...")
}
//sampleEnd
}

Read the KEEP for more details.

Interception
of
delegated
property
binding
For delegated properties, it is now possible to intercept delegate to property binding using the provideDelegate operator.
For example, if we want to check the property name before binding, we can write something like this:

class ResourceLoader<T>(id: ResourceID<T>) {


operator fun provideDelegate(thisRef: MyUI, prop: KProperty<*>): ReadOnlyProperty<MyUI, T> {
checkProperty(thisRef, prop.name)
... // property creation
}

private fun checkProperty(thisRef: MyUI, name: String) { ... }


}

fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { ... }

class MyUI {
val image by bindResource(ResourceID.image_id)
val text by bindResource(ResourceID.text_id)
}

155
The provideDelegate method will be called for each property during the creation of a MyUI instance, and it can perform
the necessary validation right away.

Read the delegated properties documentation for more details.

Generic
enum
value
access
It is now possible to enumerate the values of an enum class in a generic way.

//sampleStart
enum class RGB { RED, GREEN, BLUE }

inline fun <reified T : Enum<T>> printAllValues() {


print(enumValues<T>().joinToString { it.name })
}
//sampleEnd

fun main(args: Array<String>) {


printAllValues<RGB>() // prints RED, GREEN, BLUE
}

Scope
control
for
implicit
receivers
in
DSLs
The @DslMarker annotation allows to restrict the use of receivers from outer scopes in a DSL context. Consider the
canonical HTML builder example:

table {
tr {
td { + "Text" }
}
}

In Kotlin 1.0, code in the lambda passed to td has access to three implicit receivers: the one passed to table, to tr and to
td. This allows you to call methods that make no sense in the context - for example to call tr inside td and thus to put a
<tr> tag in a <td>.

In Kotlin 1.1, you can restrict that, so that only methods defined on the implicit receiver of td will be available inside the
lambda passed to td. You do that by defining your annotation marked with the @DslMarker meta-annotation and applying
it to the base class of the tag classes.

Read the type safe builders documentation and KEEP for more details.

rem
operator
The mod operator is now deprecated, and rem is used instead. See this issue for motivation.

156
Standard
library

String
to
number
conversions
There is a bunch of new extensions on the String class to convert it to a number without throwing an exception on invalid
number: String.toIntOrNull(): Int?, String.toDoubleOrNull(): Double? etc.

val port = System.getenv("PORT")?.toIntOrNull() ?: 80

Also integer conversion functions, like Int.toString(), String.toInt(), String.toIntOrNull(), each got an overload with radix
parameter, which allows to specify the base of conversion (2 to 36).

onEach()
onEach is a small, but useful extension function for collections and sequences, which allows to perform some action,
possibly with side-effects, on each element of the collection/sequence in a chain of operations. On iterables it behaves
like forEach but also returns the iterable instance further. And on sequences it returns a wrapping sequence, which
applies the given action lazily as the elements are being iterated.

inputDir.walk()
.filter { it.isFile && it.name.endsWith(".txt") }
.onEach { println("Moving $it to $outputDir") }
.forEach { moveFile(it, File(outputDir, it.toRelativeString(inputDir))) }

also(),
takeIf(),
and
takeUnless()
These are three general-purpose extension functions applicable to any receiver.

also is like apply: it takes the receiver, does some action on it, and returns that receiver. The difference is that in the block
inside apply the receiver is available as this, while in the block inside also it's available as it (and you can give it another
name if you want). This comes handy when you do not want to shadow this from the outer scope:

class Block {
lateinit var content: String
}

//sampleStart
fun Block.copy() = Block().also {
it.content = this.content
}
//sampleEnd

// using 'apply' instead


fun Block.copy1() = Block().apply {
this.content = [email protected]
}

fun main(args: Array<String>) {


val block = Block().apply { content = "content" }

157
val copy = block.copy()
println("Testing the content was copied:")
println(block.content == copy.content)
}

takeIf is like filter for a single value. It checks whether the receiver meets the predicate, and returns the receiver, if it does
or null if it doesn't. Combined with an elvis operator (?:) and early returns it allows writing constructs like:

val outDirFile = File(outputDir.path).takeIf { it.exists() } ?: return false


// do something with existing outDirFile

fun main(args: Array<String>) {


val input = "Kotlin"
val keyword = "in"

//sampleStart
val index = input.indexOf(keyword).takeIf { it >= 0 } ?: error("keyword not found")
// do something with index of keyword in input string, given that it's found
//sampleEnd

println("'$keyword' was found in '$input'")
println(input)
println(" ".repeat(index) + "^")
}

takeUnless is the same as takeIf, but it takes the inverted predicate. It returns the receiver when it doesn't meet the
predicate and null otherwise. So one of the examples above could be rewritten with takeUnless as following:

val index = input.indexOf(keyword).takeUnless { it < 0 } ?: error("keyword not found")

It is also convenient to use when you have a callable reference instead of the lambda:

private fun testTakeUnless(string: String) {


//sampleStart
val result = string.takeUnless(String::isEmpty)
//sampleEnd

println("string = \"$string\"; result = \"$result\"")


}

fun main(args: Array<String>) {


testTakeUnless("")
testTakeUnless("abc")
}

groupingBy()
This API can be used to group a collection by key and fold each group simultaneously. For example, it can be used to
count the number of words starting with each letter:

158
fun main(args: Array<String>) {
val words = "one two three four five six seven eight nine ten".split(' ')
//sampleStart
val frequencies = words.groupingBy { it.first() }.eachCount()
//sampleEnd
println("Counting first letters: $frequencies.")

// The alternative way that uses 'groupBy' and 'mapValues' creates an intermediate map,
// while 'groupingBy' way counts on the fly.
val groupBy = words.groupBy { it.first() }.mapValues { (_, list) -> list.size }
println("Comparing the result with using 'groupBy': ${groupBy == frequencies}.")
}

Map.toMap()
and
Map.toMutableMap()
These functions can be used for easy copying of maps:

class ImmutablePropertyBag(map: Map<String, Any>) {


private val mapCopy = map.toMap()
}

Map.minus(key)
The operator plus provides a way to add key-value pair(s) to a read-only map producing a new map, however there was
not a simple way to do the opposite: to remove a key from the map you have to resort to less straightforward ways to like
Map.filter() or Map.filterKeys(). Now the operator minus fills this gap. There are 4 overloads available: for removing a single
key, a collection of keys, a sequence of keys and an array of keys.

fun main(args: Array<String>) {


//sampleStart
val map = mapOf("key" to 42)
val emptyMap = map - "key"
//sampleEnd

println("map: $map")
println("emptyMap: $emptyMap")
}

minOf()
and
maxOf()
These functions can be used to find the lowest and greatest of two or three given values, where values are primitive
numbers or Comparable objects. There is also an overload of each function that take an additional Comparator instance if
you want to compare objects that are not comparable themselves.

fun main(args: Array<String>) {


//sampleStart
val list1 = listOf("a", "b")
val list2 = listOf("x", "y", "z")
val minSize = minOf(list1.size, list2.size)

159
val longestList = maxOf(list1, list2, compareBy { it.size })
//sampleEnd

println("minSize = $minSize")
println("longestList = $longestList")
}

Array-like
List
instantiation
functions
Similar to the Array constructor, there are now functions that create List and MutableList instances and initialize each
element by calling a lambda:

fun main(args: Array<String>) {


//sampleStart
val squares = List(10) { index -> index * index }
val mutable = MutableList(10) { 0 }
//sampleEnd

println("squares: $squares")
println("mutable: $mutable")
}

Map.getValue()
This extension on Map returns an existing value corresponding to the given key or throws an exception, mentioning which
key was not found. If the map was produced with withDefault, this function will return the default value instead of throwing
an exception.

fun main(args: Array<String>) {


//sampleStart
val map = mapOf("key" to 42)
// returns non-nullable Int value 42
val value: Int = map.getValue("key")

val mapWithDefault = map.withDefault { k -> k.length }


// returns 4
val value2 = mapWithDefault.getValue("key2")

// map.getValue("anotherKey") // <- this will throw NoSuchElementException


//sampleEnd

println("value is $value")
println("value2 is $value2")
}

Abstract
collections
These abstract classes can be used as base classes when implementing Kotlin collection classes. For implementing read-
only collections there are AbstractCollection, AbstractList, AbstractSet and AbstractMap, and for mutable collections
there are AbstractMutableCollection, AbstractMutableList, AbstractMutableSet and AbstractMutableMap. On JVM, these
abstract mutable collections inherit most of their functionality from JDK's abstract collections.

160
Array
manipulation
functions
The standard library now provides a set of functions for element-by-element operations on arrays: comparison
(contentEquals and contentDeepEquals), hash code calculation (contentHashCode and contentDeepHashCode), and
conversion to a string (contentToString and contentDeepToString). They're supported both for the JVM (where they act as
aliases for the corresponding functions in java.util.Arrays) and for JS (where the implementation is provided in the Kotlin
standard library).

fun main(args: Array<String>) {


//sampleStart
val array = arrayOf("a", "b", "c")
println(array.toString()) // JVM implementation: type-and-hash gibberish
println(array.contentToString()) // nicely formatted as list
//sampleEnd
}

JVM
Backend

Java
8
bytecode
support
Kotlin has now the option of generating Java 8 bytecode (-jvm-target 1.8 command line option or the corresponding
options in Ant/Maven/Gradle). For now this doesn't change the semantics of the bytecode (in particular, default methods
in interfaces and lambdas are generated exactly as in Kotlin 1.0), but we plan to make further use of this later.

Java
8
standard
library
support
There are now separate versions of the standard library supporting the new JDK APIs added in Java 7 and 8. If you need
access to the new APIs, use kotlin-stdlib-jre7 and kotlin-stdlib-jre8 maven artifacts instead of the standard kotlin-stdlib.
These artifacts are tiny extensions on top of kotlin-stdlib and they bring it to your project as a transitive dependency.

Parameter
names
in
the
bytecode
Kotlin now supports storing parameter names in the bytecode. This can be enabled using the -java-parameters command
line option.

Constant
inlining
The compiler now inlines values of const val properties into the locations where they are used.

Mutable
closure
variables
The box classes used for capturing mutable closure variables in lambdas no longer have volatile fields. This change
improves performance, but can lead to new race conditions in some rare usage scenarios. If you're affected by this, you
need to provide your own synchronization for accessing the variables.

161
javax.script
support
Kotlin now integrates with the javax.script API (JSR-223). The API allows to evaluate snippets of code at runtime:

val engine = ScriptEngineManager().getEngineByExtension("kts")!!


engine.eval("val x = 3")
println(engine.eval("x + 2")) // Prints out 5

See here for a larger example project using the API.

kotlin.reflect.full
To prepare for Java 9 support, the extension functions and properties in the kotlin-reflect.jar library have been moved to
the package kotlin.reflect.full. The names in the old package (kotlin.reflect) are deprecated and will be removed in Kotlin
1.2. Note that the core reflection interfaces (such as KClass) are part of the Kotlin standard library, not kotlin-reflect, and
are not affected by the move.

JavaScript
backend

Unified
standard
library
A much larger part of the Kotlin standard library can now be used from code compiled to JavaScript. In particular, key
classes such as collections (ArrayList, HashMap etc.), exceptions (IllegalArgumentException etc.) and a few others
(StringBuilder, Comparator) are now defined under the kotlin package. On the JVM, the names are type aliases for the
corresponding JDK classes, and on the JS, the classes are implemented in the Kotlin standard library.

Better
code
generation
JavaScript backend now generates more statically checkable code, which is friendlier to JS code processing tools, like
minifiers, optimisers, linters, etc.

The
external
modifier
If you need to access a class implemented in JavaScript from Kotlin in a typesafe way, you can write a Kotlin declaration
using the external modifier. (In Kotlin 1.0, the @native annotation was used instead.) Unlike the JVM target, the JS one
permits to use external modifier with classes and properties. For example, here's how you can declare the DOM Node
class:

external class Node {


val firstChild: Node

fun appendChild(child: Node): Node

fun removeChild(child: Node): Node

// etc
}

162
Improved
import
handling
You can now describe declarations which should be imported from JavaScript modules more precisely. If you add the
@JsModule("<module-name>") annotation on an external declaration it will be properly imported to a module system
(either CommonJS or AMD) during the compilation. For example, with CommonJS the declaration will be imported via
require(...) function. Additionally, if you want to import a declaration either as a module or as a global JavaScript object,
you can use the @JsNonModule annotation.

For example, here's how you can import JQuery into a Kotlin module:

external interface JQuery {


fun toggle(duration: Int = definedExternally): JQuery
fun click(handler: (Event) -> Unit): JQuery
}

@JsModule("jquery")
@JsNonModule
@JsName("$")
external fun jquery(selector: String): JQuery

In this case, JQuery will be imported as a module named jquery. Alternatively, it can be used as a $-object, depending on
what module system Kotlin compiler is configured to use.

You can use these declarations in your application like this:

fun main(args: Array<String>) {


jquery(".toggle-button").click {
jquery(".toggle-panel").toggle(300)
}
}

What's
new
in
Kotlin
for
KMM
KMM is part of the larger Kotlin ecosystem and leverages Kotlin features and improvements for a better mobile developer
experience. Every Kotlin release brings features and improvements that are helpful for mobile developers like you.

Android Studio will recommend an automatic update to a new Kotlin release. You can also update manually.

Here you can find a short summary of the features Kotlin provides for developing multiplatform mobile applications.

Kotlin
1.5.30
for
KMM
Kotlin 1.5.30 introduces a number of improvements and features that are helpful for KMM:

Apple silicon support. Kotlin 1.5.30 introduces native support for Apple silicon. Now the Kotlin/Native compiler and

163
tooling can run on Apple silicon hardware without Rosetta translation environment

Learn more about Apple silicon support.

Improved Kotlin DSL for CocoaPods Gradle plugin. Kotlin 1.5.30 introduces the improved CocoaPods Gradle plugin
DSL. In addition to the name of the framework, you can now specify other parameters in the pod configuration:

Dynamic or static version of the framework

Dependencies explicit export

Bitcode embedding

Custom names for Xcode configuration

Learn more about CocoaPods Gradle plugin improvements.

Experimental interoperability with Swift 5.5 async/await. The Kotlin/Native compiler now emits the _Nullable_result
attribute in the generated Objective-C headers for suspending functions with nullable return types. This makes it
possible to call them from Swift as async functions with the proper nullability.

Learn more about experimental interoperability with Swift 5.5 async/await.

Improved Swift/Objective-C mapping for objects and companion objects. Getting objects and companion objects can
now be done in a way that is more intuitive for native iOS developers.

Learn more about mapping for objects and companion objects.

Sharing custom cinterop libraries between platforms. Starting from Kotlin 1.5.30, you can use custom cinterop libraries
in shared native code.

Learn more about sharing custom cinterop libraries between platforms.

Support for XCFrameworks. Now all Kotlin Multiplatform projects can use XCFrameworks.

Learn more about support for XCFrameworks.

New default publishing setup for Android artifacts. Kotlin 1.5.30 brings new default publishing setup for Android
artefacts. You can publish your multiplatform library for the Android target by specifying Android variant names in the
build script. The Kotlin Gradle plugin will generate publications automatically.

Learn more about new default publishing setup for Android artifacts.

Kotlin
1.5.20
for
KMM
Kotlin 1.5.20 introduces a number of improvements and features that are helpful for KMM:

Export of KDoc comments to generated Objective-C headers. You can now set the Kotlin/Native compiler to export
the documentation comments (KDoc) from Kotlin code to the Objective-C frameworks generated from it, making them
visible to the frameworks’ consumers.

164
This feature is experimental. We would appreciate your feedback on it in YouTrack.

Learn more about exporting KDoc comments to generated Objective-C headers and how to opt in to this feature.

New framework-packing task for Kotlin/Native. The Kotlin Multiplatform Gradle plugin now includes the
embedAndSignAppleFrameworkForXcode task, which can be used from Xcode to connect KMM modules to the iOS
part of your project.

Check out this blog post to learn about the new framework-packing task and how to remove from the packForXcode
task from your build script.

Learn more about what's new in Kotlin 1.5.20.

Kotlin
1.5.0
for
KMM
Kotlin 1.5.0 introduces a number of improvements and features that are helpful for KMM:

Simplified test dependency selection for each platform. Now you can use the kotlin-test dependency to add
dependencies for testing in the commonTest source set. The Gradle plugin will infer the corresponding platform
dependencies for each test source set:

kotlin-test-junit for JVM source sets.

kotlin-test-common and kotlin-test-annotations-common for common source sets.

iOS source sets use Kotlin/Native, which has everything built in, so they do not require any additional artifacts.

You can also use the kotlin-test dependency in any shared or platform-specific source set. Learn more about setting
dependencies on test libraries.

New API for getting a char’s Unicode category. A variety of new character-related functions are available on all
platforms and in the common code. They include several functions for checking whether a char is a letter or a digit,
like Char.isLetterOrDigit(), as well as functions for checking the case of a char, like Char.isUpperCase(). The property
Char.category and the enum class CharCategory are available, as well.
Learn more about this new API.

Improved Kotlin/Native performance and stability. Kotlin/Native is receiving a set of performance improvements that
speed up both compilation and execution.
Learn more about the Kotlin/Native improvements.

Learn more about what's new in Kotlin 1.5.0.

Kotlin
1.4.30
for
KMM
Kotlin 1.4.30 introduces a number of improvements that are helpful for KMM:

Improved compilation time for an iOS simulator. Recompiling binaries for the iOS simulator after making changes in the
code now requires much less time. You can see the most significant improvements when re-running unit tests or

165
applications on the iOS simulator. For example, the time required to rebuild the framework in the KMM Networking and
data storage sample has decreased from 9.5 seconds (in 1.4.10) to 4.5 seconds (in 1.4.30).
These optimizations affect other scenarios as well.

Support for libraries delivered in Xcode 12.2.

Support for the new watchosX64 target in Kotlin/Native. This target makes it possible to run the simulator on 64-bit
architecture.

Learn more about what's new in Kotlin 1.4.30.

Kotlin
1.4.20
for
KMM
Kotlin 1.4.20 introduces a number of features, improvements, and bug fixes that are helpful for KMM:

CocoaPods plugin improvements:

Rebuilding dependencies only when necessary.

Ability to add dependencies on libraries from a custom spec repository, Git repository, or archive, as well as on
libraries with custom cinterop options.
Learn more about adding CocoaPods dependencies and these improvements.

Support for libraries delivered in Xcode 12.

Escape analysis for Kotlin/Native. A prototype of a new mechanism that gives a 10% iOS runtime performance
improvement by allocating certain objects on the stack instead of the heap.

Opt-in wrapping of Objective-C exceptions in runtime to avoid crashes. Learn how to opt in.

Updated structure of multiplatform library publications. The library root publication, which stands for the whole library,
now includes metadata artifacts. These were published separately in earlier Kotlin versions.
For compatibility, both multiplatform library authors and users must update to Kotlin 1.4.20. Learn more about
publishing a multiplatform library.

Deprecation of the Kotlin Android Extensions plugin. The Parcelable implementation generator has been moved to a
separate kotlin-parcelize plugin.

Learn more about what's new in Kotlin 1.4.20.

What's
new
in
Kotlin
plugin
2021.2
Enjoy improved performance, a better coroutines debugging experience, WSL 2 and Run Targets support, and more
improvements for Kotlin in IntelliJ IDEA 2021.2:

Performance improvements

Better debugging experience

166
Remote development support

Kotlin plugin in the IntelliJ IDEA repository

Other IDE improvements

Performance
improvements
IntelliJ IDEA 2021.2 brings some major performance improvements for Kotlin:

Faster test files analysis. Now you can run tests before code analysis finishes. The Run test icon appears in the gutter
as soon as you open the file and you can run your test immediately.

Run and debug your code before the IDE finishes indexing. The indexing process in the IDE and running code are now
autonomous from each other. You can run or debug the project right away without waiting for the IDE to finish its work.

Improved speed of rename refactoring. Rename refactoring for particular cases, like for fields with common names
name or id, became faster. Check out this YouTrack issue for more details.

Shared indexes for new Spring Boot projects. Shared indexes help you to prevent situations where you open a project
and need to wait for indexing to finish. In the previous version of IntelliJ IDEA you can download the JDK shared
indexes that save time during every project import. Now shared indexes are available for Spring Boot projects. Learn
more about how to download and use shared indexes in the IntelliJ IDEA documentation.

Better
debugging
experience
IntelliJ IDEA 2021.2 brings useful improvements and updates to the coroutine agent in the debugger:

Evaluate suspend functions

Now you can evaluate suspend function calls during the debugging process. You can put a breakpoint and evaluate
the suspend function:

import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

suspend fun longRunningFun(): Int {


delay(2000)
return 10
}

suspend fun fastFun(): Int {


delay(100)
return 32
}

fun main() = runBlocking {


val deferred = async { longRunningFun() }
// Put a breakpoint here and evaluate `the fastFun() + deferred.await()` expression:

167
val sum = deferred.await() + fastFun()
println(sum)
}

Look through these YouTrack tickets for more details: KT-27974, KT-31701.

Preserving variables after suspension points

Previously, when local variables were not used after passing a suspension point, you couldn’t see their values in
the Local Variable table. This helped avoid memory leaks, but as a side effect such variables disappeared in the
Variables view of the Debugger tool window.

Now you can see the values of such variables for common cases. IntelliJ IDEA also handles other specific cases
properly and notifies you when it is impossible to obtain the value.

For example, when you debug through the following code, the debugger shows the message that the x1, x2, x3
variables have been optimized out:

import kotlinx.coroutines.runBlocking

suspend fun foo() {

}
fun main() = runBlocking {
// Set a breakpoint here:
val x1 = 1
println(x1)
foo()
val x2 = 2
println(x2)
foo()
val x3 = 3
println(x3)
foo()
println()
}

Check out these YouTrack issues for more details: KTIJ-18499, KTIJ-18630.

Coroutines extension support in Java, Maven, and Spring run configurations

The coroutines agent is now available for Java, Maven, and Spring run configurations with a dependency on
kotlinx.coroutines.

Remote
development
support
Some popular remote-development scenarios are now available for Kotlin projects: WSL 2 (Windows Subsystem for
Linux) support and the Run Targets feature.
Run, debug, and test your code in different remote environments without leaving the IDE.

168
Kotlin
plugin
in
the
IntelliJ
IDEA
repository
The Kotlin plugin code has been moved to the IntelliJ IDEA repository. That means that every stable IDE release improves
your Kotlin experience and brings you more debugging, refactoring, and IDE-related features. To contribute to the Kotlin
plugin, clone the IntelliJ IDEA repository.

Since the Kotlin plugin and Kotlin have separate release cycles, this creates some limitations that are important to
emphasize:

The EAP version of Kotlin works only with the stable version of the IDE. That means that you can't install the Kotlin EAP
version to the EAP IDEA release.

The Kotlin plugin is based on the previous stable version of the Kotlin compiler. You can still update the Kotlin version
in your project, but some IDE-related features might not be available. We are working on stabilizing the process so that
the next versions of the plugin will be based on the latest stable version of the compiler.

Learn more about the EAP for Kotlin and IntelliJ IDEA.

Other
IDE
improvements
IntelliJ IDEA 2021.2 also brings more IDE features that improve the Kotlin experience:

Automatic ML code completion. Kotlin code completion works based on a machine learning mechanism by default.
Code suggestions are prioritized more carefully as IntelliJ IDEA considers the choices of thousands of real users in
similar situations. You can configure ML-assisted completion in Preferences/Settings | Editor | Code Completion.

Clickable inlay hints. Now you can click the type in the inlay hint and look through the declaration of the type, including
generics types. Just hold Cmd + click the type in the hint:

Clickable types in inlay hints

You can customize the inlay hints’ appearance in Preferences | Editor | Inlay hints | Kotlin.

Package Search integration. Package Search now works with build.gradle.kts files. This feature allows you to upgrade,
downgrade, and remove existing dependencies. You can use it to find new dependencies and add them automatically.
Package Search will add the required repositories to your build script if they’re missing.

169
Advanced settings. There is a new node Advanced Settings in the Preferences | Settings window. It contains some
use-case-specific options conveniently grouped by the IDE tool. For example, you can add a left margin in Distraction-
free mode, or set the maximum number of recent projects which are displayed in the File | Open Recent menu.

Quick access to Eclipse projects. IntelliJ IDEA detects existing Eclipse projects automatically and adds them to the
Welcome screen. To try this feature, select Open existing Eclipse projects on your first IDE launch.

See the What’s new in IntelliJ IDEA 2021.2 blog post to learn more about the platform enhancements.

What's
new
in
Kotlin
plugin
2021.1
This release aims to increase productivity and improve the development experience. Version 2021.1 of the Kotlin plugin
introduces the following major updates:

Performance improvements

Evaluation of custom getters during debugging

Improved Change Signature refactoring

Code completion for type arguments

UML diagrams for Kotlin classes

Other platform enhancements

You can also learn about new features in this blog post.

Performance
improvements
With 2021.1, the Kotlin plugin has received a number of performance improvements that speed up the development
process.

Here are some major refinements:

Faster syntax and error highlighting. The code highlighting API has been reworked, so you now get all the necessary
diagnostic information faster. See the benchmark results and share your feedback in this YouTrack issue.

Code completion speed improvements. The Kotlin plugin provides faster code completion. Check out this YouTrack
issue to see the benchmark results.

This version also introduces other improvements for code completion, particularly code completion for type
arguments.

Improved IDE responsiveness. We’ve fixed numerous issues based on your feedback, and we’ve improved the
overall stability of the plugin, as well as IDE responsiveness.

170
Evaluation
of
custom
getters
during
debugging
This release expands the capabilities of the debugger. One of the most notable features is the ability to display Kotlin
properties without a backing field in the Variables view.

Previously, during a debug session, you could only see the properties without a custom getter and those with a backing
field. Properties with a custom getter didn't appear because they are represented as regular methods on the JVM.
Starting with version 2021.1 of the Kotlin plugin, you can see all such properties and evaluate them on demand by clicking
on `get() near the property name.

For example, when debugging of the following code, you can execute the get() method to see the value:

class LanguageVersion(val major: Int, val minor: Int) {


val isStable: Boolean
get() = major <= 1 && minor <= 4
val isExperimental: Boolean
get() = !isStable
val versionString: String
get() = "$major.$minor"

override fun toString() = versionString
}

fun main() {
val version = LanguageVersion(1, 4)
}

In the Debug window, you can see the values of the properties:

Variables view

Improved
Change
Signature
refactoring
This release contains changes to the Change Signature refactoring. We’ve fixed more than 40 issues to make the
refactoring process better.

171
Here are some of the important improvements:

Support for warning messages for more refactoring cases.

Fixes to inheritance refactoring, including cross-language refactoring. See the YouTrack issue for details.* Improved
UX of properties processing.

Improved UX for processing properties.

Addition of a way to declare the default parameter value. See the YouTrack issue for details.

Correct backticks processing.

Code
completion
for
type
arguments
From now on, code completion will offer functions and properties after generic functions and will restore type arguments
where needed. When you select such a function from the list, the IDE adds the correct type argument to the preceding
code.

In the following example, there is a list of strings to be reversed:

fun typeArgumentsAtCodeCompletion() {
// Function definition from stdlib:
// public fun <T> emptyList(): List<T>

val list: List<String> = emptyList() // T is inferred from the context (explicit variable
type)
}

To reverse this list, start typing the name of the reversed() function:

Now code completion suggests functions

After you apply the code completion suggestion, the IDE automatically adds the <String> type:

fun typeArgumentsAtCodeCompletion() {
// Function definition from stdlib:
// public fun <T> emptyList(): List<T>

val list: List<String> = emptyList<String>().reversed()

172
}

The type argument for emptyList() is required to evaluate the expression type. Otherwise, the code will not compile.

UML
diagrams
for
Kotlin
classes
With this release, you can test Kotlin code visualization via UML Class diagrams. To build a diagram, select Diagrams |
Show Diagram... | Kotlin Classes in the Project View.

UML diagram for Kotlin classes

Currently, the diagrams only show inheritance and nesting relationships. All other more detailed association connections,
like aggregation, composition, dependency, and others will be available in the future releases.

Other
platform
enhancements
Since the plugin and the platform have been moved to the same codebase and now ship simultaneously, this release also
brings the following features that improve the Kotlin experience:

You can now launch the basic memory profiler that was announced in the IntelliJ IDEA 2020.3 release via Gradle run.

173
To improve the experience of working with coroutines, this release provides better thread-blocking call detection. The
inspection now correctly warns you about inappropriate blocking method calls.

We’ve fixed some of the language injection issues that received the most votes. Language injection now works
correctly for the following cases:
When you use triple quotes to inject multi-line strings and add the .trimIndent(), or .trimMargin() functions at the end.
See the YouTrack issue for details.

When you concatenate strings. See the YouTrack issue for details.

What's
new
in
Kotlin
plugin
2020.3
This plugin release introduces the following features:

New types of inline refactorings

Structural search and replace

EditorConfig support

Project templates for Jetpack Compose for Desktop

New
types
of
inline
refactorings
Cross-language conversion is possible starting with version 2020.3 of the Kotlin plugin. You can now use the inline
refactoring actions for Kotlin elements defined in Java.

The Kotlin plugin can inline code from libraries with attached sources. That means you can inline refactor all the Kotlin
scope functions: also, let, run, apply, and with.

Also, this release brings refactoring improvements for lambda expressions. Now the IDE analyzes their syntax more
thoroughly and formats them correctly.

Structural
search
and
replace
Structural search and replace (SSR) actions are now available for Kotlin. The SSR feature allows you to find and replace
code patterns, taking the syntax and semantics of the source code into account.

To start using the feature, open the Structural Search dialog for your .kt file and select one of the templates or create your
own.

EditorConfig
support
From 2020.3, the Kotlin API has the full support of .editorconfig files for managing code style on a directory level.

174
Project
templates
for
Jetpack
Compose
for
Desktop
The new experimental Jetpack Compose for Desktop templates are now available in the Kotlin Project Wizard. You can
create a project using the following templates:

Desktop – a Compose project targeting the desktop JVM platform: Windows, Linux, or macOS.

Multiplatform – a Multiplatform Compose project targeting the desktop JVM platform (Windows, Linux, macOS) and
Android with shared code in common modules.

Kotlin Project Wizard – Jetpack Compose project

To create a project, select one of the templates while creating a new project and specify the Gradle build system. The
Kotlin plugin creates all the configuration files automatically. You can try out this experimental feature by working through
Getting Started with Compose for Desktop tutorial.

Read more about Jetpack Compose features in this blog post and look through the examples of Compose applications.

Basic
syntax
This is a collection of basic syntax elements with examples. At the end of every section, you'll find a link to a detailed
description of the related topic.

You can also learn all the Kotlin essentials with the free Kotlin Basics track on JetBrains Academy.

175
Package
definition
and
imports
Package specification should be at the top of the source file.

package my.demo

import kotlin.text.*

// ...

It is not required to match directories and packages: source files can be placed arbitrarily in the file system.

See Packages.

Program
entry
point
An entry point of a Kotlin application is the main function.

fun main() {
println("Hello world!")
}

Another form of main accepts a variable number of String arguments.

fun main(args: Array<String>) {


println(args.contentToString())
}

Print
to
the
standard
output
print prints its argument to the standard output.

fun main() {
//sampleStart
print("Hello ")
print("world!")
//sampleEnd
}

println prints its arguments and adds a line break, so that the next thing you print appears on the next line.

fun main() {
//sampleStart
println("Hello world!")
println(42)
//sampleEnd
}

176
Functions
A function with two Int parameters and Int return type.

//sampleStart
fun sum(a: Int, b: Int): Int {
return a + b
}
//sampleEnd

fun main() {
print("sum of 3 and 5 is ")
println(sum(3, 5))
}

A function body can be an expression. Its return type is inferred.

//sampleStart
fun sum(a: Int, b: Int) = a + b
//sampleEnd

fun main() {
println("sum of 19 and 23 is ${sum(19, 23)}")
}

A function that returns no meaningful value.

//sampleStart
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
//sampleEnd

fun main() {
printSum(-1, 8)
}

Unit return type can be omitted.

//sampleStart
fun printSum(a: Int, b: Int) {
println("sum of $a and $b is ${a + b}")
}
//sampleEnd

fun main() {
printSum(-1, 8)
}

177
See Functions.

Variables
Read-only local variables are defined using the keyword val. They can be assigned a value only once.

fun main() {
//sampleStart
val a: Int = 1 // immediate assignment
val b = 2 // `Int` type is inferred
val c: Int // Type required when no initializer is provided
c = 3 // deferred assignment
//sampleEnd
println("a = $a, b = $b, c = $c")
}

Variables that can be reassigned use the var keyword.

fun main() {
//sampleStart
var x = 5 // `Int` type is inferred
x += 1
//sampleEnd
println("x = $x")
}

You can declare variables at the top level.

//sampleStart
val PI = 3.14
var x = 0

fun incrementX() {
x += 1
}
//sampleEnd

fun main() {
println("x = $x; PI = $PI")
incrementX()
println("incrementX()")
println("x = $x; PI = $PI")
}

See also Properties.

Creating
classes
and
instances
To define a class, use the class keyword.

178
class Shape

Properties of a class can be listed in its declaration or body.

class Rectangle(var height: Double, var length: Double) {


var perimeter = (height + length) * 2
}

The default constructor with parameters listed in the class declaration is available automatically.

class Rectangle(var height: Double, var length: Double) {


var perimeter = (height + length) * 2
}
fun main() {
//sampleStart
val rectangle = Rectangle(5.0, 2.0)
println("The perimeter is ${rectangle.perimeter}")
//sampleEnd
}

Inheritance between classes is declared by a colon (:). Classes are final by default; to make a class inheritable, mark it as
open.

open class Shape

class Rectangle(var height: Double, var length: Double): Shape() {


var perimeter = (height + length) * 2
}

See classes and objects and instances.

Comments
Just like most modern languages, Kotlin supports single-line (or end-of-line) and multi-line (block) comments.

// This is an end-of-line comment

/* This is a block comment


on multiple lines. */

Block comments in Kotlin can be nested.

/* The comment starts here


/* contains a nested comment *â​ /
and ends here. */

See Documenting Kotlin Code for information on the documentation comment syntax.

179
String
templates

fun main() {
//sampleStart
var a = 1
// simple name in template:
val s1 = "a is $a"

a = 2
// arbitrary expression in template:
val s2 = "${s1.replace("is", "was")}, but now is $a"
//sampleEnd
println(s2)
}

See String templates for details.

Conditional
expressions

//sampleStart
fun maxOf(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
//sampleEnd

fun main() {
println("max of 0 and 42 is ${maxOf(0, 42)}")
}

In Kotlin, if can also be used as an expression.

//sampleStart
fun maxOf(a: Int, b: Int) = if (a > b) a else b
//sampleEnd

fun main() {
println("max of 0 and 42 is ${maxOf(0, 42)}")
}

See if -expressions.

for
loop

fun main() {
//sampleStart

180
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}
//sampleEnd
}

or

fun main() {
//sampleStart
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
//sampleEnd
}

See for loop.

while
loop

fun main() {
//sampleStart
val items = listOf("apple", "banana", "kiwifruit")
var index = 0
while (index < items.size) {
println("item at $index is ${items[index]}")
index++
}
//sampleEnd
}

See while loop.

when
expression

//sampleStart
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
//sampleEnd

fun main() {
println(describe(1))
println(describe("Hello"))

181
println(describe(1000L))
println(describe(2))
println(describe("other"))
}

See when expression.

Ranges
Check if a number is within a range using in operator.

fun main() {
//sampleStart
val x = 10
val y = 9
if (x in 1..y+1) {
println("fits in range")
}
//sampleEnd
}

Check if a number is out of range.

fun main() {
//sampleStart
val list = listOf("a", "b", "c")

if (-1 !in 0..list.lastIndex) {
println("-1 is out of range")
}
if (list.size !in list.indices) {
println("list size is out of valid list indices range, too")
}
//sampleEnd
}

Iterate over a range.

fun main() {
//sampleStart
for (x in 1..5) {
print(x)
}
//sampleEnd
}

Or over a progression.

fun main() {
//sampleStart
for (x in 1..10 step 2) {

182
print(x)
}
println()
for (x in 9 downTo 0 step 3) {
print(x)
}
//sampleEnd
}

See Ranges and progressions.

Collections
Iterate over a collection.

fun main() {
val items = listOf("apple", "banana", "kiwifruit")
//sampleStart
for (item in items) {
println(item)
}
//sampleEnd
}

Check if a collection contains an object using in operator.

fun main() {
val items = setOf("apple", "banana", "kiwifruit")
//sampleStart
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
//sampleEnd
}

Using lambda expressions to filter and map collections:

fun main() {
//sampleStart
val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.uppercase() }
.forEach { println(it) }
//sampleEnd
}

See Collections overview.

183
Nullable
values
and
null
checks
A reference must be explicitly marked as nullable when null value is possible. Nullable type names have ? at the end.

Return null if str does not hold an integer:

fun parseInt(str: String): Int? {


// ...
}

Use a function returning nullable value:

fun parseInt(str: String): Int? {


return str.toIntOrNull()
}

//sampleStart
fun printProduct(arg1: String, arg2: String) {
val x = parseInt(arg1)
val y = parseInt(arg2)

// Using `x * y` yields error because they may hold nulls.


if (x != null && y != null) {
// x and y are automatically cast to non-nullable after null check
println(x * y)
}
else {
println("'$arg1' or '$arg2' is not a number")
}
}
//sampleEnd

fun main() {
printProduct("6", "7")
printProduct("a", "7")
printProduct("a", "b")
}

or

fun parseInt(str: String): Int? {


return str.toIntOrNull()
}

fun printProduct(arg1: String, arg2: String) {


val x = parseInt(arg1)
val y = parseInt(arg2)

//sampleStart
// ...
if (x == null) {
println("Wrong number format in arg1: '$arg1'")
return
}
if (y == null) {

184
println("Wrong number format in arg2: '$arg2'")
return
}

// x and y are automatically cast to non-nullable after null check


println(x * y)
//sampleEnd
}

fun main() {
printProduct("6", "7")
printProduct("a", "7")
printProduct("99", "b")
}

See Null-safety.

Type
checks
and
automatic
casts
The is operator checks if an expression is an instance of a type. If an immutable local variable or property is checked for a
specific type, there's no need to cast it explicitly:

//sampleStart
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// `obj` is automatically cast to `String` in this branch
return obj.length
}

// `obj` is still of type `Any` outside of the type-checked branch


return null
}
//sampleEnd

fun main() {
fun printLength(obj: Any) {
println("Getting the length of '$obj'. Result: ${getStringLength(obj) ?: "Error: The
object is not a string"} ")
}
printLength("Incomprehensibilities")
printLength(1000)
printLength(listOf(Any()))
}

or

//sampleStart
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null

// `obj` is automatically cast to `String` in this branch


return obj.length
}
//sampleEnd

185
fun main() {
fun printLength(obj: Any) {
println("Getting the length of '$obj'. Result: ${getStringLength(obj) ?: "Error: The
object is not a string"} ")
}
printLength("Incomprehensibilities")
printLength(1000)
printLength(listOf(Any()))
}

or even

//sampleStart
fun getStringLength(obj: Any): Int? {
// `obj` is automatically cast to `String` on the right-hand side of `&&`
if (obj is String && obj.length > 0) {
return obj.length
}

return null
}
//sampleEnd

fun main() {
fun printLength(obj: Any) {
println("Getting the length of '$obj'. Result: ${getStringLength(obj) ?: "Error: The
object is not a string"} ")
}
printLength("Incomprehensibilities")
printLength("")
printLength(1000)
}

See Classes and Type casts.

Idioms
A collection of random and frequently used idioms in Kotlin. If you have a favorite idiom, contribute it by sending a pull
request.

Create
DTOs
(POJOs/POCOs)

data class Customer(val name: String, val email: String)

provides a Customer class with the following functionality:

getters (and setters in case of var s) for all properties

equals()

186
hashCode()

toString()

copy()

component1(), component2(), ..., for all properties (see Data classes)

Default
values
for
function
parameters

fun foo(a: Int = 0, b: String = "") { ... }

Filter
a
list

val positives = list.filter { x -> x > 0 }

Or alternatively, even shorter:

val positives = list.filter { it > 0 }

Learn the difference between Java and Kotlin filtering.

Check
the
presence
of
an
element
in
a
collection

if ("[email protected]" in emailsList) { ... }

if ("[email protected]" !in emailsList) { ... }

String
interpolation

println("Name $name")

Learn the difference between Java and Kotlin string concatenation.

Instance
checks

when (x) {

187
is Foo -> ...
is Bar -> ...
else -> ...
}

Read-only
list

val list = listOf("a", "b", "c")

Read-only
map

val map = mapOf("a" to 1, "b" to 2, "c" to 3)

Access
a
map
entry

println(map["key"])
map["key"] = value

Traverse
a
map
or
a
list
of
pairs

for ((k, v) in map) {


println("$k -> $v")
}

k and v can be any convenient names, such as name and age.

Iterate
over
a
range

for (i in 1..100) { ... } // closed range: includes 100


for (i in 1 until 100) { ... } // half-open range: does not include 100
for (x in 2..10 step 2) { ... }
for (x in 10 downTo 1) { ... }
if (x in 1..10) { ... }

Lazy
property

188
val p: String by lazy {
// compute the string
}

Extension
functions

fun String.spaceToCamelCase() { ... }

"Convert this to camelcase".spaceToCamelCase()

Create
a
singleton

object Resource {
val name = "Name"
}

Instantiate
an
abstract
class

abstract class MyAbstractClass {


abstract fun doSomething()
abstract fun sleep()
}

fun main() {
val myObject = object : MyAbstractClass() {
override fun doSomething() {
// ...
}

override fun sleep() { // ...


}
}
myObject.doSomething()
}

If-not-null
shorthand

val files = File("Test").listFiles()

println(files?.size) // size is printed if files is not null

189
If-not-null-else
shorthand

val files = File("Test").listFiles()

println(files?.size ?: "empty") // if files is null, this prints "empty"

Execute
a
statement
if
null

val values = ...


val email = values["email"] ?: throw IllegalStateException("Email is missing!")

Get
first
item
of
a
possibly
empty
collection

val emails = ... // might be empty


val mainEmail = emails.firstOrNull() ?: ""

Execute
if
not
null

val value = ...

value?.let {
... // execute this block if not null
}

Map
nullable
value
if
not
null

val value = ...

val mapped = value?.let { transformValue(it) } ?: defaultValue


// defaultValue is returned if the value or the transform result is null.

Return
on
when
statement

fun transform(color: String): Int {


return when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")

190
}
}

try-catch
expression

fun test() {
val result = try {
count()
} catch (e: ArithmeticException) {
throw IllegalStateException(e)
}

// Working with result


}

if
expression

fun foo(param: Int) {


val result = if (param == 1) {
"one"
} else if (param == 2) {
"two"
} else {
"three"
}
}

Builder-style
usage
of
methods
that
return
Unit

fun arrayOfMinusOnes(size: Int): IntArray {


return IntArray(size).apply { fill(-1) }
}

Single-expression
functions

fun theAnswer() = 42

This is equivalent to

fun theAnswer(): Int {


return 42
}

191
This can be effectively combined with other idioms, leading to shorter code. For example, with the when expression:

fun transform(color: String): Int = when (color) {


"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")
}

Call
multiple
methods
on
an
object
instance
(with)

class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}

val myTurtle = Turtle()


with(myTurtle) { //draw a 100 pix square
penDown()
for (i in 1..4) {
forward(100.0)
turn(90.0)
}
penUp()
}

Configure
properties
of
an
object
(apply)

val myRectangle = Rectangle().apply {


length = 4
breadth = 5
color = 0xFAFAFA
}

This is useful for configuring properties that aren't present in the object constructor.

Java
7's
try-with-resources

val stream = Files.newInputStream(Paths.get("/some/file.txt"))


stream.buffered().reader().use { reader ->
println(reader.readText())
}

192
Generic
function
that
requires
the
generic
type
information

// public final class Gson {


// ...
// public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
// ...

inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json,


T::class.java)

Nullable
Boolean

val b: Boolean? = ...


if (b == true) {
...
} else {
// `b` is false or null
}

Swap
two
variables

var a = 1
var b = 2
a = b.also { b = a }

Mark
code
as
incomplete
(TODO)
Kotlin's standard library has a TODO() function that will always throw a NotImplementedError. Its return type is Nothing so
it can be used regardless of expected type. There's also an overload that accepts a reason parameter:

fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")

IntelliJ IDEA's kotlin plugin understands the semantics of TODO() and automatically adds a code pointer in the TODO tool
window.

What’s
next?
Learn how to perform typical tasks with strings in Java and Kotlin.

193
Coding
conventions
Commonly known and easy-to-follow coding conventions are vital for any programming language. Here we provide
guidelines on the code style and code organization for projects that use Kotlin.

Configure
style
in
IDE
Two most popular IDEs for Kotlin - IntelliJ IDEA and Android Studio provide powerful support for code styling. You can
configure them to automatically format your code in consistence with the given code style.

Apply
the
style
guide
1. Go to Settings | Editor | Code Style | Kotlin.

2. Click Set from....

3. Select Kotlin style guide.

Verify
that
your
code
follows
the
style
guide
1. Go to Settings | Editor | Inspections | Kotlin.

2. Open Kotlin | Style issues.

3. Switch on File is not formatted according to project settings inspection. Additional inspections that verify other issues
described in the style guide (such as naming conventions) are enabled by default.

Source
code
organization

Directory
structure
In pure Kotlin projects, the recommended directory structure follows the package structure with the common root
package omitted. For example, if all the code in the project is in the org.example.kotlin package and its subpackages, files
with the org.example.kotlin package should be placed directly under the source root, and files in
org.example.kotlin.network.socket should be in the network/socket subdirectory of the source root.

On JVM: In projects where Kotlin is used together with Java, Kotlin source files should reside in the same
source root as the Java source files, and follow the same directory structure: each file should be stored in the
directory corresponding to each package statement.

Source
file
names

194
If a Kotlin file contains a single class (potentially with related top-level declarations), its name should be the same as the
name of the class, with the .kt extension appended. If a file contains multiple classes, or only top-level declarations,
choose a name describing what the file contains, and name the file accordingly. Use upper camel case with an uppercase
first letter (also known as Pascal case), for example, ProcessDeclarations.kt.

The name of the file should describe what the code in the file does. Therefore, you should avoid using meaningless words
such as Util in file names.

Source
file
organization
Placing multiple declarations (classes, top-level functions or properties) in the same Kotlin source file is encouraged as
long as these declarations are closely related to each other semantically, and the file size remains reasonable (not
exceeding a few hundred lines).

In particular, when defining extension functions for a class which are relevant for all clients of this class, put them in the
same file with the class itself. When defining extension functions that make sense only for a specific client, put them next
to the code of that client. Avoid creating files just to hold all extensions of some class.

Class
layout
The contents of a class should go in the following order:

1. Property declarations and initializer blocks

2. Secondary constructors

3. Method declarations

4. Companion object

Do not sort the method declarations alphabetically or by visibility, and do not separate regular methods from extension
methods. Instead, put related stuff together, so that someone reading the class from top to bottom can follow the logic of
what's happening. Choose an order (either higher-level stuff first, or vice versa) and stick to it.

Put nested classes next to the code that uses those classes. If the classes are intended to be used externally and aren't
referenced inside the class, put them in the end, after the companion object.

Interface
implementation
layout
When implementing an interface, keep the implementing members in the same order as members of the interface (if
necessary, interspersed with additional private methods used for the implementation).

Overload
layout
Always put overloads next to each other in a class.

Naming
rules

195
Package and class naming rules in Kotlin are quite simple:

Names of packages are always lowercase and do not use underscores (org.example.project). Using multi-word names
is generally discouraged, but if you do need to use multiple words, you can either just concatenate them together or
use camel case (org.example.myProject).

Names of classes and objects start with an uppercase letter and use camel case:

open class DeclarationProcessor { /*...*/ }

object EmptyDeclarationProcessor : DeclarationProcessor() { /*...*/ }

Function
names
Names of functions, properties and local variables start with a lowercase letter and use camel case and no underscores:

fun processDeclarations() { /*...*/ }


var declarationCount = 1

Exception: factory functions used to create instances of classes can have the same name as the abstract return type:

interface Foo { /*...*/ }

class FooImpl : Foo { /*...*/ }

fun Foo(): Foo { return FooImpl() }

Names
for
test
methods
In tests (and only in tests), you can use method names with spaces enclosed in backticks. Note that such method names
are currently not supported by the Android runtime. Underscores in method names are also allowed in test code.

class MyTestCase {
@Test fun `ensure everything works`() { /*...*/ }

@Test fun ensureEverythingWorks_onAndroid() { /*...*/ }
}

Property
names
Names of constants (properties marked with const, or top-level or object val properties with no custom get function that
hold deeply immutable data) should use uppercase underscore-separated (screaming snake case) names:

const val MAX_COUNT = 8


val USER_NAME_FIELD = "UserName"

196
Names of top-level or object properties which hold objects with behavior or mutable data should use camel case names:

val mutableCollection: MutableSet<String> = HashSet()

Names of properties holding references to singleton objects can use the same naming style as object declarations:

val PersonComparator: Comparator<Person> = /*...*/

For enum constants, it's OK to use either uppercase underscore-separated names ( screaming snake case) (enum class
Color { RED, GREEN }) or upper camel case names, depending on the usage.

Names
for
backing
properties
If a class has two properties which are conceptually the same but one is part of a public API and another is an
implementation detail, use an underscore as the prefix for the name of the private property:

class C {
private val _elementList = mutableListOf<Element>()

val elementList: List<Element>


get() = _elementList
}

Choose
good
names
The name of a class is usually a noun or a noun phrase explaining what the class is: List, PersonReader.

The name of a method is usually a verb or a verb phrase saying what the method does: close, readPersons. The name
should also suggest if the method is mutating the object or returning a new one. For instance sort is sorting a collection in
place, while sorted is returning a sorted copy of the collection.

The names should make it clear what the purpose of the entity is, so it's best to avoid using meaningless words
(Manager, Wrapper) in names.

When using an acronym as part of a declaration name, capitalize it if it consists of two letters ( IOStream); capitalize only
the first letter if it is longer (XmlFormatter, HttpInputStream).

Formatting

Indentation
Use four spaces for indentation. Do not use tabs.

For curly braces, put the opening brace in the end of the line where the construct begins, and the closing brace on a
separate line aligned horizontally with the opening construct.

197
if (elements != null) {
for (element in elements) {
// ...
}
}

In Kotlin, semicolons are optional, and therefore line breaks are significant. The language design assumes Java-
style braces, and you may encounter surprising behavior if you try to use a different formatting style.

Horizontal
whitespace
Put spaces around binary operators (a + b). Exception: don't put spaces around the "range to" operator (0..i).

Do not put spaces around unary operators (a++).

Put spaces between control flow keywords (if, when, for, and while) and the corresponding opening parenthesis.

Do not put a space before an opening parenthesis in a primary constructor declaration, method declaration or method
call.

class A(val x: Int)

fun foo(x: Int) { ... }

fun bar() {
foo(1)
}

Never put a space after (, [, or before ], )

Never put a space around . or ?.: foo.bar().filter { it > 2 }.joinToString(), foo?.bar()

Put a space after //: // This is a comment

Do not put spaces around angle brackets used to specify type parameters: class Map<K, V> { ... }

Do not put spaces around ::: Foo::class, String::length

Do not put a space before ? used to mark a nullable type: String?

As a general rule, avoid horizontal alignment of any kind. Renaming an identifier to a name with a different length should
not affect the formatting of either the declaration or any of the usages.

Colon
Put a space before : in the following cases:

when it's used to separate a type and a supertype

198
when delegating to a superclass constructor or a different constructor of the same class

after the object keyword

Don't put a space before : when it separates a declaration and its type.

Always put a space after :.

abstract class Foo<out T : Any> : IFoo {


abstract fun foo(a: Int): T
}

class FooImpl : Foo() {


constructor(x: String) : this(x) { /*...*/ }

val x = object : IFoo { /*...*/ }
}

Class
headers
Classes with a few primary constructor parameters can be written in a single line:

class Person(id: Int, name: String)

Classes with longer headers should be formatted so that each primary constructor parameter is in a separate line with
indentation. Also, the closing parenthesis should be on a new line. If you use inheritance, the superclass constructor call
or the list of implemented interfaces should be located on the same line as the parenthesis:

class Person(
id: Int,
name: String,
surname: String
) : Human(id, name) { /*...*/ }

For multiple interfaces, the superclass constructor call should be located first and then each interface should be located
in a different line:

class Person(
id: Int,
name: String,
surname: String
) : Human(id, name),
KotlinMaker { /*...*/ }

For classes with a long supertype list, put a line break after the colon and align all supertype names horizontally:

class MyFavouriteVeryLongClassHolder :
MyLongHolder<MyFavouriteVeryLongClass>(),
SomeOtherInterface,
AndAnotherOne {

199
fun foo() { /*...*/ }
}

To clearly separate the class header and body when the class header is long, either put a blank line following the class
header (as in the example above), or put the opening curly brace on a separate line:

class MyFavouriteVeryLongClassHolder :
MyLongHolder<MyFavouriteVeryLongClass>(),
SomeOtherInterface,
AndAnotherOne
{
fun foo() { /*...*/ }
}

Use regular indent (four spaces) for constructor parameters. This ensures that properties declared in the primary
constructor have the same indentation as properties declared in the body of a class.

Modifiers
order
If a declaration has multiple modifiers, always put them in the following order:

public / protected / private / internal


expect / actual
final / open / abstract / sealed / const
external
override
lateinit
tailrec
vararg
suspend
inner
enum / annotation / fun // as a modifier in `fun interface`
companion
inline / value
infix
operator
data

Place all annotations before modifiers:

@Named("Foo")
private val foo: Foo

Unless you're working on a library, omit redundant modifiers (for example, public).

Annotations
Place annotations on separate lines before the declaration to which they are attached, and with the same indentation:

200
@Target(AnnotationTarget.PROPERTY)
annotation class JsonExclude

Annotations without arguments may be placed on the same line:

@JsonExclude @JvmField
var x: String

A single annotation without arguments may be placed on the same line as the corresponding declaration:

@Test fun foo() { /*...*/ }

File
annotations
File annotations are placed after the file comment (if any), before the package statement, and are separated from package
with a blank line (to emphasize the fact that they target the file and not the package).

/** License, copyright and whatever */


@file:JvmName("FooBar")

package foo.bar

Functions
If the function signature doesn't fit on a single line, use the following syntax:

fun longMethodName(
argument: ArgumentType = defaultValue,
argument2: AnotherArgumentType,
): ReturnType {
// body
}

Use regular indent (four spaces) for function parameters. It helps ensure consistency with constructor parameters.

Prefer using an expression body for functions with the body consisting of a single expression.

fun foo(): Int { // bad


return 1
}

fun foo() = 1 // good

Expression
bodies
If the function has an expression body whose first line doesn't fit on the same line as the declaration, put the = sign on the

201
first line and indent the expression body by four spaces.

fun f(x: String, y: String, z: String) =


veryLongFunctionCallWithManyWords(andLongParametersToo(), x, y, z)

Properties
For very simple read-only properties, consider one-line formatting:

val isEmpty: Boolean get() = size == 0

For more complex properties, always put get and set keywords on separate lines:

val foo: String


get() { /*...*/ }

For properties with an initializer, if the initializer is long, add a line break after the = sign and indent the initializer by four
spaces:

private val defaultCharset: Charset? =


EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file)

Control
flow
statements
If the condition of an if or when statement is multiline, always use curly braces around the body of the statement. Indent
each subsequent line of the condition by four spaces relative to statement begin. Put the closing parentheses of the
condition together with the opening curly brace on a separate line:

if (!component.isSyncing &&
!hasAnyKotlinRuntimeInScope(module)
) {
return createKotlinNotConfiguredPanel(module)
}

This helps align the condition and statement bodies.

Put the else, catch, finally keywords, as well as the while keyword of a do-while loop, on the same line as the preceding
curly brace:

if (condition) {
// body
} else {
// else part
}

try {
// body

202
} finally {
// cleanup
}

In a when statement, if a branch is more than a single line, consider separating it from adjacent case blocks with a blank
line:

private fun parsePropertyValue(propName: String, token: Token) {


when (token) {
is Token.ValueToken ->
callback.visitValue(propName, token.value)

Token.LBRACE -> { // ...


}
}
}

Put short branches on the same line as the condition, without braces.

when (foo) {
true -> bar() // good
false -> { baz() } // bad
}

Method
calls
In long argument lists, put a line break after the opening parenthesis. Indent arguments by four spaces. Group multiple
closely related arguments on the same line.

drawSquare(
x = 10, y = 10,
width = 100, height = 100,
fill = true
)

Put spaces around the = sign separating the argument name and value.

Wrap
chained
calls
When wrapping chained calls, put the . character or the ?. operator on the next line, with a single indent:

val anchor = owner


?.firstChild!!
.siblings(forward = true)
.dropWhile { it is PsiComment || it is PsiWhiteSpace }

The first call in the chain usually should have a line break before it, but it's OK to omit it if the code makes more sense that
way.

203
Lambdas
In lambda expressions, spaces should be used around the curly braces, as well as around the arrow which separates the
parameters from the body. If a call takes a single lambda, pass it outside of parentheses whenever possible.

list.filter { it > 10 }

If assigning a label for a lambda, do not put a space between the label and the opening curly brace:

fun foo() {
ints.forEach lit@{
// ...
}
}

When declaring parameter names in a multiline lambda, put the names on the first line, followed by the arrow and the
newline:

appendCommaSeparated(properties) { prop ->


val propertyValue = prop.get(obj) // ...
}

If the parameter list is too long to fit on a line, put the arrow on a separate line:

foo {
context: Context,
environment: Env
->
context.configureEnv(environment)
}

Trailing
commas
A trailing comma is a comma symbol after the last item of a series of elements:

class Person(
val firstName: String,
val lastName: String,
val age: Int, // trailing comma
)

Using trailing commas has several benefits:

It makes version-control diffs cleaner – as all the focus is on the changed value.

It makes it easy to add and reorder elements – there is no need to add or delete the comma if you manipulate
elements.

It simplifies code generation, for example, for object initializers. The last element can also have a comma.

204
Trailing commas are entirely optional – your code will still work without them. The Kotlin style guide encourages the use
of trailing commas at the declaration site and leaves it at your discretion for the call site.

To enable trailing commas in the IntelliJ IDEA formatter, go to Settings | Editor | Code Style | Kotlin, open the Other tab
and select the Use trailing comma option.

Enumerations

enum class Direction {


NORTH,
SOUTH,
WEST,
EAST, // trailing comma
}

Value arguments

fun shift(x: Int, y: Int) { /*...*/ }


shift(
25,
20, // trailing comma
)
val colors = listOf(
"red",
"green",
"blue", // trailing comma
)

Class properties and parameters

class Customer(
val name: String,
val lastName: String, // trailing comma
)
class Customer(
val name: String,
lastName: String, // trailing comma
)

Function value parameters

fun powerOf(
number: Int,
exponent: Int, // trailing comma
) { /*...*/ }
constructor(
x: Comparable<Number>,
y: Iterable<Number>, // trailing comma

205
) {}
fun print(
vararg quantity: Int,
description: String, // trailing comma
) {}

Parameters with optional type (including setters)

val sum: (Int, Int, Int) -> Int = fun(


x,
y,
z, // trailing comma
): Int {
return x + y + x
}
println(sum(8, 8, 8))

Indexing suffix

class Surface {
operator fun get(x: Int, y: Int) = 2 * x + 4 * y - 10
}
fun getZValue(mySurface: Surface, xValue: Int, yValue: Int) =
mySurface[
xValue,
yValue, // trailing comma
]

Parameters in lambdas

fun main() {
val x = {
x: Comparable<Number>,
y: Iterable<Number>, // trailing comma
->
println("1")
}
println(x)
}

when entry

fun isReferenceApplicable(myReference: KClass<*>) = when (myReference) {


Comparable::class,
Iterable::class,
String::class, // trailing comma
-> true
else -> false

206
}

Collection literals (in annotations)

annotation class ApplicableFor(val services: Array<String>)


@ApplicableFor([
"serializer",
"balancer",
"database",
"inMemoryCache", // trailing comma
])
fun run() {}

Type arguments

fun <T1, T2> foo() {}


fun main() {
foo<
Comparable<Number>,
Iterable<Number>, // trailing comma
>()
}

Type parameters

class MyMap<
MyKey,
MyValue, // trailing comma
> {}

Destructuring declarations

data class Car(val manufacturer: String, val model: String, val year: Int)
val myCar = Car("Tesla", "Y", 2019)
val (
manufacturer,
model,
year, // trailing comma
) = myCar
val cars = listOf<Car>()
fun printMeanValue() {
var meanValue: Int = 0
for ((
_,
_,
year, // trailing comma
) in cars) {
meanValue += year

207
}
println(meanValue/cars.size)
}
printMeanValue()

Documentation
comments
For longer documentation comments, place the opening /** on a separate line and begin each subsequent line with an
asterisk:

/**
* This is a documentation comment
* on multiple lines.
*/

Short comments can be placed on a single line:

/** This is a short documentation comment. */

Generally, avoid using @param and @return tags. Instead, incorporate the description of parameters and return values
directly into the documentation comment, and add links to parameters wherever they are mentioned. Use @param and
@return only when a lengthy description is required which doesn't fit into the flow of the main text.

// Avoid doing this:

/**
* Returns the absolute value of the given number.
* @param number The number to return the absolute value for.
* @return The absolute value.
*/
fun abs(number: Int) { /*...*/ }

// Do this instead:

/**
* Returns the absolute value of the given [number].
*/
fun abs(number: Int) { /*...*/ }

Avoid
redundant
constructs
In general, if a certain syntactic construction in Kotlin is optional and highlighted by the IDE as redundant, you should omit
it in your code. Do not leave unnecessary syntactic elements in code just "for clarity".

Unit
return
type
If a function returns Unit, the return type should be omitted:

208
fun foo() { // ": Unit" is omitted here

Semicolons
Omit semicolons whenever possible.

String
templates
Don't use curly braces when inserting a simple variable into a string template. Use curly braces only for longer
expressions.

println("$name has ${children.size} children")

Idiomatic
use
of
language
features

Immutability
Prefer using immutable data to mutable. Always declare local variables and properties as val rather than var if they are not
modified after initialization.

Always use immutable collection interfaces (Collection, List, Set, Map) to declare collections which are not mutated.
When using factory functions to create collection instances, always use functions that return immutable collection types
when possible:

// Bad: use of mutable collection type for value which will not be mutated
fun validateValue(actualValue: String, allowedValues: HashSet<String>) { ... }

// Good: immutable collection type used instead


fun validateValue(actualValue: String, allowedValues: Set<String>) { ... }

// Bad: arrayListOf() returns ArrayList<T>, which is a mutable collection type


val allowedValues = arrayListOf("a", "b", "c")

// Good: listOf() returns List<T>


val allowedValues = listOf("a", "b", "c")

Default
parameter
values
Prefer declaring functions with default parameter values to declaring overloaded functions.

// Bad
fun foo() = foo("a")
fun foo(a: String) { /*...*/ }

209
// Good
fun foo(a: String = "a") { /*...*/ }

Type
aliases
If you have a functional type or a type with type parameters which is used multiple times in a codebase, prefer defining a
type alias for it:

typealias MouseClickHandler = (Any, MouseEvent) -> Unit


typealias PersonIndex = Map<String, Person>

If you use a private or internal type alias for avoiding name collision, prefer the import … as … mentioned in Packages
and Imports.

Lambda
parameters
In lambdas which are short and not nested, it's recommended to use the it convention instead of declaring the parameter
explicitly. In nested lambdas with parameters, always declare parameters explicitly.

Returns
in
a
lambda
Avoid using multiple labeled returns in a lambda. Consider restructuring the lambda so that it will have a single exit point.
If that's not possible or not clear enough, consider converting the lambda into an anonymous function.

Do not use a labeled return for the last statement in a lambda.

Named
arguments
Use the named argument syntax when a method takes multiple parameters of the same primitive type, or for parameters
of Boolean type, unless the meaning of all parameters is absolutely clear from context.

drawSquare(x = 10, y = 10, width = 100, height = 100, fill = true)

Conditional
statements
Prefer using the expression form of try, if, and when.

return if (x) foo() else bar()

return when(x) {
0 -> "zero"
else -> "nonzero"
}

The above is preferable to:

210
if (x)
return foo()
else
return bar()

when(x) {
0 -> return "zero"
else -> return "nonzero"
}

if
versus
when
Prefer using if for binary conditions instead of when. For example, use this syntax with if:

if (x == null) ... else ...

instead of this one with when:

when (x) {
null -> // ...
else -> // ...
}

Prefer using when if there are three or more options.

Nullable
Boolean
values
in
conditions
If you need to use a nullable Boolean in a conditional statement, use if (value == true) or if (value == false) checks.

Loops
Prefer using higher-order functions (filter, map etc.) to loops. Exception: forEach (prefer using a regular for loop instead,
unless the receiver of forEach is nullable or forEach is used as part of a longer call chain).

When making a choice between a complex expression using multiple higher-order functions and a loop, understand the
cost of the operations being performed in each case and keep performance considerations in mind.

Loops
on
ranges
Use the until function to loop over an open range:

for (i in 0..n - 1) { /*...*/ } // bad


for (i in 0 until n) { /*...*/ } // good

211
Strings
Prefer string templates to string concatenation.

Prefer multiline strings to embedding \n escape sequences into regular string literals.

To maintain indentation in multiline strings, use trimIndent when the resulting string does not require any internal
indentation, or trimMargin when internal indentation is required:

fun main() {
//sampleStart
println("""
Not
trimmed
text
"""
)

println("""
Trimmed
text
""".trimIndent()
)

println()

val a = """Trimmed to margin text:


|if(a > 1) {
| return a
|}""".trimMargin()

println(a)
//sampleEnd
}

Learn the difference between Java and Kotlin multiline strings.

Functions
vs
properties
In some cases functions with no arguments might be interchangeable with read-only properties. Although the semantics
are similar, there are some stylistic conventions on when to prefer one to another.

Prefer a property over a function when the underlying algorithm:

does not throw

is cheap to calculate (or cached on the first run)

returns the same result over invocations if the object state hasn't changed

Extension
functions
Use extension functions liberally. Every time you have a function that works primarily on an object, consider making it an
extension function accepting that object as a receiver. To minimize API pollution, restrict the visibility of extension

212
functions as much as it makes sense. As necessary, use local extension functions, member extension functions, or top-
level extension functions with private visibility.

Infix
functions
Declare a function as infix only when it works on two objects which play a similar role. Good examples: and, to, zip. Bad
example: add.

Do not declare a method as infix if it mutates the receiver object.

Factory
functions
If you declare a factory function for a class, avoid giving it the same name as the class itself. Prefer using a distinct name
making it clear why the behavior of the factory function is special. Only if there is really no special semantics, you can use
the same name as the class.

class Point(val x: Double, val y: Double) {


companion object {
fun fromPolar(angle: Double, radius: Double) = Point(...)
}
}

If you have an object with multiple overloaded constructors that don't call different superclass constructors and can't be
reduced to a single constructor with default argument values, prefer to replace the overloaded constructors with factory
functions.

Platform
types
A public function/method returning an expression of a platform type must declare its Kotlin type explicitly:

fun apiCall(): String = MyJavaApi.getProperty("name")

Any property (package-level or class-level) initialized with an expression of a platform type must declare its Kotlin type
explicitly:

class Person {
val name: String = MyJavaApi.getProperty("name")
}

A local value initialized with an expression of a platform type may or may not have a type declaration:

fun main() {
val name = MyJavaApi.getProperty("name")
println(name)
}

213
Scope
functions
apply/with/run/also/let
Kotlin provides a set of functions to execute a block of code in the context of a given object: let, run, with, apply, and
also. For the guidance on choosing the right scope function for your case, refer to Scope Functions.

Coding
conventions
for
libraries
When writing libraries, it's recommended to follow an additional set of rules to ensure API stability:

Always explicitly specify member visibility (to avoid accidentally exposing declarations as public API)

Always explicitly specify function return types and property types (to avoid accidentally changing the return type when
the implementation changes)

Provide KDoc comments for all public members, with the exception of overrides that do not require any new
documentation (to support generating documentation for the library)

Basic
types
In Kotlin, everything is an object in the sense that we can call member functions and properties on any variable. Some
types can have a special internal representation - for example, numbers, characters and booleans can be represented as
primitive values at runtime - but to the user they look like ordinary classes. In this section we describe the basic types
used in Kotlin: numbers, booleans, characters, strings, and arrays.

Numbers

Integer
types
Kotlin provides a set of built-in types that represent numbers.
For integer numbers, there are four types with different sizes and, hence, value ranges.

Type Size (bits) Min value Max value

Byte 8 -128 127

Short 16 -32768 32767

Int 32 -2,147,483,648 (-2 31) 2,147,483,647 (2 31- 1)

Long 64 -9,223,372,036,854,775,808 (-2 63) 9,223,372,036,854,775,807 (2 63- 1)

All variables initialized with integer values not exceeding the maximum value of Int have the inferred type Int. If the initial
value exceeds this value, then the type is Long. To specify the Long value explicitly, append the suffix L to the value.

214
val one = 1 // Int
val threeBillion = 3000000000 // Long
val oneLong = 1L // Long
val oneByte: Byte = 1

Floating-point
types
For real numbers, Kotlin provides floating-point types Float and Double. According to the IEEE 754 standard, floating
point types differ by their decimal place, that is, how many decimal digits they can store. Float reflects the IEEE 754 single
precision, while Double provides double precision.

Type Size (bits) Significant bits Exponent bits Decimal digits

Float 32 24 8 6-7

Double 64 53 11 15-16

You can initialize Double and Float variables with numbers having a fractional part. It's separated from the integer part by
a period (.) For variables initialized with fractional numbers, the compiler infers the Double type.

val pi = 3.14 // Double


// val one: Double = 1 // Error: type mismatch
val oneDouble = 1.0 // Double

To explicitly specify the Float type for a value, add the suffix f or F. If such a value contains more than 6-7 decimal digits,
it will be rounded.

val e = 2.7182818284 // Double


val eFloat = 2.7182818284f // Float, actual value is 2.7182817

Note that unlike some other languages, there are no implicit widening conversions for numbers in Kotlin. For example, a
function with a Double parameter can be called only on Double values, but not Float, Int, or other numeric values.

fun main() {
fun printDouble(d: Double) { print(d) }

val i = 1
val d = 1.0
val f = 1.0f

printDouble(d)
// printDouble(i) // Error: Type mismatch
// printDouble(f) // Error: Type mismatch
}

To convert numeric values to different types, use Explicit conversions.

215
Literal
constants
There are the following kinds of literal constants for integral values:

Decimals: 123
Longs are tagged by a capital L: 123L

Hexadecimals: 0x0F

Binaries: 0b00001011

Octal literals are not supported.

Kotlin also supports a conventional notation for floating-point numbers:

Doubles by default: 123.5, 123.5e10

Floats are tagged by f or F: 123.5f

You can use underscores to make number constants more readable:

val oneMillion = 1_000_000


val creditCardNumber = 1234_5678_9012_3456L
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

Numbers
representation
on
the
JVM
On the JVM platform, numbers are stored as primitive types: int, double, and so on. Exceptions are cases when you
create a nullable number reference such as Int? or use generics. In these cases numbers are boxed in Java classes
Integer, Double, and so on.

Note that nullable references to the same number can be different objects:

fun main() {
//sampleStart
val a: Int = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a

val b: Int = 10000
val boxedB: Int? = b
val anotherBoxedB: Int? = b

println(boxedA === anotherBoxedA) // true
println(boxedB === anotherBoxedB) // false
//sampleEnd
}

216
All nullable references to a are actually the same object because of the memory optimization that JVM applies to Integer s
between -128 and 127. It doesn't apply to the b references, so they are different objects.

On the other hand, they are still equal:

fun main() {
//sampleStart
val b: Int = 10000
println(b == b) // Prints 'true'
val boxedB: Int? = b
val anotherBoxedB: Int? = b
println(boxedB == anotherBoxedB) // Prints 'true'
//sampleEnd
}

Explicit
conversions
Due to different representations, smaller types are not subtypes of bigger ones. If they were, we would have troubles of
the following sort:

// Hypothetical code, does not actually compile:


val a: Int? = 1 // A boxed Int (java.lang.Integer)
val b: Long? = a // implicit conversion yields a boxed Long (java.lang.Long)
print(b == a) // Surprise! This prints "false" as Long's equals() checks whether the other is
Long as well

So equality would have been lost silently, not to mention identity.

As a consequence, smaller types are NOT implicitly converted to bigger types. This means that assigning a value of type
Byte to an Int variable requires an explicit conversion.

fun main() {
//sampleStart
val b: Byte = 1 // OK, literals are checked statically
// val i: Int = b // ERROR
val i1: Int = b.toInt()
//sampleEnd
}

All number types support conversions to other types:

toByte(): Byte

toShort(): Short

toInt(): Int

toLong(): Long

toFloat(): Float

217
toDouble(): Double

toChar(): Char

In many cases, there is no need in explicit conversions because the type is inferred from the context, and arithmetical
operations are overloaded for appropriate conversions, for example:

val l = 1L + 3 // Long + Int => Long

Operations
Kotlin supports the standard set of arithmetical operations over numbers: +, -, *, /, %. They are declared as members of
appropriate classes.

fun main() {
//sampleStart
println(1 + 2)
println(2_500_000_000L - 1L)
println(3.14 * 2.71)
println(10.0 / 3)
//sampleEnd
}

You can also override these operators for custom classes. See Operator overloading for details.

Division of integers
Division between integers numbers always returns an integer number. Any fractional part is discarded.

fun main() {
//sampleStart
val x = 5 / 2
//println(x == 2.5) // ERROR: Operator '==' cannot be applied to 'Int' and 'Double'
println(x == 2)
//sampleEnd
}

This is true for a division between any two integer types.

fun main() {
//sampleStart
val x = 5L / 2
println(x == 2L)
//sampleEnd
}

To return a floating-point type, explicitly convert one of the arguments to a floating-point type.

fun main() {

218
//sampleStart
val x = 5 / 2.toDouble()
println(x == 2.5)
//sampleEnd
}

Bitwise operations
Kotlin provides a set of bitwise operations on integer numbers. They operate on the binary level directly with bits of the
numbers' representation. Bitwise operations are represented by functions that can be called in infix form. They can be
applied only to Int and Long.

val x = (1 shl 2) and 0x000FF000

Here is the complete list of bitwise operations:

shl(bits) – signed shift left

shr(bits) – signed shift right

ushr(bits) – unsigned shift right

and(bits) – bitwise and

or(bits) – bitwise or

xor(bits) – bitwise xor

inv() – bitwise inversion

Floating-point
numbers
comparison
The operations on floating-point numbers discussed in this section are:

Equality checks: a == b and a != b

Comparison operators: a < b, a > b, a <= b, a >= b

Range instantiation and range checks: a..b, x in a..b, x !in a..b

When the operands a and b are statically known to be Float or Double or their nullable counterparts (the type is declared
or inferred or is a result of a smart cast), the operations on the numbers and the range that they form follow the IEEE 754
Standard for Floating-Point Arithmetic.

However, to support generic use cases and provide total ordering, when the operands are not statically typed as floating
point numbers (e.g. Any, Comparable<...>, a type parameter), the operations use the equals and compareTo
implementations for Float and Double, which disagree with the standard, so that:

NaN is considered equal to itself

NaN is considered greater than any other element including POSITIVE_INFINITY

219
-0.0 is considered less than 0.0

Unsigned
integers
In addition to integer types, Kotlin provides the following types for unsigned integer numbers:

UByte: an unsigned 8-bit integer, ranges from 0 to 255

UShort: an unsigned 16-bit integer, ranges from 0 to 65535

UInt: an unsigned 32-bit integer, ranges from 0 to 2^32 - 1

ULong: an unsigned 64-bit integer, ranges from 0 to 2^64 - 1

Unsigned types support most of the operations of their signed counterparts.

Changing type from unsigned type to signed counterpart (and vice versa) is a binary incompatible change.

Unsigned arrays and ranges

Unsigned arrays and operations on them are in Beta. They can be changed incompatibly at any time. Opt-in is
required (see the details below).

Same as for primitives, each of unsigned type has corresponding type that represents arrays of that type:

UByteArray: an array of unsigned bytes

UShortArray: an array of unsigned shorts

UIntArray: an array of unsigned ints

ULongArray: an array of unsigned longs

Same as for signed integer arrays, they provide similar API to Array class without boxing overhead.

When you use unsigned arrays, you'll get a warning that indicates that this feature is not stable yet. To remove the
warning, opt in using the @ExperimentalUnsignedTypes annotation. It's up to you to decide if your clients have to
explicitly opt-in into usage of your API, but keep in mind that unsigned array are not a stable feature, so API which uses
them can be broken by changes in the language. Learn more about opt-in requirements.

Ranges and progressions are supported for UInt and ULong by classes UIntRange, UIntProgression, ULongRange, and
ULongProgression. Together with the unsigned integer types, these classes are stable.

Literals
To make unsigned integers easier to use, Kotlin provides an ability to tag an integer literal with a suffix indicating a

220
specific unsigned type (similarly to Float or Long):

u and U tag unsigned literals. The exact type is determined based on the expected type. If no expected type is
provided, compiler will use UInt or ULong depending on the size of literal.

val b: UByte = 1u // UByte, expected type provided


val s: UShort = 1u // UShort, expected type provided
val l: ULong = 1u // ULong, expected type provided

val a1 = 42u // UInt: no expected type provided, constant fits in UInt


val a2 = 0xFFFF_FFFF_FFFFu // ULong: no expected type provided, constant doesn't fit in UInt

uL and UL explicitly tag literal as unsigned long.

val a = 1UL // ULong, even though no expected type provided and constant fits into UInt

Further discussion
See language proposal for unsigned types for technical details and further discussion.

Booleans
The type Boolean represents boolean objects that can have two values: true and false.

Boolean has a nullable counterpart Boolean? that also has the null value.

Built-in operations on booleans include:

|| – disjunction (logical OR)

&& – conjunction (logical AND)

!- negation (logical NOT)

|| and && work lazily.

fun main() {
//sampleStart
val myTrue: Boolean = true
val myFalse: Boolean = false
val boolNull: Boolean? = null

println(myTrue || myFalse)
println(myTrue && myFalse)
println(!myTrue)
//sampleEnd
}

221
On JVM: nullable references to boolean objects are boxed similarly to numbers.

Characters
Characters are represented by the type Char. Character literals go in single quotes: '1'.

Special characters start from an escaping backslash \. The following escape sequences are supported: \t, \b, \n, \r, \', \",
\\ and \$.

To encode any other character, use the Unicode escape sequence syntax: '\uFF00'.

fun main() {
//sampleStart
val aChar: Char = 'a'

println(aChar)
println('\n') //prints an extra newline character
println('\uFF00')
//sampleEnd
}

If a value of character variable is a digit, you can explicitly convert it to an Int number using the digitToInt() function.

On JVM: Like numbers, characters are boxed when a nullable reference is needed. Identity is not preserved by
the boxing operation.

Strings
Strings in Kotlin are represented by the type String. Generally, a string value is a sequence of characters in double quotes
(").

val str = "abcd 123"

Elements of a string are characters that you can access via the indexing operation: s[i]. You can iterate over these
characters with a for loop:

fun main() {
val str = "abcd"
//sampleStart
for (c in str) {
println(c)
}
//sampleEnd
}

222
Strings are immutable. Once you initialize a string, you can't change its value or assign a new value to it. All operations
that transform strings return their results in a new String object, leaving the original string unchanged.

fun main() {
//sampleStart
val str = "abcd"
println(str.uppercase()) // Create and print a new String object
println(str) // the original string remains the same
//sampleEnd
}

To concatenate strings, use the + operator. This also works for concatenating strings with values of other types, as long
as the first element in the expression is a string:

fun main() {
//sampleStart
val s = "abc" + 1
println(s + "def")
//sampleEnd
}

Note that in most cases using string templates or raw strings is preferable to string concatenation.

String
literals
Kotlin has two types of string literals:

escaped strings that may contain escaped characters

raw strings that can contain newlines and arbitrary text

Here's an example of an escaped string:

val s = "Hello, world!\n"

Escaping is done in the conventional way, with a backslash (\). See Characters above for the list of supported escape
sequences.

A raw string is delimited by a triple quote ("""), contains no escaping and can contain newlines and any other characters:

val text = """


for (c in "foo")
print(c)
"""

To remove leading whitespace from raw strings, use the trimMargin() function:

val text = """


|Tell me and I forget.

223
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()

By default, | is used as margin prefix, but you can choose another character and pass it as a parameter, like
trimMargin(">").

String
templates
String literals may contain template expressions - pieces of code that are evaluated and whose results are concatenated
into the string. A template expression starts with a dollar sign ($) and consists of either a name:

fun main() {
//sampleStart
val i = 10
println("i = $i") // prints "i = 10"
//sampleEnd
}

or an expression in curly braces:

fun main() {
//sampleStart
val s = "abc"
println("$s.length is ${s.length}") // prints "abc.length is 3"
//sampleEnd
}

You can use templates both in raw and escaped strings. To insert the $ character in a raw string (which doesn't support
backslash escaping) before any symbol, which is allowed as a beginning of an identifier, use the following syntax:

val price = """


${'$'}_9.99
"""

Arrays
Arrays in Kotlin are represented by the Array class. It has get and set functions that turn into [] by operator overloading
conventions, and the size property, along with other useful member functions:

class Array<T> private constructor() {


val size: Int
operator fun get(index: Int): T
operator fun set(index: Int, value: T): Unit

operator fun iterator(): Iterator<T>


// ...

224
}

To create an array, use the function arrayOf() and pass the item values to it, so that arrayOf(1, 2, 3) creates an array [1, 2,
3]. Alternatively, the arrayOfNulls() function can be used to create an array of a given size filled with null elements.

Another option is to use the Array constructor that takes the array size and the function that returns values of array
elements given its index:

fun main() {
//sampleStart
// Creates an Array<String> with values ["0", "1", "4", "9", "16"]
val asc = Array(5) { i -> (i * i).toString() }
asc.forEach { println(it) }
//sampleEnd
}

As we said above, the [] operation stands for calls to member functions get() and set().

Arrays in Kotlin are invariant. This means that Kotlin does not let us assign an Array<String> to an Array<Any>, which
prevents a possible runtime failure (but you can use Array<out Any>, see Type Projections).

Primitive
type
arrays
Kotlin also has classes that represent arrays of primitive types without boxing overhead: ByteArray, ShortArray, IntArray,
and so on. These classes have no inheritance relation to the Array class, but they have the same set of methods and
properties. Each of them also has a corresponding factory function:

val x: IntArray = intArrayOf(1, 2, 3)


x[0] = x[1] + x[2]

// Array of int of size 5 with values [0, 0, 0, 0, 0]


val arr = IntArray(5)

// e.g. initialise the values in the array with a constant


// Array of int of size 5 with values [42, 42, 42, 42, 42]
val arr = IntArray(5) { 42 }

// e.g. initialise the values in the array using a lambda


// Array of int of size 5 with values [0, 1, 2, 3, 4] (values initialised to their index value)
var arr = IntArray(5) { it * 1 }

Type
checks
and
casts

is
and
!is
operators
Use the is operator or its negated form !is to perform a runtime check that identifies whether an object conforms to a

225
given type:

if (obj is String) {
print(obj.length)
}

if (obj !is String) { // same as !(obj is String)


print("Not a String")
} else {
print(obj.length)
}

Smart
casts
In most cases, you don't need to use explicit cast operators in Kotlin because the compiler tracks the is -checks and
explicit casts for immutable values and inserts (safe) casts automatically when necessary:

fun demo(x: Any) {


if (x is String) {
print(x.length) // x is automatically cast to String
}
}

The compiler is smart enough to know that a cast is safe if a negative check leads to a return:

if (x !is String) return

print(x.length) // x is automatically cast to String

or if it is on the right-hand side of && or ||:

// x is automatically cast to String on the right-hand side of `||`


if (x !is String || x.length == 0) return

// x is automatically cast to String on the right-hand side of `&&`


if (x is String && x.length > 0) {
print(x.length) // x is automatically cast to String
}

Smart casts work for when expressions and while loops as well:

when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}

Note that smart casts work only when the compiler can guarantee that the variable won't change between the check and
the usage. More specifically, smart casts can be used under the following conditions:

226
val local variables - always, with the exception of local delegated properties.

val properties - if the property is private or internal or if the check is performed in the same module where the property
is declared. Smart casts cannot be used on open properties or properties that have custom getters.

var local variables - if the variable is not modified between the check and the usage, is not captured in a lambda that
modifies it, and is not a local delegated property.

var properties - never, because the variable can be modified at any time by other code.

"Unsafe"
cast
operator
Usually, the cast operator throws an exception if the cast isn't possible. And so, it's called unsafe. The unsafe cast in
Kotlin is done by the infix operator as.

val x: String = y as String

Note that null cannot be cast to String, as this type is not nullable. If y is null, the code above throws an exception. To
make code like this correct for null values, use the nullable type on the right-hand side of the cast:

val x: String? = y as String?

"Safe"
(nullable)
cast
operator
To avoid exceptions, use the safe cast operator as?, which returns null on failure.

val x: String? = y as? String

Note that despite the fact that the right-hand side of as? is a non-null type String, the result of the cast is nullable.

Type
erasure
and
generic
type
checks
Kotlin ensures type safety for operations involving generics at compile time, while, at runtime, instances of generic types
don't hold information about their actual type arguments. For example, List<Foo> is erased to just List<*>. In general,
there is no way to check whether an instance belongs to a generic type with certain type arguments at runtime.

Because of that, the compiler prohibits is -checks that cannot be performed at runtime due to type erasure, such as ints
is List<Int> or list is T (type parameter). You can, however, check an instance against a star-projected type:

if (something is List<*>) {
something.forEach { println(it) } // The items are typed as `Any?`
}

227
Similarly, when you already have the type arguments of an instance checked statically (at compile time), you can make an
is -check or a cast that involves the non-generic part of the type. Note that angle brackets are omitted in this case:

fun handleStrings(list: List<String>) {


if (list is ArrayList) {
// `list` is smart-cast to `ArrayList<String>`
}
}

The same syntax but with the type arguments omitted can be used for casts that do not take type arguments into
account: list as ArrayList.

Inline functions with reified type parameters have their actual type arguments inlined at each call site. This enables arg is T
checks for the type parameters, but if arg is an instance of a generic type itself, its type arguments are still erased.

//sampleStart
inline fun <reified A, reified B> Pair<*, *>.asPairOf(): Pair<A, B>? {
if (first !is A || second !is B) return null
return first as A to second as B
}

val somePair: Pair<Any?, Any?> = "items" to listOf(1, 2, 3)

val stringToSomething = somePair.asPairOf<String, Any>()


val stringToInt = somePair.asPairOf<String, Int>()
val stringToList = somePair.asPairOf<String, List<*>>()
val stringToStringList = somePair.asPairOf<String, List<String>>() // Compiles but breaks type
safety!
// Expand the sample for more details

//sampleEnd

fun main() {
println("stringToSomething = " + stringToSomething)
println("stringToInt = " + stringToInt)
println("stringToList = " + stringToList)
println("stringToStringList = " + stringToStringList)
//println(stringToStringList?.second?.forEach() {it.length}) // This will throw
ClassCastException as list items are not String
}

Unchecked
casts
As established above, type erasure makes checking the actual type arguments of a generic type instance impossible at
runtime. Additionally, generic types in the code might not be connected to each other closely enough for the compiler to
ensure type safety.

Even so, sometimes we have high-level program logic that implies type safety instead. For example:

228
fun readDictionary(file: File): Map<String, *> = file.inputStream().use {
TODO("Read a mapping of strings to arbitrary elements.")
}

// We saved a map with `Int`s into this file


val intsFile = File("ints.dictionary")

// Warning: Unchecked cast: `Map<String, *>` to `Map<String, Int>`


val intsDictionary: Map<String, Int> = readDictionary(intsFile) as Map<String, Int>

A warning appears for the cast in the last line. The compiler can't fully check it at runtime and provides no guarantee that
the values in the map are Int.

To avoid unchecked casts, you can redesign the program structure. In the example above, you could use the
DictionaryReader<T> and DictionaryWriter<T> interfaces with type-safe implementations for different types. You can
introduce reasonable abstractions to move unchecked casts from the call site to the implementation details. Proper use of
generic variance can also help.

For generic functions, using reified type parameters makes casts like arg as T checked, unless arg 's type has its own
type arguments that are erased.

An unchecked cast warning can be suppressed by annotating the statement or the declaration where it occurs with
@Suppress("UNCHECKED_CAST"):

inline fun <reified T> List<*>.asListOfType(): List<T>? =


if (all { it is T })
@Suppress("UNCHECKED_CAST")
this as List<T> else
null

On the JVM: array types (Array<Foo>) retain information about the erased type of their elements, and type casts
to an array type are partially checked: the nullability and actual type arguments of the element type are still
erased. For example, the cast foo as Array<List<String>?> will succeed if foo is an array holding any List<*>,
whether it is nullable or not.

Conditions
and
loops

If
expression
In Kotlin, if is an expression: it returns a value. Therefore, there is no ternary operator (condition ? then : else) because
ordinary if works fine in this role.

var max = a
if (a < b) max = b

229
// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
}

// As expression
val max = if (a > b) a else b

Branches of if branches can be blocks. In this case, the last expression is the value of a block:

val max = if (a > b) {


print("Choose a")
a
} else {
print("Choose b")
b
}

If you're using if as an expression, for example, for returning its value or assigning it to a variable, the else branch is
mandatory.

When
expression
when defines a conditional expression with multiple branches. It is similar to the switch statement in C-like languages. Its
simple form looks like this.

when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}

when matches its argument against all branches sequentially until some branch condition is satisfied.

when can be used either as an expression or as a statement. If it is used as an expression, the value of the first matching
branch becomes the value of the overall expression. If it is used as a statement, the values of individual branches are
ignored. Just like with if, each branch can be a block, and its value is the value of the last expression in the block.

The else branch is evaluated if none of the other branch conditions are satisfied. If when is used as an expression, the
else branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions, for
example, with enum class entries and sealed class subtypes).

enum class Bit {


ZERO, ONE

230
}

val numericValue = when (getRandomBit()) {


Bit.ZERO -> 0
Bit.ONE -> 1
// the 'else' clause is not required because all cases are covered
}

To define a common behavior for multiple cases, combine their conditions in a single line with a comma:

when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}

You can use arbitrary expressions (not only constants) as branch conditions

when (x) {
s.toInt() -> print("s encodes x")
else -> print("s does not encode x")
}

You can also check a value for being in or !in a range or a collection:

when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}

Another option is checking that a value is or !is of a particular type. Note that, due to smart casts, you can access the
methods and properties of the type without any extra checks.

fun hasPrefix(x: Any) = when(x) {


is String -> x.startsWith("prefix")
else -> false
}

when can also be used as a replacement for an if- else if chain. If no argument is supplied, the branch conditions are
simply boolean expressions, and a branch is executed when its condition is true:

when {
x.isOdd() -> print("x is odd")
y.isEven() -> print("y is even")
else -> print("x+y is odd")
}

You can capture when subject in a variable using following syntax:

231
fun Request.getBody() =
when (val response = executeRequest()) {
is Success -> response.body
is HttpError -> throw HttpException(response.status)
}

The scope of variable introduced in when subject is restricted to the body of this when.

For
loops
The for loop iterates through anything that provides an iterator. This is equivalent to the foreach loop in languages like C#.
The syntax of for is the following:

for (item in collection) print(item)

The body of for can be a block.

for (item: Int in ints) {


// ...
}

As mentioned before, for iterates through anything that provides an iterator. This means that it:

has a member or an extension function iterator() that returns Iterator<>:


has a member or an extension function next()

has a member or an extension function hasNext() that returns Boolean.

All of these three functions need to be marked as operator.

To iterate over a range of numbers, use a range expression:

fun main() {
//sampleStart
for (i in 1..3) {
println(i)
}
for (i in 6 downTo 0 step 2) {
println(i)
}
//sampleEnd
}

A for loop over a range or an array is compiled to an index-based loop that does not create an iterator object.

If you want to iterate through an array or a list with an index, you can do it this way:

fun main() {
val array = arrayOf("a", "b", "c")

232
//sampleStart
for (i in array.indices) {
println(array[i])
}
//sampleEnd
}

Alternatively, you can use the withIndex library function:

fun main() {
val array = arrayOf("a", "b", "c")
//sampleStart
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
//sampleEnd
}

While
loops
while and do-while loops execute their body continuously while their condition is satisfied. The difference between them is
the condition checking time:

while checks the condition and, if it's satisfied, executes the body and then returns to the condition check.

do-while executes the body and then checks the condition. If it's satisfied, the loop repeats. So, the body of do-while
executes at least once regardless of the condition.

while (x > 0) {
x--
}

do {
val y = retrieveData()
} while (y != null) // y is visible here!

Break
and
continue
in
loops
Kotlin supports traditional break and continue operators in loops. See Returns and jumps.

Returns
and
jumps
Kotlin has three structural jump expressions:

return by default returns from the nearest enclosing function or anonymous function

233
break terminates the nearest enclosing loop

continue proceeds to the next step of the nearest enclosing loop

All of these expressions can be used as part of larger expressions:

val s = person.name ?: return

The type of these expressions is the Nothing type.

Break
and
continue
labels
Any expression in Kotlin may be marked with a label. Labels have the form of an identifier followed by the @ sign, for
example: abc@, fooBar@. To label an expression, just add a label in front of it.

loop@ for (i in 1..100) {


// ...
}

Now, we can qualify a break or a continue with a label:

loop@ for (i in 1..100) {


for (j in 1..100) {
if (...) break@loop
}
}

A break qualified with a label jumps to the execution point right after the loop marked with that label. A continue proceeds
to the next iteration of that loop.

Return
at
labels
With function literals, local functions and object expressions, functions can be nested in Kotlin. Qualified return s allow us
to return from an outer function. The most important use case is returning from a lambda expression. Recall that when we
write this:

//sampleStart
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return // non-local return directly to the caller of foo()
print(it)
}
println("this point is unreachable")
}
//sampleEnd

fun main() {

234
foo()
}

The return -expression returns from the nearest enclosing function - foo. Note that such non-local returns are supported
only for lambda expressions passed to inline functions. To return from a lambda expression, label it and qualify the return:

//sampleStart
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // local return to the caller of the lambda - the forEach loop
print(it)
}
print(" done with explicit label")
}
//sampleEnd

fun main() {
foo()
}

Now, it returns only from the lambda expression. Oftentimes it is more convenient to use implicit labels: such a label has
the same name as the function to which the lambda is passed.

//sampleStart
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // local return to the caller of the lambda - the forEach
loop
print(it)
}
print(" done with implicit label")
}
//sampleEnd

fun main() {
foo()
}

Alternatively, you can replace the lambda expression with an anonymous function. A return statement in an anonymous
function will return from the anonymous function itself.

//sampleStart
fun foo() {
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return // local return to the caller of the anonymous function - the
forEach loop
print(value)
})
print(" done with anonymous function")
}
//sampleEnd

fun main() {
foo()

235
}

Note that the use of local returns in previous three examples is similar to the use of continue in regular loops. There is no
direct equivalent for break, but it can be simulated by adding another nesting lambda and non-locally returning from it:

//sampleStart
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // non-local return from the lambda passed to run
print(it)
}
}
print(" done with nested loop")
}
//sampleEnd

fun main() {
foo()
}

When returning a value, the parser gives preference to the qualified return:

return@a 1

This means "return 1 at label @a" and not "return a labeled expression (@a 1)".

Exceptions

Exception
classes
All exception classes in Kotlin inherit the Throwable class. Every exception has a message, a stack trace, and an optional
cause.

To throw an exception object, use the throw expression:

fun main() {
//sampleStart
throw Exception("Hi There!")
//sampleEnd
}

To catch an exception, use the try... catch expression:

try {
// some code
} catch (e: SomeException) {

236
// handler
} finally {
// optional finally block
}

There may be zero or more catch blocks, and the finally block may be omitted. However, at least one catch or finally block
is required.

Try
is
an
expression
try is an expression, which means it can have a return value:

val a: Int? = try { input.toInt() } catch (e: NumberFormatException) { null }

The returned value of a try expression is either the last expression in the try block or the last expression in the catch block
(or blocks). The contents of the finally block don't affect the result of the expression.

Checked
exceptions
Kotlin does not have checked exceptions. There are many reasons for this, but we will provide a simple example that
illustrates why it is the case.

The following is an example interface from the JDK implemented by the StringBuilder class:

Appendable append(CharSequence csq) throws IOException;

This signature says that every time I append a string to something (a StringBuilder, some kind of a log, a console, etc.), I
have to catch the IOExceptions. Why? Because the implementation might be performing IO operations (Writer also
implements Appendable). The result is code like this all over the place.:

try {
log.append(message)
} catch (IOException e) {
// Must be safe
}

And that’s not good. Just take a look at Effective Java, 3rd Edition, Item 77: Don't ignore exceptions.

Bruce Eckel says this about checked exceptions:

Examination of small programs leads to the conclusion that requiring exception specifications could both
enhance developer productivity and enhance code quality, but experience with large software projects
suggests a different result – decreased productivity and little or no increase in code quality.

237
And here are some additional thoughts on the matter:

Java's checked exceptions were a mistake (Rod Waldhoff)

The Trouble with Checked Exceptions (Anders Hejlsberg)

If you want to alert callers about possible exceptions when calling Kotlin code from Java, Swift, or Objective-C, you can
use the @Throws annotation. Read more about using this annotation for Java and for Swift and Objective-C.

The
Nothing
type
throw is an expression in Kotlin, so you can use it, for example, as part of an Elvis expression:

val s = person.name ?: throw IllegalArgumentException("Name required")

The throw expression has the type Nothing. This type has no values and is used to mark code locations that can never be
reached. In your own code, you can use Nothing to mark a function that never returns:

fun fail(message: String): Nothing {


throw IllegalArgumentException(message)
}

When you call this function, the compiler will know that the execution doesn't continue beyond the call:

val s = person.name ?: fail("Name required")


println(s) // 's' is known to be initialized at this point

You may also encounter this type when dealing with type inference. The nullable variant of this type, Nothing?, has
exactly one possible value, which is null. If you use null to initialize a value of an inferred type and there's no other
information that can be used to determine a more specific type, the compiler will infer the Nothing? type:

val x = null // 'x' has type `Nothing?`


val l = listOf(null) // 'l' has type `List<Nothing?>

Java
interoperability
Please see the section on exceptions in the Java interoperability page for information about Java interoperability.

Packages
and
imports
A source file may start with a package declaration:

238
package org.example

fun printMessage() { /*...*/ }


class Message { /*...*/ }

// ...

All the contents, such as classes and functions, of the source file are included in this package. So, in the example above,
the full name of printMessage() is org.example.printMessage, and the full name of Message is org.example.Message.

If the package is not specified, the contents of such a file belong to the default package with no name.

Default
imports
A number of packages are imported into every Kotlin file by default:

kotlin.*

kotlin.annotation.*

kotlin.collections.*

kotlin.comparisons.*

kotlin.io.*

kotlin.ranges.*

kotlin.sequences.*

kotlin.text.*

Additional packages are imported depending on the target platform:

JVM:

java.lang.*

kotlin.jvm.*

JS:

kotlin.js.*

Imports
Apart from the default imports, each file may contain its own import directives.

You can import either a single name:

239
import org.example.Message // Message is now accessible without qualification

or all the accessible contents of a scope: package, class, object, and so on:

import org.example.* // everything in 'org.example' becomes accessible

If there is a name clash, you can disambiguate by using as keyword to locally rename the clashing entity:

import org.example.Message // Message is accessible


import org.test.Message as testMessage // testMessage stands for 'org.test.Message'

The import keyword is not restricted to importing classes; you can also use it to import other declarations:

top-level functions and properties

functions and properties declared in object declarations

enum constants

Visibility
of
top-level
declarations
If a top-level declaration is marked private, it is private to the file it's declared in (see Visibility modifiers).

Classes
Classes in Kotlin are declared using the keyword class:

class Person { /*...*/ }

The class declaration consists of the class name, the class header (specifying its type parameters, the primary
constructor, and some other things), and the class body surrounded by curly braces. Both the header and the body are
optional; if the class has no body, the curly braces can be omitted.

class Empty

Constructors
A class in Kotlin can have a primary constructor and one or more secondary constructors. The primary constructor is a
part of the class header, and it goes after the class name and optional type parameters.

class Person constructor(firstName: String) { /*...*/ }

240
If the primary constructor does not have any annotations or visibility modifiers, the constructor keyword can be omitted:

class Person(firstName: String) { /*...*/ }

The primary constructor cannot contain any code. Initialization code can be placed in initializer blocks prefixed with the
init keyword.

During the initialization of an instance, the initializer blocks are executed in the same order as they appear in the class
body, interleaved with the property initializers:

//sampleStart
class InitOrderDemo(name: String) {
val firstProperty = "First property: $name".also(::println)

init {
println("First initializer block that prints ${name}")
}

val secondProperty = "Second property: ${name.length}".also(::println)

init {
println("Second initializer block that prints ${name.length}")
}
}
//sampleEnd

fun main() {
InitOrderDemo("hello")
}

Primary constructor parameters can be used in the initializer blocks. They can also be used in property initializers
declared in the class body:

class Customer(name: String) {


val customerKey = name.uppercase()
}

Kotlin has a concise syntax for declaring properties and initializing them from the primary constructor:

class Person(val firstName: String, val lastName: String, var age: Int)

Such declarations can also include default values of the class properties:

class Person(val firstName: String, val lastName: String, var isEmployed: Boolean = true)

You can use a trailing comma when you declare class properties:

class Person(

241
val firstName: String,
val lastName: String,
var age: Int, // trailing comma
) { /*...*/ }

Much like regular properties, properties declared in the primary constructor can be mutable (var) or read-only (val).

If the constructor has annotations or visibility modifiers, the constructor keyword is required and the modifiers go before
it:

class Customer public @Inject constructor(name: String) { /*...*/ }

Learn more about visibility modifiers.

Secondary
constructors
A class can also declare secondary constructors, which are prefixed with constructor:

class Person(val pets: MutableList<Pet> = mutableListOf())

class Pet {
constructor(owner: Person) {
owner.pets.add(this) // adds this pet to the list of its owner's pets
}
}

If the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either
directly or indirectly through another secondary constructor(s). Delegation to another constructor of the same class is
done using the this keyword:

class Person(val name: String) {


var children: MutableList<Person> = mutableListOf()
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}

Code in initializer blocks effectively becomes part of the primary constructor. Delegation to the primary constructor
happens as the first statement of a secondary constructor, so the code in all initializer blocks and property initializers is
executed before the body of the secondary constructor.

Even if the class has no primary constructor, the delegation still happens implicitly, and the initializer blocks are still
executed:

//sampleStart
class Constructors {
init {
println("Init block")
}

242
constructor(i: Int) {
println("Constructor $i")
}
}
//sampleEnd

fun main() {
Constructors(1)
}

If a non-abstract class does not declare any constructors (primary or secondary), it will have a generated primary
constructor with no arguments. The visibility of the constructor will be public.

If you don't want your class to have a public constructor, declare an empty primary constructor with non-default visibility:

class DontCreateMe private constructor () { /*...*/ }

On the JVM, if all of the primary constructor parameters have default values, the compiler will generate an
additional parameterless constructor which will use the default values. This makes it easier to use Kotlin with
libraries such as Jackson or JPA that create class instances through parameterless constructors.

class Customer(val customerName: String = "")

Creating
instances
of
classes
To create an instance of a class, call the constructor as if it were a regular function:

val invoice = Invoice()

val customer = Customer("Joe Smith")

Kotlin does not have a new keyword.

The process of creating instances of nested, inner, and anonymous inner classes is described in Nested classes.

Class
members
Classes can contain:

Constructors and initializer blocks

243
Functions

Properties

Nested and inner classes

Object declarations

Inheritance
Classes can be derived from each other and form inheritance hierarchies. Learn more about inheritance in Kotlin.

Abstract
classes
A class may be declared abstract, along with some or all of its members. An abstract member does not have an
implementation in its class. You don't need to annotate abstract classes or functions with open.

abstract class Polygon {


abstract fun draw()
}

class Rectangle : Polygon() {


override fun draw() {
// draw the rectangle
}
}

You can override a non-abstract open member with an abstract one.

open class Polygon {


open fun draw() {
// some default polygon drawing method
}
}

abstract class WildShape : Polygon() {


// Classes that inherit WildShape need to provide their own
// draw method instead of using the default on Polygon
abstract override fun draw()
}

Companion
objects
If you need to write a function that can be called without having a class instance but that needs access to the internals of
a class (such as a factory method), you can write it as a member of an object declaration inside that class.

Even more specifically, if you declare a companion object inside your class, you can access its members using only the

244
class name as a qualifier.

Inheritance
All classes in Kotlin have a common superclass, Any, which is the default superclass for a class with no supertypes
declared:

class Example // Implicitly inherits from Any

Any has three methods: equals(), hashCode(), and toString(). Thus, these methods are defined for all Kotlin classes.

By default, Kotlin classes are final – they can’t be inherited. To make a class inheritable, mark it with the open
keyword:

open class Base // Class is open for inheritance

To declare an explicit supertype, place the type after a colon in the class header:

open class Base(p: Int)

class Derived(p: Int) : Base(p)

If the derived class has a primary constructor, the base class can (and must) be initialized in that primary constructor
according to its parameters.

If the derived class has no primary constructor, then each secondary constructor has to initialize the base type using the
super keyword or it has to delegate to another constructor which does. Note that in this case different secondary
constructors can call different constructors of the base type:

class MyView : View {


constructor(ctx: Context) : super(ctx)

constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)


}

Overriding
methods
Kotlin requires explicit modifiers for overridable members and overrides:

open class Shape {


open fun draw() { /*...*/ }
fun fill() { /*...*/ }
}

245
class Circle() : Shape() {
override fun draw() { /*...*/ }
}

The override modifier is required for Circle.draw(). If it were missing, the compiler would complain. If there is no open
modifier on a function, like Shape.fill(), declaring a method with the same signature in a subclass is not allowed, either
with override or without it. The open modifier has no effect when added to members of a final class – a class without an
open modifier.

A member marked override is itself open, so it may be overridden in subclasses. If you want to prohibit re-overriding, use
final:

open class Rectangle() : Shape() {


final override fun draw() { /*...*/ }
}

Overriding
properties
The overriding mechanism works on properties in the same way that it does on methods. Properties declared on a
superclass that are then redeclared on a derived class must be prefaced with override, and they must have a compatible
type. Each declared property can be overridden by a property with an initializer or by a property with a get method:

open class Shape {


open val vertexCount: Int = 0
}

class Rectangle : Shape() {


override val vertexCount = 4
}

You can also override a val property with a var property, but not vice versa. This is allowed because a val property
essentially declares a get method, and overriding it as a var additionally declares a set method in the derived class.

Note that you can use the override keyword as part of the property declaration in a primary constructor:

interface Shape {
val vertexCount: Int
}

class Rectangle(override val vertexCount: Int = 4) : Shape // Always has 4 vertices

class Polygon : Shape {


override var vertexCount: Int = 0 // Can be set to any number later
}

Derived
class
initialization
order

246
During the construction of a new instance of a derived class, the base class initialization is done as the first step
(preceded only by evaluation of the arguments for the base class constructor), which means that it happens before the
initialization logic of the derived class is run.

//sampleStart
open class Base(val name: String) {

init { println("Initializing a base class") }

open val size: Int =


name.length.also { println("Initializing size in the base class: $it") }
}

class Derived(
name: String,
val lastName: String,
) : Base(name.replaceFirstChar { it.uppercase() }.also { println("Argument for the base class:
$it") }) {

init { println("Initializing a derived class") }

override val size: Int =


(super.size + lastName.length).also { println("Initializing size in the derived class:
$it") }
}
//sampleEnd

fun main() {
println("Constructing the derived class(\"hello\", \"world\")")
Derived("hello", "world")
}

This means that when the base class constructor is executed, the properties declared or overridden in the derived class
have not yet been initialized. Using any of those properties in the base class initialization logic (either directly or indirectly
through another overridden open member implementation) may lead to incorrect behavior or a runtime failure. When
designing a base class, you should therefore avoid using open members in the constructors, property initializers, or init
blocks.

Calling
the
superclass
implementation
Code in a derived class can call its superclass functions and property accessor implementations using the super
keyword:

open class Rectangle {


open fun draw() { println("Drawing a rectangle") }
val borderColor: String get() = "black"
}

class FilledRectangle : Rectangle() {


override fun draw() {
super.draw()
println("Filling the rectangle")
}

247
val fillColor: String get() = super.borderColor
}

Inside an inner class, accessing the superclass of the outer class is done using the super keyword qualified with the outer
class name: super@Outer:

open class Rectangle {


open fun draw() { println("Drawing a rectangle") }
val borderColor: String get() = "black"
}

//sampleStart
class FilledRectangle: Rectangle() {
override fun draw() {
val filler = Filler()
filler.drawAndFill()
}

inner class Filler {
fun fill() { println("Filling") }
fun drawAndFill() {
[email protected]() // Calls Rectangle's implementation of draw()
fill()
println("Drawn a filled rectangle with color ${[email protected]}")
// Uses Rectangle's implementation of borderColor's get()
}
}
}
//sampleEnd

fun main() {
val fr = FilledRectangle()
fr.draw()
}

Overriding
rules
In Kotlin, implementation inheritance is regulated by the following rule: if a class inherits multiple implementations of the
same member from its immediate superclasses, it must override this member and provide its own implementation
(perhaps, using one of the inherited ones).

To denote the supertype from which the inherited implementation is taken, use super qualified by the supertype name in
angle brackets, such as super<Base>:

open class Rectangle {


open fun draw() { /* ... */ }
}

interface Polygon {
fun draw() { /* ... */ } // interface members are 'open' by default
}

248
class Square() : Rectangle(), Polygon {
// The compiler requires draw() to be overridden:
override fun draw() {
super<Rectangle>.draw() // call to Rectangle.draw()
super<Polygon>.draw() // call to Polygon.draw()
}
}

It's fine to inherit from both Rectangle and Polygon, but both of them have their implementations of draw(), so you need to
override draw() in Square and provide a separate implementation for it to eliminate the ambiguity.

Properties

Declaring
properties
Properties in Kotlin classes can be declared either as mutable, using the var keyword, or as read-only, using the val
keyword.

class Address {
var name: String = "Holmes, Sherlock"
var street: String = "Baker"
var city: String = "London"
var state: String? = null
var zip: String = "123456"
}

To use a property, simply refer to it by its name:

fun copyAddress(address: Address): Address {


val result = Address() // there's no 'new' keyword in Kotlin
result.name = address.name // accessors are called
result.street = address.street
// ...
return result
}

Getters
and
setters
The full syntax for declaring a property is as follows:

var <propertyName>[: <PropertyType>] [= <property_initializer>]


[<getter>]
[<setter>]

The initializer, getter, and setter are optional. The property type is optional if it can be inferred from the initializer or from

249
the initializer’s or the getter’s return type, as shown below:

var initialized = 1 // has type Int, default getter and setter


// var allByDefault // ERROR: explicit initializer required, default getter and setter implied

The full syntax of a read-only property declaration differs from a mutable one in two ways: it starts with val instead of var
and does not allow a setter:

val simple: Int? // has type Int, default getter, must be initialized in constructor
val inferredType = 1 // has type Int and a default getter

You can define custom accessors for a property. If you define a custom getter, it will be called every time you access the
property (this way you can implement a computed property). Here's an example of a custom getter:

//sampleStart
class Rectangle(val width: Int, val height: Int) {
val square: Int
get() = this.width * this.height
}
//sampleEnd
fun main() {
val rectangle = Rectangle(3, 4)
println("Width=${rectangle.width}, height=${rectangle.height}, square=${rectangle.square}")
}

You can omit the property type if it can be inferred from the getter:

val square get() = this.width * this.height

If you define a custom setter, it will be called every time you assign a value to the property, except its initialization. A
custom setter looks like this:

var stringRepresentation: String


get() = this.toString()
set(value) {
setDataFromString(value) // parses the string and assigns values to other properties
}

By convention, the name of the setter parameter is value, but you can choose a different name if you prefer.

If you need to annotate an accessor or change its visibility, but you don't need to change the default implementation, you
can define the accessor without defining its body:

var setterVisibility: String = "abc"


private set // the setter is private and has the default implementation

var setterWithAnnotation: Any? = null


@Inject set // annotate the setter with Inject

250
Backing
fields
In Kotlin, a field is only used as a part of a property to hold its value in memory. Fields cannot be declared directly.
However, when a property needs a backing field, Kotlin provides it automatically. This backing field can be referenced in
the accessors using the field identifier:

var counter = 0 // the initializer assigns the backing field directly


set(value) {
if (value >= 0)
field = value
// counter = value // ERROR StackOverflow: Using actual name 'counter' would make
setter recursive
}

The field identifier can only be used in the accessors of the property.

A backing field will be generated for a property if it uses the default implementation of at least one of the accessors, or if a
custom accessor references it through the field identifier.

For example, there would be no backing field in the following case:

val isEmpty: Boolean


get() = this.size == 0

Backing
properties
If you want to do something that does not fit into this implicit backing field scheme, you can always fall back to having a
backing property:

private var _table: Map<String, Int>? = null


public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap() // Type parameters are inferred
}
return _table ?: throw AssertionError("Set to null by another thread")
}

On the JVM: Access to private properties with default getters and setters is optimized to avoid function call
overhead.

Compile-time
constants
If the value of a read-only property is known at compile time, mark it as a compile time constant using the const modifier.
Such a property needs to fulfil the following requirements:

It must be a top-level property, or a member of an object declaration or a companion object.

251
It must be initialized with a value of type String or a primitive type

It cannot be a custom getter

Such properties can be used in annotations:

const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"

@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }

Late-initialized
properties
and
variables
Normally, properties declared as having a non-null type must be initialized in the constructor. However, it is often the case
that doing so is not convenient. For example, properties can be initialized through dependency injection, or in the setup
method of a unit test. In these cases, you cannot supply a non-null initializer in the constructor, but you still want to avoid
null checks when referencing the property inside the body of a class.

To handle such cases, you can mark the property with the lateinit modifier:

public class MyTest {


lateinit var subject: TestSubject

@SetUp fun setup() {


subject = TestSubject()
}

@Test fun test() {


subject.method() // dereference directly
}
}

This modifier can be used on var properties declared inside the body of a class (not in the primary constructor, and only
when the property does not have a custom getter or setter), as well as for top-level properties and local variables. The
type of the property or variable must be non-null, and it must not be a primitive type.

Accessing a lateinit property before it has been initialized throws a special exception that clearly identifies the property
being accessed and the fact that it hasn't been initialized.

Checking
whether
a
lateinit
var
is
initialized
To check whether a lateinit var has already been initialized, use .isInitialized on the reference to that property:

if (foo::bar.isInitialized) {
println(foo.bar)
}

This check is only available for properties that are lexically accessible when declared in the same type, in one of the outer
types, or at top level in the same file.

252
Overriding
properties
See Overriding properties

Delegated
properties
The most common kind of property simply reads from (and maybe writes to) a backing field, but custom getters and
setters allow you to use properties so one can implement any sort of behavior of a property. Somewhere in between the
simplicity of the first kind and variety of the second, there are common patterns for what properties can do. A few
examples: lazy values, reading from a map by a given key, accessing a database, notifying a listener on access.

Such common behaviors can be implemented as libraries using delegated properties.

Interfaces
Interfaces in Kotlin can contain declarations of abstract methods, as well as method implementations. What makes them
different from abstract classes is that interfaces cannot store a state. They can have properties, but these need to be
abstract or provide accessor implementations.

An interface is defined using the keyword interface:

interface MyInterface {
fun bar()
fun foo() {
// optional body
}
}

Implementing
interfaces
A class or object can implement one or more interfaces:

class Child : MyInterface {


override fun bar() {
// body
}
}

Properties
in
interfaces
You can declare properties in interfaces. A property declared in an interface can either be abstract or provide
implementations for accessors. Properties declared in interfaces can't have backing fields, and therefore accessors

253
declared in interfaces can't reference them:

interface MyInterface {
val prop: Int // abstract

val propertyWithImplementation: String


get() = "foo"

fun foo() {
print(prop)
}
}

class Child : MyInterface {


override val prop: Int = 29
}

Interfaces
Inheritance
An interface can derive from other interfaces, meaning it can both provide implementations for their members and declare
new functions and properties. Quite naturally, classes implementing such an interface are only required to define the
missing implementations:

interface Named {
val name: String
}

interface Person : Named {


val firstName: String
val lastName: String

override val name: String get() = "$firstName $lastName"
}

data class Employee(


// implementing 'name' is not required
override val firstName: String,
override val lastName: String,
val position: Position
) : Person

Resolving
overriding
conflicts
When you declare many types in your supertype list, you may inherit more than one implementation of the same method:

interface A {
fun foo() { print("A") }
fun bar()
}

interface B {

254
fun foo() { print("B") }
fun bar() { print("bar") }
}

class C : A {
override fun bar() { print("bar") }
}

class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}

override fun bar() {


super<B>.bar()
}
}

Interfaces A and B both declare functions foo() and bar(). Both of them implement foo(), but only B implements bar() (bar()
is not marked as abstract in A, because this is the default for interfaces if the function has no body). Now, if you derive a
concrete class C from A, you have to override bar() and provide an implementation.

However, if you derive D from A and B, you need to implement all the methods that you have inherited from multiple
interfaces, and you need to specify how exactly D should implement them. This rule applies both to methods for which
you've inherited a single implementation (bar()) and to those for which you've inherited multiple implementations (foo()).

Functional
(SAM)
interfaces
An interface with only one abstract method is called a functional interface, or a Single Abstract Method (SAM) interface.
The functional interface can have several non-abstract members but only one abstract member.

To declare a functional interface in Kotlin, use the fun modifier.

fun interface KRunnable {


fun invoke()
}

SAM
conversions
For functional interfaces, you can use SAM conversions that help make your code more concise and readable by using
lambda expressions.

Instead of creating a class that implements a functional interface manually, you can use a lambda expression. With a
SAM conversion, Kotlin can convert any lambda expression whose signature matches the signature of the interface's
single method into the code, which dynamically instantiates the interface implementation.

For example, consider the following Kotlin functional interface:

255
fun interface IntPredicate {
fun accept(i: Int): Boolean
}

If you don't use a SAM conversion, you will need to write code like this:

// Creating an instance of a class


val isEven = object : IntPredicate {
override fun accept(i: Int): Boolean {
return i % 2 == 0
}
}

By leveraging Kotlin's SAM conversion, you can write the following equivalent code instead:

// Creating an instance using lambda


val isEven = IntPredicate { it % 2 == 0 }

A short lambda expression replaces all the unnecessary code.

fun interface IntPredicate {


fun accept(i: Int): Boolean
}

val isEven = IntPredicate { it % 2 == 0 }

fun main() {
println("Is 7 even? - ${isEven.accept(7)}")
}

You can also use SAM conversions for Java interfaces.

Functional
interfaces
vs.
type
aliases
Functional interfaces and type aliases serve different purposes. Type aliases are just names for existing types – they
don't create a new type, while functional interfaces do. You can provide extensions that are specific to a particular
functional interface to be inapplicable for plain functions or their type aliases.

Type aliases can have only one member, while functional interfaces can have multiple non-abstract members and one
abstract member. Functional interfaces can also implement and extend other interfaces.

Functional interfaces are more flexible and provide more capabilities than type aliases, but they can be more costly both
syntactically and at runtime because they can require conversions to a specific interface. When you choose which one to
use in your code, consider your needs:

If your API needs to accept a function (any function) with some specific parameter and return types – use a simple
functional type or define a type alias to give a shorter name to the corresponding functional type.

256
If your API accepts a more complex entity than a function – for example, it has non-trivial contracts and/or
operations on it that can't be expressed in a functional type's signature – declare a separate functional interface for
it.

Visibility
modifiers
Classes, objects, interfaces, constructors, and functions, as well as properties and their setters, can have visibility
modifiers. Getters always have the same visibility as their properties.

There are four visibility modifiers in Kotlin: private, protected, internal, and public. The default visibility is public.

On this page, you'll learn how the modifiers apply to different types of declaring scopes.

Packages
Functions, properties, classes, objects, and interfaces can be declared at the "top-level" directly inside a package:

// file name: example.kt


package foo

fun baz() { ... }


class Bar { ... }

If you don’t use a visibility modifier, public is used by default, which means that your declarations will be visible
everywhere.

If you mark a declaration as private, it will only be visible inside the file that contains the declaration.

If you mark it as internal, it will be visible everywhere in the same module.

The protected modifier is not available for top-level declarations.

To use a visible top-level declaration from another package, you should import it.

Examples:

// file name: example.kt


package foo

private fun foo() { ... } // visible inside example.kt

public var bar: Int = 5 // property is visible everywhere


private set // setter is visible only in example.kt

internal val baz = 6 // visible inside the same module

257
Class
members
For members declared inside a class:

private means that the member is visible inside this class only (including all its members).

protected means that the member has the same visibility as one marked as private, but that it is also visible in
subclasses.

internal means that any client inside this module who sees the declaring class sees its internal members.

public means that any client who sees the declaring class sees its public members.

In Kotlin, an outer class does not see private members of its inner classes.

If you override a protected or an internal member and do not specify the visibility explicitly, the overriding member will
also have the same visibility as the original.

Examples:

open class Outer {


private val a = 1
protected open val b = 2
internal open val c = 3
val d = 4 // public by default

protected class Nested {
public val e: Int = 5
}
}

class Subclass : Outer() {


// a is not visible
// b, c and d are visible
// Nested and e are visible

override val b = 5 // 'b' is protected


override val c = 7 // 'c' is internal
}

class Unrelated(o: Outer) {


// o.a, o.b are not visible
// o.c and o.d are visible (same module)
// Outer.Nested is not visible, and Nested::e is not visible either
}

Constructors
Use the following syntax to specify the visibility of the primary constructor of a class:

258
You need to add an explicit constructor keyword.

class C private constructor(a: Int) { ... }

Here the constructor is private. By default, all constructors are public, which effectively amounts to them being visible
everywhere the class is visible (this means that a constructor of an internal class is only visible within the same module).

Local
declarations
Local variables, functions, and classes can't have visibility modifiers.

Modules
The internal visibility modifier means that the member is visible within the same module. More specifically, a module is a
set of Kotlin files compiled together, for example:

An IntelliJ IDEA module.

A Maven project.

A Gradle source set (with the exception that the test source set can access the internal declarations of main).

A set of files compiled with one invocation of the <kotlinc> Ant task.

Extensions
Kotlin provides the ability to extend a class with new functionality without having to inherit from the class or use design
patterns such as Decorator. This is done via special declarations called extensions.

For example, you can write new functions for a class from a third-party library that you can't modify. Such functions can
be called in the usual way, as if they were methods of the original class. This mechanism is called an extension function.
There are also extension properties that let you define new properties for existing classes.

Extension
functions
To declare an extension function, prefix its name with a receiver type, which refers to the type being extended. The
following adds a swap function to MutableList<Int>:

fun MutableList<Int>.swap(index1: Int, index2: Int) {


val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp

259
}

The this keyword inside an extension function corresponds to the receiver object (the one that is passed before the dot).
Now, you can call such a function on any MutableList<Int>:

val list = mutableListOf(1, 2, 3)


list.swap(0, 2) // 'this' inside 'swap()' will hold the value of 'list'

This function makes sense for any MutableList<T>, and you can make it generic:

fun <T> MutableList<T>.swap(index1: Int, index2: Int) {


val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp
}

You need to declare the generic type parameter before the function name to make it available in the receiver type
expression. For more information about generics, see generic functions.

Extensions
are
resolved
statically
Extensions do not actually modify the classes they extend. By defining an extension, you are not inserting new members
into a class, only making new functions callable with the dot-notation on variables of this type.

Extension functions are dispatched statically, which means they are not virtual by receiver type. An extension function
being called is determined by the type of the expression on which the function is invoked, not by the type of the result
from evaluating that expression at runtime. For example:

fun main() {
//sampleStart
open class Shape
class Rectangle: Shape()

fun Shape.getName() = "Shape"
fun Rectangle.getName() = "Rectangle"

fun printClassName(s: Shape) {
println(s.getName())
}

printClassName(Rectangle())
//sampleEnd
}

This example prints Shape, because the extension function called depends only on the declared type of the parameter s,
which is the Shape class.

If a class has a member function, and an extension function is defined which has the same receiver type, the same name,
and is applicable to given arguments, the member always wins. For example:

260
fun main() {
//sampleStart
class Example {
fun printFunctionType() { println("Class method") }
}

fun Example.printFunctionType() { println("Extension function") }

Example().printFunctionType()
//sampleEnd
}

This code prints Class method.

However, it's perfectly OK for extension functions to overload member functions that have the same name but a different
signature:

fun main() {
//sampleStart
class Example {
fun printFunctionType() { println("Class method") }
}

fun Example.printFunctionType(i: Int) { println("Extension function #$i") }

Example().printFunctionType(1)
//sampleEnd
}

Nullable
receiver
Note that extensions can be defined with a nullable receiver type. These extensions can be called on an object variable
even if its value is null, and they can check for this == null inside the body.

This way, you can call toString() in Kotlin without checking for null, as the check happens inside the extension function:

fun Any?.toString(): String {


if (this == null) return "null"
// after the null check, 'this' is autocast to a non-null type, so the toString() below
// resolves to the member function of the Any class
return toString()
}

Extension
properties
Kotlin supports extension properties much like it supports functions:

val <T> List<T>.lastIndex: Int


get() = size - 1

261
Since extensions do not actually insert members into classes, there's no efficient way for an extension property
to have a backing field. This is why initializers are not allowed for extension properties. Their behavior can only
be defined by explicitly providing getters/setters.

Example:

val House.number = 1 // error: initializers are not allowed for extension properties

Companion
object
extensions
If a class has a companion object defined, you can also define extension functions and properties for the companion
object. Just like regular members of the companion object, they can be called using only the class name as the qualifier:

class MyClass {
companion object { } // will be called "Companion"
}

fun MyClass.Companion.printCompanion() { println("companion") }

fun main() {
MyClass.printCompanion()
}

Scope
of
extensions
In most cases, you define extensions on the top level, directly under packages:

package org.example.declarations

fun List<String>.getLongestString() { /*...*/}

To use an extension outside its declaring package, import it at the call site:

package org.example.usage

import org.example.declarations.getLongestString

fun main() {
val list = listOf("red", "green", "blue")
list.getLongestString()
}

262
See Imports for more information.

Declaring
extensions
as
members
You can declare extensions for one class inside another class. Inside such an extension, there are multiple implicit
receivers- objects whose members can be accessed without a qualifier. An instance of a class in which the extension is
declared is called a dispatch receiver, and an instance of the receiver type of the extension method is called an extension
receiver.

class Host(val hostname: String) {


fun printHostname() { print(hostname) }
}

class Connection(val host: Host, val port: Int) {


fun printPort() { print(port) }

fun Host.printConnectionString() {
printHostname() // calls Host.printHostname()
print(":")
printPort() // calls Connection.printPort()
}

fun connect() {
/*...*/
host.printConnectionString() // calls the extension function
}
}

fun main() {
Connection(Host("kotl.in"), 443).connect()
//Host("kotl.in").printConnectionString() // error, the extension function is unavailable
outside Connection
}

In the event of a name conflict between the members of a dispatch receiver and an extension receiver, the extension
receiver takes precedence. To refer to the member of the dispatch receiver, you can use the qualified this syntax.

class Connection {
fun Host.getConnectionString() {
toString() // calls Host.toString()
[email protected]() // calls Connection.toString()
}
}

Extensions declared as members can be declared as open and overridden in subclasses. This means that the dispatch of
such functions is virtual with regard to the dispatch receiver type, but static with regard to the extension receiver type.

open class Base { }

class Derived : Base() { }

open class BaseCaller {

263
open fun Base.printFunctionInfo() {
println("Base extension function in BaseCaller")
}

open fun Derived.printFunctionInfo() {


println("Derived extension function in BaseCaller")
}

fun call(b: Base) {


b.printFunctionInfo() // call the extension function
}
}

class DerivedCaller: BaseCaller() {


override fun Base.printFunctionInfo() {
println("Base extension function in DerivedCaller")
}

override fun Derived.printFunctionInfo() {


println("Derived extension function in DerivedCaller")
}
}

fun main() {
BaseCaller().call(Base()) // "Base extension function in BaseCaller"
DerivedCaller().call(Base()) // "Base extension function in DerivedCaller" - dispatch
receiver is resolved virtually
DerivedCaller().call(Derived()) // "Base extension function in DerivedCaller" - extension
receiver is resolved statically
}

Note
on
visibility
Extensions utilize the same visibility modifiers as regular functions declared in the same scope would. For example:

An extension declared at the top level of a file has access to the other private top-level declarations in the same file.

If an extension is declared outside its receiver type, it cannot access the receiver's private or protected members.

Data
classes
It is not unusual to create classes whose main purpose is to hold data. In such classes, some standard functionality and
some utility functions are often mechanically derivable from the data. In Kotlin, these are called data classes and are
marked with data:

data class User(val name: String, val age: Int)

The compiler automatically derives the following members from all properties declared in the primary constructor:

equals()/ hashCode() pair

264
toString() of the form "User(name=John, age=42)"

componentN() functions corresponding to the properties in their order of declaration.

copy() function (see below).

To ensure consistency and meaningful behavior of the generated code, data classes have to fulfill the following
requirements:

The primary constructor needs to have at least one parameter.

All primary constructor parameters need to be marked as val or var.

Data classes cannot be abstract, open, sealed, or inner.

Additionally, the generation of data class members follows these rules with regard to the members’ inheritance:

If there are explicit implementations of equals(), hashCode(), or toString() in the data class body or final
implementations in a superclass, then these functions are not generated, and the existing implementations are used.

If a supertype has componentN() functions that are open and return compatible types, the corresponding functions are
generated for the data class and override those of the supertype. If the functions of the supertype cannot be
overridden due to incompatible signatures or due to their being final, an error is reported.

Providing explicit implementations for the componentN() and copy() functions is not allowed.

Data classes may extend other classes (see Sealed classes for examples).

On the JVM, if the generated class needs to have a parameterless constructor, default values for the properties
have to be specified (see Constructors).

data class User(val name: String = "", val age: Int = 0)

Properties
declared
in
the
class
body
The compiler only uses the properties defined inside the primary constructor for the automatically generated functions. To
exclude a property from the generated implementations, declare it inside the class body:

data class Person(val name: String) {


var age: Int = 0
}

Only the property name will be used inside the toString(), equals(), hashCode(), and copy() implementations, and there will
only be one component function component1(). While two Person objects can have different ages, they will be treated as
equal.

265
data class Person(val name: String) {
var age: Int = 0
}
fun main() {
//sampleStart
val person1 = Person("John")
val person2 = Person("John")
person1.age = 10
person2.age = 20
//sampleEnd
println("person1 == person2: ${person1 == person2}")
println("person1 with age ${person1.age}: ${person1}")
println("person2 with age ${person2.age}: ${person2}")
}

Copying
Use the copy() function to copy an object, allowing you to alter some of its properties while keeping the rest unchanged.
The implementation of this function for the User class above would be as follows:

fun copy(name: String = this.name, age: Int = this.age) = User(name, age)

You can then write the following:

val jack = User(name = "Jack", age = 1)


val olderJack = jack.copy(age = 2)

Data
classes
and
destructuring
declarations
Component functions generated for data classes make it possible to use them in destructuring declarations:

val jane = User("Jane", 35)


val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"

Standard
data
classes
The standard library provides the Pair and Triple classes. In most cases, though, named data classes are a better design
choice because they make the code more readable by providing meaningful names for the properties.

Sealed
classes
Sealed classes and interfaces represent restricted class hierarchies that provide more control over inheritance. All direct

266
subclasses of a sealed class are known at compile time. No other subclasses may appear after a module with the sealed
class is compiled. For example, third-party clients can't extend your sealed class in their code. Thus, each instance of a
sealed class has a type from a limited set that is known when this class is compiled.

The same works for sealed interfaces and their implementations: once a module with a sealed interface is compiled, no
new implementations can appear.

In some sense, sealed classes are similar to enum classes: the set of values for an enum type is also restricted, but each
enum constant exists only as a single instance, whereas a subclass of a sealed class can have multiple instances, each
with its own state.

As an example, consider a library's API. It's likely to contain error classes to let the library users handle errors that it can
throw. If the hierarchy of such error classes includes interfaces or abstract classes visible in the public API, then nothing
prevents implementing or extending them in the client code. However, the library doesn't know about errors declared
outside it, so it can't treat them consistently with its own classes. With a sealed hierarchy of error classes, library authors
can be sure that they know all possible error types and no other ones can appear later.

To declare a sealed class or interface, put the sealed modifier before its name:

sealed interface Error

sealed class IOError(): Error

class FileReadError(val f: File): IOError()


class DatabaseError(val source: DataSource): IOError()

object RuntimeError : Error

A sealed class is abstract by itself, it cannot be instantiated directly and can have abstract members.

Constructors of sealed classes can have one of two visibilities: protected (by default) or private:

sealed class IOError {


constructor() { /*...*/ } // protected by default
private constructor(description: String): this() { /*...*/ } // private is OK
// public constructor(code: Int): this() {} // Error: public and internal are not allowed
}

Location
of
direct
subclasses
Direct subclasses of sealed classes and interfaces must be declared in the same package. They may be top-level or
nested inside any number of other named classes, named interfaces, or named objects. Subclasses can have any
visibility as long as they are compatible with normal inheritance rules in Kotlin.

Subclasses of sealed classes must have a proper qualified name. They can't be local nor anonymous objects.

267
enum classes can't extend a sealed class (as well as any other class), but they can implement sealed
interfaces.

These restrictions don't apply to indirect subclasses. If a direct subclass of a sealed class is not marked as sealed, it can
be extended in any ways that its modifiers allow:

sealed interface Error // has implementations only in same package and module

sealed class IOError(): Error // extended only in same package and module
open class CustomError(): Error // can be extended wherever it's visible

Inheritance
in
multiplatform
projects
There is one more inheritance restriction in multiplatform projects: direct subclasses of sealed classes must reside in the
same source set. It applies to sealed classes without the expect and actual modifiers.

If a sealed class is declared as expect in a common source set and have actual implementations in platform source sets,
both expect and actual versions can have subclasses in their source sets. Moreover, if you use a hierarchical structure,
you can create subclasses in any source set between the expect and actual declarations.

Learn more about the hierarchical structure of multiplatform projects.

Sealed
classes
and
when
expression
The key benefit of using sealed classes comes into play when you use them in a when expression. If it's possible to verify
that the statement covers all cases, you don't need to add an else clause to the statement. However, this works only if
you use when as an expression (using the result) and not as a statement:

fun log(e: Error) = when(e) {


is FileReadError -> { println("Error while reading file ${e.file}") }
is DatabaseError -> { println("Error while reading from database ${e.source}") }
RuntimeError -> { println("Runtime error") }
// the `else` clause is not required because all the cases are covered
}

when expressions on expect sealed classes in the common code of multiplatform projects still require an else
branch. This happens because subclasses of actual platform implementations aren't known in the common
code.

Generics:
in,
out,
where

268
Classes in Kotlin can have type parameters, just like in Java:

class Box<T>(t: T) {
var value = t
}

To create an instance of such a class, simply provide the type arguments:

val box: Box<Int> = Box<Int>(1)

But if the parameters can be inferred, for example, from the constructor arguments, you can omit the type arguments:

val box = Box(1) // 1 has type Int, so the compiler figures out that it is Box<Int>

Variance
One of the trickiest aspects of Java's type system is the wildcard types (see Java Generics FAQ). Kotlin doesn't have
these. Instead, Kotlin has declaration-site variance and type projections.

Let's think about why Java needs these mysterious wildcards. The problem is explained well in Effective Java, 3rd
Edition, Item 31: Use bounded wildcards to increase API flexibility. First, generic types in Java are invariant, meaning that
List<String> is not a subtype of List<Object>. If List were not invariant, it would have been no better than Java's arrays,
as the following code would have compiled but caused an exception at runtime:

// Java
List<String> strs = new ArrayList<String>();
List<Object> objs = strs; // !!! A compile-time error here saves us from a runtime exception
later.
objs.add(1); // Put an Integer into a list of Strings
String s = strs.get(0); // !!! ClassCastException: Cannot cast Integer to String

Java prohibits such things in order to guarantee run-time safety. But this has implications. For example, consider the
addAll() method from the Collection interface. What's the signature of this method? Intuitively, you'd write it this way:

// Java
interface Collection<E> ... {
void addAll(Collection<E> items);
}

But then, you would not be able to do the following (which is perfectly safe):

// Java
void copyAll(Collection<Object> to, Collection<String> from) {
to.addAll(from);
// !!! Would not compile with the naive declaration of addAll:
// Collection<String> is not a subtype of Collection<Object>

269
}

(In Java, you probably learned this the hard way, see Effective Java, 3rd Edition, Item 28: Prefer lists to arrays)

That's why the actual signature of addAll() is the following:

// Java
interface Collection<E> ... {
void addAll(Collection<? extends E> items);
}

The wildcard type argument ? extends E indicates that this method accepts a collection of objects of E or a subtype of E,
not just E itself. This means that you can safely read E 's from items (elements of this collection are instances of a
subclass of E), but cannot write to it as you don't know what objects comply with that unknown subtype of E. In return for
this limitation, you get the desired behavior: Collection<String> is a subtype of Collection<? extends Object>. In other
words, the wildcard with an extends -bound (upper bound) makes the type covariant.

The key to understanding why this works is rather simple: if you can only take items from a collection, then using a
collection of String s and reading Object s from it is fine. Conversely, if you can only put items into the collection, it's okay
to take a collection of Object s and put String s into it: in Java there is List<? super String>, a supertype of List<Object>.

The latter is called contravariance, and you can only call methods that take String as an argument on List<? super String>
(for example, you can call add(String) or set(int, String)). If you call something that returns T in List<T>, you don't get a
String, but rather an Object.

Joshua Bloch gives the name Producers to objects you only read from and Consumers to those you only write to. He
recommends:

"For maximum flexibility, use wildcard types on input parameters that represent producers or consumers", and
proposes the following mnemonic:

PECS stands for Producer-Extends, Consumer-Super.

If you use a producer-object, say, List<? extends Foo>, you are not allowed to call add() or set() on this object,
but this does not mean that it is immutable: for example, nothing prevents you from calling clear() to remove all
the items from the list, since clear() does not take any parameters at all.

The only thing guaranteed by wildcards (or other types of variance) is type safety. Immutability is a completely
different story.

Declaration-site
variance
Let's suppose that there is a generic interface Source<T> that does not have any methods that take T as a parameter,
only methods that return T:

270
// Java
interface Source<T> {
T nextT();
}

Then, it would be perfectly safe to store a reference to an instance of Source<String> in a variable of type
Source<Object>- there are no consumer-methods to call. But Java does not know this, and still prohibits it:

// Java
void demo(Source<String> strs) {
Source<Object> objects = strs; // !!! Not allowed in Java
// ...
}

To fix this, you should declare objects of type Source<? extends Object>. Doing so is meaningless, because you can call
all the same methods on such a variable as before, so there's no value added by the more complex type. But the
compiler does not know that.

In Kotlin, there is a way to explain this sort of thing to the compiler. This is called declaration-site variance: you can
annotate the type parameter T of Source to make sure that it is only returned (produced) from members of Source<T>,
and never consumed. To do this, use the out modifier:

interface Source<out T> {


fun nextT(): T
}

fun demo(strs: Source<String>) {


val objects: Source<Any> = strs // This is OK, since T is an out-parameter
// ...
}

The general rule is this: when a type parameter T of a class C is declared out, it may occur only in the out -position in the
members of C, but in return C<Base> can safely be a supertype of C<Derived>.

In other words, you can say that the class C is covariant in the parameter T, or that T is a covariant type parameter. You
can think of C as being a producer of T 's, and NOT a consumer of T 's.

The out modifier is called a variance annotation, and since it is provided at the type parameter declaration site, it provides
declaration-site variance. This is in contrast with Java's use-site variance where wildcards in the type usages make the
types covariant.

In addition to out, Kotlin provides a complementary variance annotation: in. It makes a type parameter contravariant,
meaning it can only be consumed and never produced. A good example of a contravariant type is Comparable:

interface Comparable<in T> {


operator fun compareTo(other: T): Int
}

fun demo(x: Comparable<Number>) {


x.compareTo(1.0) // 1.0 has type Double, which is a subtype of Number

271
// Thus, you can assign x to a variable of type Comparable<Double>
val y: Comparable<Double> = x // OK!
}

The words in and out seem to be self-explanatory (as they’ve already been used successfully in C# for quite some
time), and so the mnemonic mentioned above is not really needed. It can in fact be rephrased at a higher level of
abstraction:

The Existential Transformation: Consumer in, Producer out!:-)

Type
projections

Use-site
variance:
type
projections
It is very easy to declare a type parameter T as out and avoid trouble with subtyping on the use site, but some classes
can't actually be restricted to only return T 's! A good example of this is Array:

class Array<T>(val size: Int) {


operator fun get(index: Int): T { ... }
operator fun set(index: Int, value: T) { ... }
}

This class can be neither co- nor contravariant in T. And this imposes certain inflexibilities. Consider the following
function:

fun copy(from: Array<Any>, to: Array<Any>) {


assert(from.size == to.size)
for (i in from.indices)
to[i] = from[i]
}

This function is supposed to copy items from one array to another. Let's try to apply it in practice:

val ints: Array<Int> = arrayOf(1, 2, 3)


val any = Array<Any>(3) { "" }
copy(ints, any)
// ^ type is Array<Int> but Array<Any> was expected

Here you run into the same familiar problem: Array<T> is invariant in T, and so neither Array<Int> nor Array<Any> is a
subtype of the other. Why not? Again, this is because copy could have an unexpected behavior, for example, it may
attempt to write a String to from, and if you actually pass an array of Int there, a ClassCastException will be thrown later.

To prohibit the copy function from writing to from, you can do the following:

fun copy(from: Array<out Any>, to: Array<Any>) { ... }

272
This is type projection, which means that from is not a simple array, but is rather a restricted (projected) one. You can only
call methods that return the type parameter T, which in this case means that you can only call get(). This is our approach
to use-site variance, and it corresponds to Java's Array<? extends Object> while being slightly simpler.

You can project a type with in as well:

fun fill(dest: Array<in String>, value: String) { ... }

Array<in String> corresponds to Java's Array<? super String>. This means that you can pass an array of CharSequence
or an array of Object to the fill() function.

Star-projections
Sometimes you want to say that you know nothing about the type argument, but you still want to use it in a safe way. The
safe way here is to define such a projection of the generic type, that every concrete instantiation of that generic type will
be a subtype of that projection.

Kotlin provides so-called star-projection syntax for this:

For Foo<out T : TUpper>, where T is a covariant type parameter with the upper bound TUpper, Foo<*> is equivalent to
Foo<out TUpper>. This means that when the T is unknown you can safely read values of TUpper from Foo<*>.

For Foo<in T>, where T is a contravariant type parameter, Foo<*> is equivalent to Foo<in Nothing>. This means there
is nothing you can write to Foo<*> in a safe way when T is unknown.

For Foo<T : TUpper>, where T is an invariant type parameter with the upper bound TUpper, Foo<*> is equivalent to
Foo<out TUpper> for reading values and to Foo<in Nothing> for writing values.

If a generic type has several type parameters, each of them can be projected independently. For example, if the type is
declared as interface Function<in T, out U> you could use the following star-projections:

Function<*, String> means Function<in Nothing, String>.

Function<Int, *> means Function<Int, out Any?>.

Function<*, *> means Function<in Nothing, out Any?>.

Star-projections are very much like Java's raw types, but safe.

Generic
functions
Classes aren’t the only declarations that can have type parameters. Functions can, too. Type parameters are placed
before the name of the function:

fun <T> singletonList(item: T): List<T> {


// ...

273
}

fun <T> T.basicToString(): String { // extension function


// ...
}

To call a generic function, specify the type arguments at the call site after the name of the function:

val l = singletonList<Int>(1)

Type arguments can be omitted if they can be inferred from the context, so the following example works as well:

val l = singletonList(1)

Generic
constraints
The set of all possible types that can be substituted for a given type parameter may be restricted by generic constraints.

Upper
bounds
The most common type of constraint is an upper bound, which corresponds to Java's extends keyword:

fun <T : Comparable<T>> sort(list: List<T>) { ... }

The type specified after a colon is the upper bound, indicating that only a subtype of Comparable<T> can be substituted
for T. For example:

sort(listOf(1, 2, 3)) // OK. Int is a subtype of Comparable<Int>


sort(listOf(HashMap<Int, String>())) // Error: HashMap<Int, String> is not a subtype of
Comparable<HashMap<Int, String>>

The default upper bound (if there was none specified) is Any?. Only one upper bound can be specified inside the angle
brackets. If the same type parameter needs more than one upper bound, you need a separate where -clause:

fun <T> copyWhenGreater(list: List<T>, threshold: T): List<String>


where T : CharSequence,
T : Comparable<T> {
return list.filter { it > threshold }.map { it.toString() }
}

The passed type must satisfy all conditions of the where clause simultaneously. In the above example, the T type must
implement both CharSequence and Comparable.

274
Type
erasure
The type safety checks that Kotlin performs for generic declaration usages are done at compile time. At runtime, the
instances of generic types do not hold any information about their actual type arguments. The type information is said to
be erased. For example, the instances of Foo<Bar> and Foo<Baz?> are erased to just Foo<*>.

Therefore, there is no general way to check whether an instance of a generic type was created with certain type
arguments at runtime, and the compiler prohibits such is -checks.

Type casts to generic types with concrete type arguments, for example, foo as List<String>, cannot be checked at
runtime. These unchecked casts can be used when type safety is implied by high-level program logic but cannot be
inferred directly by the compiler. The compiler issues a warning on unchecked casts, and at runtime, only the non-generic
part is checked (equivalent to foo as List<*>).

The type arguments of generic function calls are also only checked at compile time. Inside the function bodies, the type
parameters cannot be used for type checks, and type casts to type parameters (foo as T) are unchecked. However, reified
type parameters of inline functions are substituted by the actual type arguments in the inlined function body at the call
sites and so can be used for type checks and casts, with the same restrictions for instances of generic types as described
above.

Nested
and
inner
classes
Classes can be nested in other classes:

class Outer {
private val bar: Int = 1
class Nested {
fun foo() = 2
}
}

val demo = Outer.Nested().foo() // == 2

You can also use interfaces with nesting. All combinations of classes and interfaces are possible: You can nest interfaces
in classes, classes in interfaces, and interfaces in interfaces.

interface OuterInterface {
class InnerClass
interface InnerInterface
}

class OuterClass {
class InnerClass
interface InnerInterface
}

275
Inner
classes
A nested class marked as inner can access the members of its outer class. Inner classes carry a reference to an object of
an outer class:

class Outer {
private val bar: Int = 1
inner class Inner {
fun foo() = bar
}
}

val demo = Outer().Inner().foo() // == 1

See Qualified this expressions to learn about disambiguation of this in inner classes.

Anonymous
inner
classes
Anonymous inner class instances are created using an object expression:

window.addMouseListener(object : MouseAdapter() {

override fun mouseClicked(e: MouseEvent) { ... }

override fun mouseEntered(e: MouseEvent) { ... }


})

On the JVM, if the object is an instance of a functional Java interface (that means a Java interface with a single
abstract method), you can create it using a lambda expression prefixed with the type of the interface:

val listener = ActionListener { println("clicked") }

Enum
classes
The most basic use case for enum classes is the implementation of type-safe enums:

enum class Direction {


NORTH, SOUTH, WEST, EAST
}

Each enum constant is an object. Enum constants are separated by commas.

Since each enum is an instance of the enum class, it can be initialized as:

276
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}

Anonymous
classes
Enum constants can declare their own anonymous classes with their corresponding methods, as well as with overriding
base methods.

enum class ProtocolState {


WAITING {
override fun signal() = TALKING
},

TALKING {
override fun signal() = WAITING
};

abstract fun signal(): ProtocolState


}

If the enum class defines any members, separate the constant definitions from the member definitions with a semicolon.

Implementing
interfaces
in
enum
classes
An enum class can implement an interface (but it cannot derive from a class), providing either a common implementation
of interface members for all of the entries, or separate implementations for each entry within its anonymous class. This is
done by adding the interfaces you want to implement to the enum class declaration as follows:

import java.util.function.BinaryOperator
import java.util.function.IntBinaryOperator

//sampleStart
enum class IntArithmetics : BinaryOperator<Int>, IntBinaryOperator {
PLUS {
override fun apply(t: Int, u: Int): Int = t + u
},
TIMES {
override fun apply(t: Int, u: Int): Int = t * u
};

override fun applyAsInt(t: Int, u: Int) = apply(t, u)
}
//sampleEnd

fun main() {
val a = 13

277
val b = 31
for (f in IntArithmetics.values()) {
println("$f($a, $b) = ${f.apply(a, b)}")
}
}

Working
with
enum
constants
Enum classes in Kotlin have synthetic methods for listing the defined enum constants and getting an enum constant by
its name. The signatures of these methods are as follows (assuming the name of the enum class is EnumClass):

EnumClass.valueOf(value: String): EnumClass


EnumClass.values(): Array<EnumClass>

The valueOf() method throws an IllegalArgumentException if the specified name does not match any of the enum
constants defined in the class.

You can access the constants in an enum class in a generic way using the enumValues<T>() and enumValueOf<T>()
functions:

enum class RGB { RED, GREEN, BLUE }

inline fun <reified T : Enum<T>> printAllValues() {


print(enumValues<T>().joinToString { it.name })
}

printAllValues<RGB>() // prints RED, GREEN, BLUE

Every enum constant has properties for obtaining its name and position in the enum class declaration:

val name: String


val ordinal: Int

The enum constants also implement the Comparable interface, with the natural order being the order in which they are
defined in the enum class.

Inline
classes
Sometimes it is necessary for business logic to create a wrapper around some type. However, it introduces runtime
overhead due to additional heap allocations. Moreover, if the wrapped type is primitive, the performance hit is terrible,
because primitive types are usually heavily optimized by the runtime, while their wrappers don't get any special treatment.

To solve such issues, Kotlin introduces a special kind of class called an inline class. Inline classes are a subset of value-
based classes. They don't have an identity and can only hold values.

278
To declare an inline class, use the value modifier before the name of the class:

value class Password(private val s: String)

To declare an inline class for the JVM backend, use the value modifier along with the @JvmInline annotation before the
class declaration:

// For JVM backends


@JvmInline
value class Password(private val s: String)

The inline modifier for inline classes is deprecated.

An inline class must have a single property initialized in the primary constructor. At runtime, instances of the inline class
will be represented using this single property (see details about runtime representation below):

// No actual instantiation of class 'Password' happens


// At runtime 'securePassword' contains just 'String'
val securePassword = Password("Don't try this in production")

This is the main feature of inline classes, which inspired the name inline: data of the class is inlined into its usages (similar
to how content of inline functions is inlined to call sites).

Members
Inline classes support some functionality of regular classes. In particular, they are allowed to declare properties and
functions, and have the init block:

@JvmInline
value class Name(val s: String) {
init {
require(s.length > 0) { }
}

val length: Int


get() = s.length

fun greet() {
println("Hello, $s")
}
}

fun main() {
val name = Name("Kotlin")
name.greet() // method `greet` is called as a static method
println(name.length) // property getter is called as a static method
}

279
Inline class properties cannot have backing fields. They can only have simple computable properties (no lateinit
/delegated properties).

Inheritance
Inline classes are allowed to inherit from interfaces:

interface Printable {
fun prettyPrint(): String
}

@JvmInline
value class Name(val s: String) : Printable {
override fun prettyPrint(): String = "Let's $s!"
}

fun main() {
val name = Name("Kotlin")
println(name.prettyPrint()) // Still called as a static method
}

It is forbidden for inline classes to participate in a class hierarchy. This means that inline classes cannot extend other
classes and must be final.

Representation
In generated code, the Kotlin compiler keeps a wrapper for each inline class. Inline class instances can be represented at
runtime either as wrappers or as the underlying type. This is similar to how Int can be represented either as a primitive int
or as the wrapper Integer.

The Kotlin compiler will prefer using underlying types instead of wrappers to produce the most performant and optimized
code. However, sometimes it is necessary to keep wrappers around. As a rule of thumb, inline classes are boxed
whenever they are used as another type.

interface I

@JvmInline
value class Foo(val i: Int) : I

fun asInline(f: Foo) {}


fun <T> asGeneric(x: T) {}
fun asInterface(i: I) {}
fun asNullable(i: Foo?) {}

fun <T> id(x: T): T = x

fun main() {
val f = Foo(42)

280
asInline(f) // unboxed: used as Foo itself
asGeneric(f) // boxed: used as generic type T
asInterface(f) // boxed: used as type I
asNullable(f) // boxed: used as Foo?, which is different from Foo

// below, 'f' first is boxed (while being passed to 'id') and then unboxed (when returned
from 'id')
// In the end, 'c' contains unboxed representation (just '42'), as 'f'
val c = id(f)
}

Because inline classes may be represented both as the underlying value and as a wrapper, referential equality is pointless
for them and is therefore prohibited.

Mangling
Since inline classes are compiled to their underlying type, it may lead to various obscure errors, for example unexpected
platform signature clashes:

@JvmInline
value class UInt(val x: Int)

// Represented as 'public final void compute(int x)' on the JVM


fun compute(x: Int) { }

// Also represented as 'public final void compute(int x)' on the JVM!


fun compute(x: UInt) { }

To mitigate such issues, functions using inline classes are mangled by adding some stable hashcode to the function
name. Therefore, fun compute(x: UInt) will be represented as public final void compute-<hashcode>(int x), which solves
the clash problem.

The mangling scheme has been changed in Kotlin 1.4.30. Use the -Xuse-14-inline-classes-mangling-scheme
compiler flag to force the compiler to use the old 1.4.0 mangling scheme and preserve binary compatibility.

Calling
from
Java
code
You can call functions that accept inline classes from Java code. To do so, you should manually disable mangling: add
the @JvmName annotation before the function declaration:

@JvmInline
value class UInt(val x: Int)

fun compute(x: Int) { }

@JvmName("computeUInt")
fun compute(x: UInt) { }

281
Inline
classes
vs
type
aliases
At first sight, inline classes seem very similar to type aliases. Indeed, both seem to introduce a new type and both will be
represented as the underlying type at runtime.

However, the crucial difference is that type aliases are assignment-compatible with their underlying type (and with other
type aliases with the same underlying type), while inline classes are not.

In other words, inline classes introduce a truly new type, contrary to type aliases which only introduce an alternative name
(alias) for an existing type:

typealias NameTypeAlias = String

@JvmInline
value class NameInlineClass(val s: String)

fun acceptString(s: String) {}


fun acceptNameTypeAlias(n: NameTypeAlias) {}
fun acceptNameInlineClass(p: NameInlineClass) {}

fun main() {
val nameAlias: NameTypeAlias = ""
val nameInlineClass: NameInlineClass = NameInlineClass("")
val string: String = ""

acceptString(nameAlias) // OK: pass alias instead of underlying type


acceptString(nameInlineClass) // Not OK: can't pass inline class instead of underlying type

// And vice versa:


acceptNameTypeAlias(string) // OK: pass underlying type instead of alias
acceptNameInlineClass(string) // Not OK: can't pass underlying type instead of inline class
}

Object
expressions
and
declarations
Sometimes you need to create an object that is a slight modification of some class, without explicitly declaring a new
subclass for it. Kotlin can handle this with object expressions and object declarations.

Object
expressions
Object expressions create objects of anonymous classes, that is, classes that aren't explicitly declared with the class
declaration. Such classes are useful for one-time use. You can define them from scratch, inherit from existing classes, or
implement interfaces. Instances of anonymous classes are also called anonymous objects because they are defined by
an expression, not a name.

Creating
anonymous
objects
from
scratch
Object expressions start with the object keyword.

282
If you just need an object that doesn’t have any nontrivial supertypes, write its members in curly braces after object:

fun main() {
//sampleStart
val helloWorld = object {
val hello = "Hello"
val world = "World"
// object expressions extend Any, so `override` is required on `toString()`
override fun toString() = "$hello $world"
}
//sampleEnd
print(helloWorld)
}

Inheriting
anonymous
objects
from
supertypes
To create an object of an anonymous class that inherits from some type (or types), specify this type after object and a
colon (:). Then implement or override the members of this class as if you were inheriting from it:

window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { /*...*/ }

override fun mouseEntered(e: MouseEvent) { /*...*/ }


})

If a supertype has a constructor, pass appropriate constructor parameters to it. Multiple supertypes can be specified as a
comma-delimited list after the colon:

open class A(x: Int) {


public open val y: Int = x
}

interface B { /*...*/ }

val ab: A = object : A(1), B {


override val y = 15
}

Using
anonymous
objects
as
return
and
value
types
When an anonymous object is used as a type of a local or private but not inline declaration (function or property), all its
members are accessible via this function or property:

class C {
private fun getObject() = object {
val x: String = "x"
}

fun printX() {
println(getObject().x)

283
}
}

If this function or property is public or private inline, its actual type is:

Any if the anonymous object doesn't have a declared supertype

The declared supertype of the anonymous object, if there is exactly one such type

The explicitly declared type if there is more than one declared supertype

In all these cases, members added in the anonymous object are not accessible. Overridden members are accessible if
they are declared in the actual type of the function or property:

interface A {
fun funFromA() {}
}
interface B

class C {
// The return type is Any. x is not accessible
fun getObject() = object {
val x: String = "x"
}

// The return type is A; x is not accessible


fun getObjectA() = object: A {
override fun funFromA() {}
val x: String = "x"
}

// The return type is B; funFromA() and x are not accessible


fun getObjectB(): B = object: A, B { // explicit return type is required
override fun funFromA() {}
val x: String = "x"
}
}

Accessing
variables
from
anonymous
objects
The code in object expressions can access variables from the enclosing scope:

fun countClicks(window: JComponent) {


var clickCount = 0
var enterCount = 0

window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
clickCount++
}

override fun mouseEntered(e: MouseEvent) {


enterCount++
}
})

284
// ...
}

Object
declarations
The Singleton pattern can be useful in several cases, and Kotlin makes it easy to declare singletons:

object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ...
}

val allDataProviders: Collection<DataProvider>


get() = // ...
}

This is called an object declaration, and it always has a name following the object keyword. Just like a variable
declaration, an object declaration is not an expression, and it cannot be used on the right-hand side of an assignment
statement.

The initialization of an object declaration is thread-safe and done on first access.

To refer to the object, use its name directly:

DataProviderManager.registerDataProvider(...)

Such objects can have supertypes:

object DefaultListener : MouseAdapter() {


override fun mouseClicked(e: MouseEvent) { ... }

override fun mouseEntered(e: MouseEvent) { ... }


}

Object declarations can't be local (that is, they can't be nested directly inside a function), but they can be
nested into other object declarations or non-inner classes.

Companion
objects
An object declaration inside a class can be marked with the companion keyword:

class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}

285
Members of the companion object can be called simply by using the class name as the qualifier:

val instance = MyClass.create()

The name of the companion object can be omitted, in which case the name Companion will be used:

class MyClass {
companion object { }
}

val x = MyClass.Companion

Class members can access the private members of the corresponding companion object.

The name of a class used by itself (not as a qualifier to another name) acts as a reference to the companion object of the
class (whether named or not):

class MyClass1 {
companion object Named { }
}

val x = MyClass1

class MyClass2 {
companion object { }
}

val y = MyClass2

Note that even though the members of companion objects look like static members in other languages, at runtime those
are still instance members of real objects, and can, for example, implement interfaces:

interface Factory<T> {
fun create(): T
}

class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}

val f: Factory<MyClass> = MyClass

However, on the JVM you can have members of companion objects generated as real static methods and fields if you use
the @JvmStatic annotation. See the Java interoperability section for more detail.

Semantic
difference
between
object
expressions
and
declarations
There is one important semantic difference between object expressions and object declarations:

286
Object expressions are executed (and initialized) immediately, where they are used.

Object declarations are initialized lazily, when accessed for the first time.

A companion object is initialized when the corresponding class is loaded (resolved) that matches the semantics of a
Java static initializer.

Delegation
The Delegation pattern has proven to be a good alternative to implementation inheritance, and Kotlin supports it natively
requiring zero boilerplate code.

A class Derived can implement an interface Base by delegating all of its public members to a specified object:

interface Base {
fun print()
}

class BaseImpl(val x: Int) : Base {


override fun print() { print(x) }
}

class Derived(b: Base) : Base by b

fun main() {
val b = BaseImpl(10)
Derived(b).print()
}

The by -clause in the supertype list for Derived indicates that b will be stored internally in objects of Derived and the
compiler will generate all the methods of Base that forward to b.

Overriding
a
member
of
an
interface
implemented
by
delegation
Overrides work as you expect: the compiler will use your override implementations instead of those in the delegate
object. If you want to add override fun printMessage() { print("abc") } to Derived, the program would print abc instead of
10 when printMessage is called:

interface Base {
fun printMessage()
fun printMessageLine()
}

class BaseImpl(val x: Int) : Base {


override fun printMessage() { print(x) }
override fun printMessageLine() { println(x) }
}

287
class Derived(b: Base) : Base by b {
override fun printMessage() { print("abc") }
}

fun main() {
val b = BaseImpl(10)
Derived(b).printMessage()
Derived(b).printMessageLine()
}

Note, however, that members overridden in this way do not get called from the members of the delegate object, which
can only access its own implementations of the interface members:

interface Base {
val message: String
fun print()
}

class BaseImpl(val x: Int) : Base {


override val message = "BaseImpl: x = $x"
override fun print() { println(message) }
}

class Derived(b: Base) : Base by b {


// This property is not accessed from b's implementation of `print`
override val message = "Message of Derived"
}

fun main() {
val b = BaseImpl(10)
val derived = Derived(b)
derived.print()
println(derived.message)
}

Learn more about delegated properties.

Delegated
properties
There are certain common kinds of properties, that, though you can implement them manually every time you need them,
it would be helpful to implement them once and add to a library. Examples include:

Lazy properties: the value gets computed only upon first access.

Observable properties: listeners get notified about changes to this property.

Storing properties in a map, instead of a separate field for each property.

To cover these (and other) cases, Kotlin supports delegated properties:

class Example {
var p: String by Delegate()

288
}

The syntax is: val/var <property name>: <Type> by <expression>. The expression after by is a delegate, because get()
(and set()) corresponding to the property will be delegated to its getValue() and setValue() methods. Property delegates
don’t have to implement any interface, but they have to provide a getValue() function (and setValue()--- for var s).

For example:

import kotlin.reflect.KProperty

class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}

When you read from p that delegate