How does Gradle handle transitive dependencies, and how can you customize this behavior?

Gradle automatically resolves transitive dependencies — the dependencies of your dependencies — building a full dependency graph so you don't have to declare every library manually. When multiple versions of the same module are requested, Gradle by default picks the highest version, and this behavior can be customized through the configurations API.

Key Points: • Gradle's default conflict resolution strategy picks the newest requested version among conflicting transitive dependencies. • exclude group: '...', module: '...' inside a dependency declaration removes a specific unwanted transitive dependency. • resolutionStrategy.force pins a specific version project-wide, overriding whatever version would otherwise "win." • api vs implementation configurations control whether a dependency is exposed transitively to consumers of your own library (api) or kept internal (implementation). • Dependency constraints provide a softer alternative to forcing — expressing a preferred version without completely overriding consumer requests. • dependencyInsight is the primary tool for understanding why a particular transitive version was selected.

Example: If a logging library transitively pulls in an old, vulnerable version of a JSON parser, adding exclude group: 'com.fasterxml.jackson.core', module: 'jackson-databind' on that dependency, plus an explicit direct dependency on the patched version, ensures the safe version is used throughout the project.

Code Example:

dependencies {
    implementation('com.example:logging-lib:2.0') {
        exclude group: 'com.fasterxml.jackson.core', module: 'jackson-databind'
    }
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
}

Interview Tip: A concise interview answer is:

"Gradle automatically resolves transitive dependencies and by default picks the highest requested version when there's a conflict. I customize this with exclude to drop an unwanted transitive dependency, or resolutionStrategy.force to pin a specific version project-wide, and I use dependencyInsight to understand exactly why a version was chosen before changing it."