Skip to content

Julia Data Types

Julia is a dynamically typed language but has a powerful type system. Understanding Julia's type system helps write efficient code.

Type Hierarchy

Julia types form a hierarchical tree, with Any as the root type:

Any
├── Number
│   ├── Real
│   │   ├── Integer
│   │   │   ├── Bool
│   │   │   ├── Int8, Int16, Int32, Int64, Int128
│   │   │   └── UInt8, UInt16, UInt32, UInt64, UInt128
│   │   └── AbstractFloat
│   │       ├── Float16, Float32, Float64
│   │       └── BigFloat
│   └── Complex
├── AbstractString
│   └── String
├── AbstractArray
│   └── Array
└── ...

Numeric Types

Integer Types

julia
# Signed integers
a = Int8(127)      # -128 to 127
b = Int16(1000)    # -32768 to 32767
c = Int32(100000)  # ~±2.1 billion
d = Int64(10)      # Default type (64-bit systems)
e = Int128(10)     # Very large integers

# Unsigned integers
f = UInt8(255)     # 0 to 255
g = UInt16(65535)  # 0 to 65535
h = UInt64(10)

# Arbitrary precision integers
big_num = big(10)^100  # BigInt

Type Ranges

julia
println(typemin(Int8))   # -128
println(typemax(Int8))   # 127
println(typemin(Int64))  # -9223372036854775808
println(typemax(Int64))  # 9223372036854775807

Floating Point Types

julia
# Floating point numbers
a = Float16(1.5)   # Half precision (2 bytes)
b = Float32(1.5)   # Single precision (4 bytes)
c = Float64(1.5)   # Double precision (8 bytes, default)
d = BigFloat(1.5)  # Arbitrary precision

# Special values
println(Inf)       # Positive infinity
println(-Inf)      # Negative infinity
println(NaN)       # Not a number

# Check special values
println(isinf(Inf))   # true
println(isnan(NaN))   # true
println(isfinite(1.0)) # true

Boolean Type

julia
t = true
f = false

println(typeof(t))  # Bool

# Booleans are also integers
println(true + true)   # 2
println(false + true)  # 1

Characters and Strings

Character (Char)

julia
# Single character with single quotes
c = 'A'
println(typeof(c))  # Char

# Unicode characters
alpha = 'α'
chinese = '中'

# Character code
println(Int('A'))   # 65
println(Char(65))   # 'A'

String

julia
# String with double quotes
s = "Hello, Julia!"
println(typeof(s))  # String

# Multi-line string
multiline = """
Line 1
Line 2
Line 3
"""

# Raw string (no escaping)
raw = raw"C:\Users\name"  # No backslash escaping needed

Composite Types

Struct

julia
# Immutable struct
struct Point
    x::Float64
    y::Float64
end

p = Point(3.0, 4.0)
println(p.x)  # 3.0
println(p.y)  # 4.0

# Mutable struct
mutable struct MutablePoint
    x::Float64
    y::Float64
end

mp = MutablePoint(1.0, 2.0)
mp.x = 10.0  # Can modify
println(mp.x)  # 10.0

Struct with Default Values

julia
# Using inner constructor
struct Rectangle
    width::Float64
    height::Float64
    
    function Rectangle(w, h=w)  # h defaults to w (square)
        new(w, h)
    end
end

r1 = Rectangle(5.0, 3.0)
r2 = Rectangle(5.0)  # Square

Parametric Types

julia
# Generic struct
struct Container{T}
    value::T
end

c1 = Container(42)       # Container{Int64}
c2 = Container("hello")  # Container{String}
c3 = Container(3.14)     # Container{Float64}

println(typeof(c1))  # Container{Int64}

Abstract Types

julia
# Define abstract types
abstract type Animal end
abstract type Mammal <: Animal end

# Concrete types inherit from abstract types
struct Dog <: Mammal
    name::String
end

struct Cat <: Mammal
    name::String
end

# Check type relationships
println(Dog <: Mammal)   # true
println(Dog <: Animal)   # true
println(Int <: Number)   # true

Type Checking and Conversion

Type Checking

julia
x = 42

# Get type
println(typeof(x))  # Int64

# Type checking
println(isa(x, Int))      # true
println(isa(x, Number))   # true
println(isa(x, String))   # false

# Type assertion with ::
function process(x::Int)
    return x * 2
end

Type Conversion

julia
# Using constructor for conversion
a = Int(3.0)      # 3 (Float64 -> Int)
b = Float64(42)   # 42.0 (Int -> Float64)

# convert function
c = convert(Float64, 42)  # 42.0

# parse string
d = parse(Int, "42")      # 42
e = parse(Float64, "3.14") # 3.14

# Convert to string
s = string(42)            # "42"
s = string(3.14)          # "3.14"

Union Types

Union types represent one of multiple possible types:

julia
# Define Union type
IntOrString = Union{Int, String}

function process(x::IntOrString)
    if x isa Int
        println("Integer: $x")
    else
        println("String: $x")
    end
end

process(42)       # Integer: 42
process("hello")  # String: hello

Type Aliases

julia
# Create type aliases
const IntVector = Vector{Int}
const StringDict = Dict{String, Any}

# Use aliases
v::IntVector = [1, 2, 3]
d::StringDict = Dict("a" => 1, "b" => "hello")

Type Parameters

Parametric Functions

julia
# Specify parameter types
function double(x::T) where T <: Number
    return x * 2
end

println(double(5))     # 10
println(double(3.14))  # 6.28

Multiple Type Parameters

julia
function combine(x::T, y::S) where {T, S}
    return (x, y, T, S)
end

result = combine(1, "hello")
println(result)  # (1, "hello", Int64, String)

Type Stability

Type-stable functions perform better:

julia
# Type unstable (not recommended)
function bad_example(x)
    if x > 0
        return x      # Int
    else
        return 0.0    # Float64
    end
end

# Type stable (recommended)
function good_example(x)
    if x > 0
        return float(x)  # Always returns Float64
    else
        return 0.0
    end
end

Common Type Functions

julia
x = 42

# Type information
println(typeof(x))       # Int64
println(supertype(Int))  # Signed
println(subtypes(Number)) # All Number subtypes

# Type checking
println(isa(x, Int))     # true
println(x isa Number)    # true (infix form)

# Type relationships
println(Int <: Number)   # true
println(Int <: String)   # false

# Type properties
println(isconcretetype(Int))    # true
println(isabstracttype(Number)) # true

Type Annotation Best Practices

julia
# 1. Use abstract types for function parameters
function sum_numbers(arr::AbstractVector{<:Number})
    return sum(arr)
end

# 2. Return type annotation (optional but helpful for documentation)
function divide(a::Int, b::Int)::Float64
    return a / b
end

# 3. Use concrete types for struct fields
struct Person
    name::String
    age::Int
end

# 4. Avoid type uncertainty in global variables
const GLOBAL_CONSTANT::Int = 100

Next Steps

After learning data types, continue with:

Content is for learning and research only.