In Scala, variables can be declared in two ways: using val or var, depending on whether the value is immutable or mutable. Here’s an explanation of each along with examples.
val: Immutable Variables
valis used to declare immutable variables. Once a value is assigned to aval, it cannot be changed (similar to a constant or final variable in other languages like Java).- Immutable means that the reference to the value cannot be changed, but the value itself (if it’s mutable) can still be modified.
Syntax:
val variableName: DataType = value
Example :
val name: String = "Alice"
val age: Int = 25
val pi: Double = 3.14
// The following will cause an error because `val` is immutable.
// name = "Bob" // Error: reassignment to val
Advantages of val: Promotes immutability, leading to safer and more predictable code, especially in concurrent environments.
var: Mutable Variables
varis used to declare mutable variables. This means the value can be changed after the initial assignment.- Mutable means that both the reference and the value can be changed.
var variableName: DataType = value
Example :
var counter: Int = 0
counter = 1 // Allowed because `var` is mutable
counter = counter + 1 // Now counter is 2
- When to use
var: Usevarsparingly, as too much mutability can make code harder to maintain, debug, and reason about.
Type Inference:
Scala supports type inference, which means that the compiler can automatically deduce the type of a variable based on the value assigned to it. You don’t need to explicitly specify the type, though you can if you want to.
Example:
val name = "Alice" // Compiler infers type as String
var count = 10 // Compiler infers type as Int
You can still explicitly declare types for clarity if you prefer:
val name: String = "Alice"
var count: Int = 10

Variable Scope:
- Variables in Scala follow block scope. They are only accessible within the block in which they are defined.
- Variables defined inside a method or a block cannot be accessed outside of that block.
Example:
def myMethod(): Unit = {
val x = 10
println(x) // Valid, x is accessible here
}
// println(x) // Error: x is not accessible outside the method
Lazy Initialization (lazy keyword):
Scala also supports lazy initialization using the lazy keyword. A lazy val is not initialized until it is accessed for the first time.
Example:
lazy val greeting = "Hello, world!"
// `greeting` will only be initialized when it is used for the first time
println(greeting)
Difference Between val and var:
| Feature | val | var |
|---|---|---|
| Mutability | Immutable (cannot be reassigned) | Mutable (can be reassigned) |
| Usage | Preferred for immutability | Used when reassignment is needed |
| Thread Safety | More thread-safe due to immutability | Less thread-safe due to mutability |
| Example | val age = 30 | var age = 30; age = 35 |
Example:
// val example
val name: String = "John"
println(name) // Prints: John
// name = "Jane" // Error: reassignment to val
// var example
var score: Int = 100
println(score) // Prints: 100
score = 150 // Reassigning new value
println(score) // Prints: 150
Summary:
val: Immutable variable, its value cannot be reassigned.var: Mutable variable, its value can be reassigned.- Scala emphasizes immutability as it is safer for concurrent programming and makes code more predictable.
- Use
valwherever possible andvaronly when necessary.
Data types
Scala provides a variety of data types to represent different kinds of values, such as numbers, characters, strings, and more. These data types are based on the underlying Java types but come with additional features specific to Scala.
Type Hierarchy in Scala:
Any
├── AnyVal
│ ├── Byte
│ ├── Short
│ ├── Int
│ ├── Long
│ ├── Float
│ ├── Double
│ ├── Char
│ ├── Boolean
│ └── Unit
└── AnyRef
├── String
├── List
└── Other Reference Types
└── Null (special type)
Type Inference in Scala:
Scala can automatically infer the type of a variable based on the assigned value, so you don’t always need to explicitly specify the type.
Example:
val inferredInt = 10 // Type is inferred as Int
val inferredDouble = 3.14 // Type is inferred as Double
val inferredString = "Scala!" // Type is inferred as String
Basic Data Types:
| Data Type | Description | Example |
|---|---|---|
Byte | 8-bit signed integer (-128 to 127) | val a: Byte = 100 |
Short | 16-bit signed integer (-32,768 to 32,767) | val b: Short = 32000 |
Int | 32-bit signed integer | val c: Int = 100000 |
Long | 64-bit signed integer | val d: Long = 10000000000L |
Float | 32-bit floating-point number | val e: Float = 3.14f |
Double | 64-bit floating-point number (default for decimals) | val f: Double = 3.14159 |
Char | 16-bit Unicode character | val g: Char = 'A' |
String | A sequence of characters | val h: String = "Hello, Scala!" |
Boolean | Represents true or false | val i: Boolean = true |
Unit | Represents no value (like void in Java) | def printMsg(): Unit = println("Message") |
Null | Type of the null literal | val j: String = null |
Nothing | The subtype of all types, represents no value (used for exceptions) | Cannot be directly instantiated |
Any | The supertype of all types | val k: Any = "Can be anything" |
AnyRef | The supertype of all reference types (equivalent to Java’s Object) | val obj: AnyRef = new Object() |
Numeric Data Types:
Example of Basic Numeric Data Types:
val byteVal: Byte = 127
val shortVal: Short = 32767
val intVal: Int = 100000
val longVal: Long = 1000000000L
val floatVal: Float = 3.14f
val doubleVal: Double = 3.141592653589793
Byte,Short,Int, andLongare used for whole numbers of various sizes.FloatandDoubleare used for floating-point numbers, whereDoubleis more precise.- You must append an
Lto indicate aLongand anfto indicate aFloat.
Arithmetic Operations Example:
val sum: Int = 10 + 20
val product: Double = 10.5 * 2
val quotient: Float = 15.0f / 4.0f
println(s"Sum: $sum, Product: $product, Quotient: $quotient")
Character and String Data Types:
Charrepresents a single Unicode character, and it is enclosed in single quotes (').Stringis a sequence of characters enclosed in double quotes (").
Example :
val charVal: Char = 'A'
val stringVal: String = "Hello, Scala!"
println(s"Char: $charVal, String: $stringVal")
Boolean Data Type:
Booleanrepresents a truth value: eithertrueorfalse.
val isScalaFun: Boolean = true
println(s"Is Scala fun? $isScalaFun")
Unit, Null, Nothing:
Unit: Similar tovoidin other languages, it represents the absence of a value. It is the return type of methods that do not return anything.Null: Used to represent the null reference, mainly for reference types likeString. It cannot be assigned to value types likeInt.Nothing: Represents the absence of a value, typically used for functions that never return (e.g., throw exceptions).
def sayHello(): Unit = {
println("Hello, World!")
}
val nullStr: String = null
// val nullInt: Int = null // This will cause an error, since primitive types can't be null
Any, AnyVal, AnyRef:
Any: The root of Scala’s type hierarchy. Every type in Scala is a subtype ofAny.AnyVal: Represents value types such asInt,Double,Boolean, etc.AnyRef: Represents reference types (like objects), similar to Java’sObject.
Example :
val anyVal: Any = "I can be any type"
val anyRef: AnyRef = "I am a reference type"
println(s"Any: $anyVal, AnyRef: $anyRef")
Summary
| Data Type | Description | Example |
|---|---|---|
Byte | 8-bit signed integer | val a: Byte = 127 |
Short | 16-bit signed integer | val b: Short = 32767 |
Int | 32-bit signed integer | val c: Int = 100000 |
Long | 64-bit signed integer | val d: Long = 1000000000L |
Float | 32-bit floating-point | val e: Float = 3.14f |
Double | 64-bit floating-point | val f: Double = 3.1415926535 |
Char | A single 16-bit character | val g: Char = 'A' |
String | A sequence of characters | val h: String = "Hello, Scala!" |
Boolean | A boolean value (true or false) | val i: Boolean = true |
Unit | Represents no value (like void) | def printMsg(): Unit = println("") |
Null | A type representing the null reference | val j: String = null |
Nothing | A type for non-returning methods (e.g., throwing exceptions) | throw new Exception |
Any | Supertype of all types | val k: Any = 42 |
AnyVal | Supertype of all value types | val l: AnyVal = 5.0 |
AnyRef | Supertype of all reference types | val m: AnyRef = "reference" |