Question
What does a single exclamation mark (!) mean in Kotlin?
I have seen it in Kotlin code a few times, especially when using Java APIs. I could not find a clear explanation in the documentation or on Stack Overflow. What does it do, and why does it appear in those situations?
Short Answer
By the end of this page, you will understand that a single exclamation mark (!) in Kotlin usually means boolean negation: it flips true to false and false to true.
You will also learn why this symbol often comes up when working with Java APIs, how it differs from Kotlin's !! operator, and how to read and write common real-world examples correctly.
Concept
In Kotlin, a single exclamation mark (!) is the logical NOT operator.
It is used with boolean expressions to reverse their value:
!truebecomesfalse!falsebecomestrue
Why this matters
Boolean logic is everywhere in programming:
- checking whether a value is valid
- reversing a condition
- handling permission or feature flags
- filtering data
- deciding whether to enter an
ifblock
For example:
val isLoggedIn = false
println(!isLoggedIn) // true
Here, isLoggedIn is false, so !isLoggedIn becomes true.
Why you may notice it more with Java APIs
When calling Java code from Kotlin, you often deal with methods like:
isEmpty()exists()hasNext()
Mental Model
Think of ! as a switch that flips a yes/no answer.
truemeans yesfalsemeans no!flips the answer
So:
isOpen = true→ the door is open!isOpen→ "the door is not open"
Another way to think about it:
isAvailable()asks a question!isAvailable()means "the answer to that question is no"
It is similar to saying:
happy→ happy!happy→ not happy
This is why ! reads naturally in conditions:
if (!user.isActive) {
println("User is inactive")
}
Read it as: if not active.
Syntax and Examples
The basic syntax is simple:
!expression
The expression must evaluate to a Boolean.
Basic example
val isSunny = true
println(!isSunny) // false
Because isSunny is true, negating it gives false.
Using ! in an if statement
val hasPermission = false
if (!hasPermission) {
println("Access denied")
}
This runs because hasPermission is false, so !hasPermission becomes true.
Common Java API style example
java.io.File
file = File()
(!file.exists()) {
println()
}
Step by Step Execution
Consider this example:
val isEmpty = false
if (!isEmpty) {
println("Container has data")
}
Here is what happens step by step:
isEmptyis assigned the valuefalse.- Kotlin evaluates the condition
!isEmpty. - Since
isEmptyisfalse,!isEmptybecomestrue. - The
ifcondition is therefore true. - Kotlin executes the code inside the block.
- The output is:
Container has data
Another trace with a Java-style method
import java.io.File
val file = File("report.txt")
if (!file.exists()) {
println("Missing file")
}
Step by step:
- A
Fileobject is created for .
Real World Use Cases
! is used constantly in everyday Kotlin code.
Validation
if (!email.contains("@")) {
println("Invalid email")
}
File and resource checks
if (!configFile.exists()) {
println("Configuration file is missing")
}
Feature flags
if (!featureEnabled) {
println("Feature is disabled")
}
Loop control
while (!queue.isEmpty()) {
println(queue.removeFirst())
}
API or database result checks
if (!results.isEmpty()) {
println("Show results")
}
Authentication and permissions
if (!user.isAuthenticated) {
println("Please sign in")
}
In all of these examples, the code asks a yes/no question and ! flips the answer.
Real Codebase Usage
In real projects, developers often use ! in a few common patterns.
Guard clauses
A guard clause exits early when something is not valid.
fun process(user: User?) {
if (user == null || !user.isActive) return
println("Processing ${user.name}")
}
Here, !user.isActive stops processing inactive users.
Validation checks
fun save(input: String) {
if (!input.isNotBlank()) {
throw IllegalArgumentException("Input cannot be blank")
}
}
This works, though input.isBlank() would usually be clearer.
Error handling
if (!response.isSuccessful) {
println("Request failed")
}
Filtering logic
Common Mistakes
Beginners often confuse ! with a few other Kotlin features.
Mistake 1: Confusing ! with !!
Broken understanding:
val name: String? = "Ada"
println(name!!)
This is not boolean negation. It is the non-null assertion operator.
!flips a boolean!!tells Kotlin to treat a nullable value as non-null
Mistake 2: Using ! on a non-boolean value
Broken code:
val number = 10
// println(!number)
Why it fails:
numberis anInt, not aBoolean!only works on boolean expressions
Correct approach:
Comparisons
Here are a few related Kotlin operators and patterns that are often confused with !.
| Syntax | Meaning | Example | Notes |
|---|---|---|---|
!x | Logical NOT | !isReady | Flips a boolean value |
x && y | Logical AND | isLoggedIn && isAdmin | True only if both are true |
| `x | y` | Logical OR | |
!!x | Non-null assertion | name!! | Throws if name is null |
Cheat Sheet
! in Kotlin quick reference:
Core rule
!booleanExpression
- Reverses a
Boolean !true→false!false→true
Common examples
val isOpen = false
println(!isOpen) // true
if (!file.exists()) {
println("Missing file")
}
if (!(age >= 18)) {
println("Minor")
}
Important distinctions
!x // boolean negation
x!! // non-null assertion
Works with
- boolean variables
- boolean-returning functions
FAQ
Is a single ! in Kotlin the same as Java?
Yes. In both languages, a single ! means logical NOT and negates a boolean expression.
Why do I see ! often when using Java APIs in Kotlin?
Because many Java methods return booleans, such as exists(), isEmpty(), or hasNext(). Kotlin uses ! to express the opposite condition.
Is ! related to null safety in Kotlin?
Not directly. ! is for boolean negation. !! is the operator related to nullability.
Can I use ! on nullable booleans?
Only if you handle null safely first. For example:
val flag: Boolean? = null
println(flag == false)
Using !flag directly is not valid when flag is nullable.
What is the difference between and ?
Mini Project
Description
Build a small Kotlin console program that checks whether a file path is usable. This project demonstrates how ! is used with boolean-returning methods from Java APIs such as exists(), canRead(), and isDirectory(). It also shows how negated conditions help with validation and early error messages.
Goal
Create a program that reports whether a given file exists, is readable, and is not a directory.
Requirements
- Accept or define a file path in the program.
- Check whether the file exists.
- Check whether the path is readable.
- Check whether the path points to a directory.
- Print a clear message for each failed check.
- Print a success message only when all checks pass.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.