> For the complete documentation index, see [llms.txt](https://harmeetsingh.gitbook.io/scala-type-system/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://harmeetsingh.gitbook.io/scala-type-system/phase-i/chapter-5-scala-types-hierarchy.md).

# Chapter 5: Scala Types Hierarchy

As we know, Scala is a pure object-oriented language. Unlike Java, Scala does not distinguish between primitive types and reference types at the language level. Instead, every value has a type, and all types are part of a unified type hierarchy, shown below.

![](https://lh6.googleusercontent.com/AKsFjb3s_yGZlHVBBJ7hrdgCPujUKugZGugzvKceZ2SQW07GRYN4iPk15rNF9Nq4jyCmwQoEyVZ-rH2un2iIipRXxlW0RDsWgjljR_BdGmkB7PqMGGO5HoA7M9RZUWbOm7V6DY8U)

At the top of the hierarchy is `Any`, which is the supertype of every Scala type. The hierarchy is broadly divided into two branches:

* `AnyVal`
* `AnyRef`

#### **AnyVal**

&#x20;`AnyVal` represents Scala's **value types**. These correspond to Java's primitive types, such as `Int`, `Float`, `Double`, `Boolean`, and `Char`.

Although they are modeled as regular classes in Scala, the compiler represents them as JVM primitive types whenever possible to avoid unnecessary object allocation.

Scala also allows developers to define **value classes** by extending `AnyVal`. Value classes provide lightweight wrappers around existing types and, in many cases, avoid object allocation during compilation.<br>

#### **AnyRef**&#x20;

`AnyRef` represents all **reference types**. It is an alias for `java.lang.Object` on the JVM. Every user-defined class and most library classes belong to the `AnyRef` branch of the hierarchy.

After compilation, these types are represented as ordinary Java reference types.

### Bottom Types

Scala also defines two **bottom types** at the lowest level of the hierarchy:

* `Null`
* `Nothing`

These types play an important role in Scala's type system, although programmers rarely use them directly.

Let's explore each of them.

#### **Null:**&#x20;

`Null` is a final abstract class in the Scala standard library. The only value of type `Null` is the `null` literal.

```scala
val result : AnyRef = null
```

Since `Null` is a subtype of `AnyRef`, `null` can be assigned to any reference type.

However, it cannot be assigned to value types such as `Int`:

```scala
val intResult: Int = null
<console>:11: error: an expression of type Null is ineligible for implicit conversion
       val intResult: Int = null
// Compilation error
```

This restriction exists because JVM primitive types cannot hold the value `null`. Since Scala represents `AnyVal` types as JVM primitive types whenever possible, `Null` is defined as a subtype of `AnyRef` only.<br>

#### **Nothing:**&#x20;

`Nothing` is another final abstract class in the Scala standard library. Unlike `Null`, `Nothing` is a subtype of **every** Scala type, including both `AnyRef` and `AnyVal`.

No values of type `Nothing` can ever exist. Instead, `Nothing` represents computations that never successfully return a value.

A common example is a method that always throws an exception:

```scala
def method: Nothing = throw new Exception
```

Since the method never returns normally, its return type is `Nothing`.

This naturally raises an important question:

> **Why do we need `Nothing`?**

Scala supports both object-oriented and functional programming. In functional programming, almost everything is treated as an **expression**, meaning every expression has a type.

Consider the following example:

```scala
val result : User = Obj match {
	case value: Manager => value
	case value: Admin => value
	case _ => throw new Exception
}
```

The first two branches return values of types `Manager` and `Admin`, whose nearest common supertype is `User`.

The final branch throws an exception.

In Scala everything is an expression and throw return something instead of just a statement like Java. If `throw` returned `Unit`, the compiler would compute the least upper bound (LUB) of:

* `Manager`
* `Admin`
* `Unit`

The resulting type would be `Any`, which is not what we want.

Instead, `throw` has the type `Nothing`, which is a subtype of every type. Since `Nothing` contributes no additional constraints when computing the least upper bound, the compiler determines the common type using only the remaining branches.

As a result, the inferred type of `result` is `User`.

This is one of the most elegant uses of `Nothing` in Scala. It allows expressions that never successfully return to participate naturally in type inference without affecting the inferred result type.<br>
