When configuring an existing task, why use tasks.named over tasks.getByName?
answer
- getByName = locate + realize
- named = provider, no realize
- config block deferred
- both validate name eagerly
- typed named<Test>
basics
~10 stasks.getByName realizes the task right away. tasks.named returns a TaskProvider and defers configuration until the task is actually realized, preserving configuration avoidance.
solid answer
~40 s`tasks.getByName("test")` locates *and realizes* the task immediately, returning the concrete `Task`. `tasks.named("test")` returns a `TaskProvider<Task>` without realizing anything; `tasks.named("test") { ... }` registers configuration that runs only when (and if) the task is realized. So if you tweak the `test` task with `named` but the current invocation never needs `test`, no realization happens. `named` also fails fast at configuration time if the task name doesn't exist, just like `getByName`, so you don't lose that safety. In Kotlin DSL you can type it: `tasks.named<Test>("test") { ... }`. The rule: locate-and-configure existing tasks with `named`, reserve `getByName` for the rare case where you genuinely need the realized object immediately (and even then, prefer mapping a provider).
code
kotlin · 8 lines// Eager: realizes 'test' on every build, even ./gradlew help
tasks.getByName("test") { /* configure */ }
// Lazy: configuration runs only if 'test' is realized
tasks.named<Test>("test") {
useJUnitPlatform()
maxParallelForks = 2
}go deeper
Know named returns a provider and getByName returns the realized task.
Explain that named defers realization/config while still validating the name, and use the typed overload.
Note when getByName is genuinely justified and how to map providers instead of realizing.
Standardize named-over-getByName in shared plugins to keep monorepo configuration time bounded.
## getByName: eager locate `tasks.getByName(name)` does two things at once: it finds the task and **realizes** it, handing you the live `Task`. Any configuration you do runs immediately, at configuration time, whether or not the task is part of the build. In a convention plugin this is a classic source of avoidable configuration cost. ## named: lazy locate `tasks.named(name)` returns a `TaskProvider` and realizes **nothing**. Two forms: ```kotlin val testProvider = tasks.named("test") // just a handle tasks.named("test") { /* config */ } // lazy configuration tasks.named<Test>("test") { useJUnitPlatform() } // typed, Kotlin DSL ``` The configuration block executes only when the task is realized — e.g. when you run it, or when a realized task depends on it. ## Both validate the name eagerly A common worry: "does named hide typos?" No. `named` validates that a task with that name exists at the time of the call and throws `UnknownTaskException` if not — same fail-fast guarantee as `getByName`. What's deferred is the *configuration block* and *realization*, not the existence check. ## Typed lookups and type safety `tasks.named<Test>("test")` (Kotlin) / `tasks.named("test", Test::class)` gives you a typed `TaskProvider<Test>`, so the configuration block sees `Test`-specific properties. With `getByName` you'd cast. ## Putting it together ```kotlin // Eager — realizes 'jar' even for ./gradlew help tasks.getByName("jar") { /* ... */ } // Lazy — 'jar' realized only if needed tasks.named("jar") { /* ... */ } ``` Pair `named` with `dependsOn(provider)` and `configureEach` to keep the whole configuration lazy.
- Does tasks.named hide typos in task names until later?No. named checks that the task exists at call time and throws UnknownTaskException immediately if it doesn't — same fail-fast as getByName. Only the configuration block and realization are deferred, not the existence check.
- How do you get type-safe access to a Test-specific property via named?Use the typed overload: tasks.named<Test>("test") { ... } in Kotlin DSL, or tasks.named("test", Test::class). The provider is TaskProvider<Test>, so the block exposes Test properties without casting.
saying these in an interview costs you the question
- Claiming named defers the existence check and so hides typos — it validates eagerly.
- Defaulting to getByName everywhere out of habit, defeating avoidance.