I believe that usually, almost always, the best way to instantiate an object is by using the "new" operator. The "new" operator instantiates an object every time that its line of code is executed.
Here's a real-world example of using Class.forName(). This code comes from an example of how to use a
JDBC database engine, using a driver.
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
Here, instantiation is dynamic because the parameter is a String that can be any JDBC database engine driver. In theory, you could switch database engines merely by changing the value of the parameter.
I had a real hard time getting the dynamic instantiation working in the one line of code above.
After spending a great deal of time trying to get the example code working, thinking that my database engine wasn't installed properly, I tried the following line of code:
new org.apache.derby.jdbc.EmbeddedDriver();
To use the "new" operator, you can't even compile unless the class that you're instantiating is findable.
The above line of code above worked. It's much simpler.
Once I got the "new" operator working, then I could turn my attention toward generalizing the code by making the class name to be instantiated a parameter as in the original example.