RHE states "Overloaded methods can exsist in any number in the same class. Each method in a parent class can be overidden at most once in any one subcass".
Yes, that is correct. You can only override just once in the sub-class and overloaded methods can exist in any number.
Is this saying that if you have say, this:
The compiler complains about duplicate methods.
I thought it was because you can't overide a non-static method to a static method or vice-versa.
Is this only the case if the 2nd print() method was placed in a subclass of Test?
First and foremost, the example you quoted does not illustrate overriding and overloading. So to discuss overriding and overloading based on your example may seem to be inappropriate.
The compilation error is caused by duplicate methods. This has nothing to do with overiding non-static methods to static methods or vice-versa. Nor has it anything to do with overriding and overloading.
Rather the compiler looks at the method signature and determines that the methods has the same signature and thus is a duplicate. Please note having the static keyword for the print() method does not make it a different signature.
The signature or identity of the method is determine by method name, type and count of parameters.
This signature is important since when we overload methods, we must be able to provide different signatures in the overloading such that the compiler will not throws an error.
For example, if you have
public float aMethod(float a, float b)
The following methods will be legal such that it overloads the above method:
public int aMethod(int a, int b) { }
private float aMethod(int a, int b, int c) { }
private float aMethod(float a) { }
In the case of overriding, it is straight forward - the overriding method must match the overriden methods, this includes the return type.
Because of the matching requirement, there can only be one overriding method. As such, each method in a parent class can be overidden at most once in any one subcass.