Your two print() methods are called "overloaded" methods: methods with the same name, but different arguments. It's up to the Java compiler to choose which of a set of overloaded methods should get called. When making this decision, the only thing the compiler looks at is the declared types of the arguments you're passing to the method: in this case, is "Object" because s is declared to be of type "Object". The fact that s really points to a String doesn't matter at all.
Overloaded methods are different that "overridden" or polymorphic methods. These are methods in different classes (i.e., multiple subclasses and a superclass) which have the same name and the same argument types. For those methods, the decision of which method to call is deferred until runtime; then the actual type of the object the method is called on does actually matter.