Overloading/overriding along with dynamic method invocation... can feel complex/confusing, although it's fairly logical once you get the hang of what's going on. Let me try to help:
It's very important to realize that this is a two-phase process.
Phase 1: Compile-time. This is where Java source code (.java text files) gets turned into JVM byte code (.class binary files).
At this point, the compiler can't generally tell the "actual" type of any variable. The variables don't have values yet -- they're just names/symbols, and won't get values until the program is run. It only knows the declared types for sure, so that's what it uses. Why? Suppose you have a method: public void service(Automobile x) { ... x.drive(15); ... }
The compiler has no way of knowing whether x will actually be an instance of type Automobile, or whether it will actually be an instance of some subclass of Automobile (like SUV or MonsterTruck). That's the way polymorphism works.
During Phase 1, the Java compiler only looks at the declared type of the object that the method is being invoked on, and the declared types of any parameters. If there are multiple (overloaded) methods with that same name, it finds the method that is the closest match that can accept the declared type of the parameters. Let's say it picks Automobile.drive(int distance). (A method's signature is defined by its name and it's parameter types).
Phase 2: runtime. At runtime, all variables DO have actual values. So at this point Java knows that the variable x being passed into the service(...) method is actually a Minivan (for example).
The Java designers wanted to allow the Minivan class to provide more specific functionality, so IF the Minivan class has overridden the Automobile.drive(int ...) method with a Minivan.drive(int ...) method, that overriding method will be invoked instead.
However, Java does NOT look at (re-examine) the actual types of all of the parameters when deciding which method to call. That would be too inefficient, and time is very precious during runtime, since extra time deciding which method to call will delay actually calling the method. So Java only does a quick check to decide if the method that the compiler previously chose has an exact matching method (same name AND declared parameter types) that overrode it in the actual object's class (or in any class between the two, if the actual type is a grandchild or other descendent from the superclass.)
If an exact-parameter-matching overriding method isn't found, then Java simply runs the method that the compiler picked out.