rubyguides

Object#object_id

obj.object_id -> integer

Every Ruby instance has a unique integer identifier called its object_id. This value corresponds to the object’s memory address in MRI (the reference implementation). You can use object_id to:

  • Check if two variables reference the same object
  • Implement object caching or memoization
  • Build identity-based data structures

The method is most useful when identity matters more than content. Two strings can look the same and still be different objects, and object_id gives you a fast way to prove that difference. That is handy for debugging, memoization, and any code that needs to know whether two variables point to the same underlying object.

In practice, object_id is a diagnostic tool more than a business rule. It helps answer “is this the same object?” without forcing you to inspect every value by hand.

Syntax

object.object_id

There are no parameters—object_id is called on any Ruby instance and always returns an Integer. The value is an implementation detail of the Ruby interpreter, so do not rely on specific numbers staying the same across runs or Ruby versions. What matters is that two references pointing to the same instance always return the same identifier.

Examples

Basic usage

str = "hello"
str.object_id
# => 70297845295380

# Same string, different object
"hello".object_id
# => 70297845295360

# Different object IDs confirm they're separate objects
str.object_id != "hello".object_id
# => true

This example demonstrates the core identity contract: two separate string literals with the same content produce different object IDs. That confirms Ruby allocates a new String instance for each literal, even when the characters match. It is a quick way to verify that equality checks and identity checks measure different things in Ruby.

Checking object identity

# Using dup creates a new object
original = "hello"
copy = original.dup

original.object_id != copy.object_id
# => true

# Assignment creates a reference to the same object
alias_ref = original

original.object_id == alias_ref.object_id
# => true

The identity check confirms that assigning a variable creates an alias to the same object, not a copy. That distinction is central to understanding Ruby’s variable semantics. When you pass an object to a method or assign it to another name, you are handing around a reference rather than duplicating the data. Understanding this early prevents a whole class of bugs where developers expect assignment to create independent copies.

Common Patterns

Memoization with object_id

class ExpensiveService
  def initialize
    @cache = {}
  end

  def fetch(key)
    @cache[key] ||= compute(key)
  end

  private

  def compute(key)
    # Simulate expensive computation
    sleep 1
    "result for #{key}"
  end
end

This example shows the identity side of the method instead of the literal return value. A cache often needs to know whether it is reusing the same object or creating a fresh one for each key. When the cache stores results keyed by object identity, it avoids recomputing expensive values for objects that have already been processed. That pattern appears in ORMs, serializers, and any system that needs to track which objects have been visited during a graph traversal.

Object identity in collections

# Use object_id as a unique key when objects lack natural IDs
users = []
users << user1 = Struct.new(:name).new("Alice")
users << user2 = Struct.new(:name).new("Bob")

user1.object_id == users[0].object_id
# => true

When you are tracking objects inside an array or another collection, the identifier can help confirm that a value was stored and retrieved without duplication. It is a simple debugging aid when the object content alone is not enough. In test suites, comparing object IDs is often faster than deep value comparisons for verifying that the same instance flows through a pipeline.

Special cases: symbols and integers

Unlike most objects, Ruby’s Symbols and Integers are immediates—they are stored directly in the variable, not as references to objects on the heap. This means:

  • Every occurrence of the same Symbol or Integer has the same object_id
  • They are not garbage collected in the same way as regular objects
# Symbols: same symbol = same object_id
:symbol.object_id
# => 1141748

:symbol.object_id
# => 1141748 (same!)

# Integers: small integers are cached
42.object_id
# => 85

42.object_id  
# => 85 (same!)

# Larger integers create new objects
10000.object_id != 10000.object_id
# => true (different objects)

This behavior makes Symbols and Integers particularly efficient when used as hash keys.

That optimization is one reason these immediate values are so common in Ruby APIs. They carry identity without the same allocation cost as ordinary heap objects.

Errors

object_id never raises an exception—it works on any object.

Because the value is tied to identity, it is best treated as an implementation detail, not something to serialize or depend on across process boundaries. In everyday Ruby code, it is a tool for checks and diagnostics, not a durable business identifier.

See Also