What's the difference of direct dependencies and constraints dependencies to upgrade?

Upgrading versions

in a moduleA with libB, there’s 3 place may define the version of libB:

  1. direct dependencies:
  2. transitive dependencies
  3. constraints dependencies

“”"
When Gradle attempts to resolve a dependency to a module version, all dependency declarations with version, all transitive dependencies and all dependency constraints for that module are taken into consideration. The highest version that matches all conditions is selected.
“”"

If moduleA has only transitive dependencies of libB(no direct dependencies). and we want to upgrade the version of libB.

Question:

  1. whether i use the direct dependencies or constraints dependencies to upgrade the version, the result is same(because gradle just choose the highest), is this true?

  2. the only difference is just on the senmantic level, that constraints dependencies mean moduleA is not direct rely on libB,
    but same on tech level, because moduleA has transitive dependencies of libB, libB is already on classpath of moduleA, no matter whether i use the direct dependencies or constraints dependencies.
    is this true?

Actually, it’s a bit more difficile.
Roughly spoken it is more or less the same.
But the difference in the details is not only semantics.
If you for example declare a version constraint, it means “if anyone depends on this lib, use at least version X (or exactly version X or whatever you define)”, so if noone depends on libB anymore transitively, you also will not get it in your class path. If you declare it as direct dependency, then you will always get it, even if noone else depends on it anymore.

Also it depends on where you declare it. If you for example declare it as implementation dependency, then it also pollutes your compile classpath, making it bigger than necessary and thus compilation slower than necessary and also decreasing up-to-dateness or cache-hits.