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 # BigIntType Ranges
julia
println(typemin(Int8)) # -128
println(typemax(Int8)) # 127
println(typemin(Int64)) # -9223372036854775808
println(typemax(Int64)) # 9223372036854775807Floating 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)) # trueBoolean Type
julia
t = true
f = false
println(typeof(t)) # Bool
# Booleans are also integers
println(true + true) # 2
println(false + true) # 1Characters 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 neededComposite 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.0Struct 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) # SquareParametric 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) # trueType 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
endType 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: helloType 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.28Multiple 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
endCommon 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)) # trueType 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 = 100Next Steps
After learning data types, continue with:
- Complex and Rational Numbers - Special numeric types
- Arrays - Array type details
- Functions - Types in function applications