skip to content

After registering an extension, how do you retrieve the same instance elsewhere, and what's the difference between getByType, findByName, and capturing the create() return value?

level: middleimportance: should knowfreq 35%

answer

  1. create returns the instance
  2. getByType = typed, throws
  3. findByType = typed, nullable
  4. getByName/findByName = untyped
  5. same single instance every time

basics

~10 s

extensions.create returns the instance, so capture it directly. Later you can fetch it from the ExtensionContainer: getByType(MyExtension::class.java) (typed, throws if absent) or findByName("myExt") (by name, returns null/Object if absent).

solid answer

~40 s

`extensions.create("myExt", MyExtension::class.java)` **returns** the created instance, so the simplest approach is to assign it: `val ext = project.extensions.create(...)`. Elsewhere (e.g. another part of the plugin, or a second plugin) you query the `ExtensionContainer`. `extensions.getByType(MyExtension::class.java)` looks it up **by type** and returns a typed `MyExtension`, throwing `UnknownDomainObjectException` if none matches. `extensions.findByType(MyExtension::class.java)` is the nullable variant. `extensions.getByName("myExt")` / `findByName("myExt")` look up **by registered name**, returning `Any`/`Object?` — you must cast. Prefer `getByType` for typed, refactor-safe access within your own plugin; use name-based lookup when you only know the string name (e.g., interacting with another plugin's extension). All of them return the **same single instance** Gradle created — extensions are not re-instantiated per lookup.

code

kotlin · 9 lines
kotlin
// Capture at creation
val ext = project.extensions.create("report", ReportExtension::class.java)

// Elsewhere, typed and required
val again = project.extensions.getByType(ReportExtension::class.java)

// React to another plugin's extension only if present
val other = project.extensions.findByName("otherExt")
if (other != null) { /* configure cautiously */ }

go deeper

for a junior

Know that create returns the instance and that you can fetch an extension back from project.extensions.

for a middle

Distinguish getByType/findByType (typed) from getByName/findByName (untyped) and get* (throws) vs find* (nullable).

for a senior

Choose retrieval strategy by context, including cross-plugin integration via pluginManager.withPlugin then getByType, and Kotlin DSL sugar (the/configure).

for a principal

Establish conventions for safe cross-plugin extension access (capability detection, optional null-guarded lookups) to keep plugin interactions robust.

## One instance, many ways to reach it When you call `extensions.create`, Gradle builds **one** instance and stores it in the project's `ExtensionContainer`. Every retrieval returns that same object; there's no re-creation. ## The retrieval options **1. Capture the return value (preferred when you create it):** ```kotlin val ext = project.extensions.create("myExt", MyExtension::class.java) ``` Direct, typed, no lookup needed. **2. By type:** ```kotlin val ext = project.extensions.getByType(MyExtension::class.java) // throws if absent val maybe = project.extensions.findByType(MyExtension::class.java) // null if absent ``` Type-safe and refactor-friendly. Use when another part of your code knows the class but not the instance. **3. By name:** ```kotlin val raw = project.extensions.getByName("myExt") // returns Any, throws if absent val rawOrNull = project.extensions.findByName("myExt") // Any? ``` Returns an untyped object; you must cast. Useful when integrating with another plugin whose extension type you can't import, or when only the string name is known. ## getX vs findX `getX` variants **throw** `UnknownDomainObjectException` when nothing matches — good for required dependencies where absence is a programming error. `findX` variants return **null**, suitable for optional integration ("configure this only if the other plugin's extension is present"). ## Kotlin DSL sugar In Kotlin you'll often see `the<MyExtension>()` or `configure<MyExtension> { }`, which delegate to `getByType`/`configure` under the hood. ## Practical guidance - Within the plugin that created it: capture the `create` return value. - Cross-cutting code that knows the type: `getByType` (or `findByType` if optional). - Reacting to a foreign plugin's extension by name: `findByName` guarded by a null check, or better, `pluginManager.withPlugin(...) { ... }` then `getByType`. ## Gotcha Don't call `create` twice for the same name — it throws because the name is already registered. Retrieve, don't re-create.

  • When would you prefer findByType over getByType?
    When the extension may legitimately be absent — e.g. optional integration with another plugin. findByType returns null instead of throwing, letting you branch.
  • What happens if you call extensions.create twice with the same name?
    It throws because that name is already registered in the ExtensionContainer. You should retrieve the existing instance instead of re-creating.

saying these in an interview costs you the question

  • Thinking each getByType/findByName creates a new instance — it returns the single stored object.
  • Using getByName and forgetting it returns an untyped Object that needs casting.

context