Reflection is the ability of a program to inspect, and sometimes modify, its own structure and behaviour at runtime.

It is commonly used to:

  • inspect types, methods, fields, modules, or attributes
  • discover capabilities dynamically
  • build frameworks, serializers, ORMs, dependency injection containers, and test tools
  • invoke code by name instead of by static references

Reflection is related to, but not identical to:

  • Introspection: reading information about program structure
  • Metaprogramming: generating or transforming code, sometimes at compile time instead of runtime
  • RTTI: runtime type information, usually a narrower feature than full reflection

Tradeoffs

Benefits:

  • flexible and dynamic
  • useful for generic tooling and frameworks
  • reduces boilerplate in some cases

Costs:

  • weaker static guarantees
  • harder to reason about and refactor safely
  • runtime overhead is often higher
  • API misuse can fail later, at runtime

Comparison Between Major Languages In This Vault

LanguageReflection supportTypical styleNotes
PythonStrong runtime introspection and reflectiondynamic and ergonomicgetattr, setattr, hasattr, type, inspect, decorators, and metaclasses make reflection common
JavascriptStrong runtime introspectionprototype-based and dynamicproperties can be inspected and modified easily; Reflect and Proxy support meta-level operations
TypescriptLimited at runtimemostly compile-time typingTypeScript types are erased at runtime, so reflection usually falls back to JavaScript objects or decorator metadata
JavaStrong standardized runtime reflectionclass-based and explicitjava.lang.reflect is widely used by frameworks such as serializers and dependency injection containers
RubyVery strong runtime reflectionhighly dynamic and metaprogramming-heavymethods and classes are easy to inspect and redefine; reflection is part of idiomatic Ruby
GoModerate runtime reflectionexplicit and conservativethe reflect package is powerful but verbose; often used in encoding, testing, and framework code
C++Limited built-in reflectionmostly compile-time techniquestraditional C++ relies more on templates, RTTI, and macros than on rich runtime reflection
RustIntentionally limited runtime reflectionstatic and safety-focusedfavors traits, enums, generics, and macros over dynamic reflection
ElixirStrong introspection on BEAM metadatafunctional and runtime-awaremodules, functions, and runtime code loading are inspectable, though the style differs from OO reflection
HaskellLimited runtime reflectiontype-driven and compile-time-heavyusually prefers typeclasses, generics, and advanced type-level programming instead

Rough Spectrum

Languages with more dynamic reflection:

Languages with more limited or deliberate reflection:

When Reflection Fits

Reflection is a good fit when you are building:

  • serializers and deserializers
  • test runners
  • plugin systems
  • schema or form generators
  • dependency injection containers
  • developer tooling

It is usually a poor fit when:

  • static dispatch is simpler
  • correctness depends on compile-time guarantees
  • performance is critical
  • the same result can be achieved with clearer explicit code