You have code that loads other classes dynamically. This can introduce a un-warranted overhead and can produce code that is more fragile.
Replace the dynamic class loading with static code.
try { DataProvider dp = (DataProvider) Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance(); } catch (IllegalAccessException iae) { // Convert exception to error to preseve the interface. // throw new IllegalAccessError(iae.getMessage()); } catch (InstantiationException ie) { // Convert exception to error to preseve the interface. // throw new InstantiationError(ie.getMessage()); } catch (ClassNotFoundException cnfe) { // Convert exception to error to preseve the interface. // throw new NoClassDefFoundError(cnfe.getMessage()); }
import org.davison.data.jdbc.JDBCProvider; . . . DataProvider dp = new JDBCProvider();
In some cases code is written with dynamic dependencies between parts of the code by utilising Java ability to load and instantiate arbitrary classes. If not properly managed, this can cause run-time errors. This design can impart a performance penalty because of the extra levels of indirection. It can also prevent the compiler from detecting certain types of error.
Start with this code:
try { DataProvider dp = (DataProvider) Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance(); } catch (IllegalAccessException iae) { // Convert exception to error to preseve the interface. // throw new IllegalAccessError(iae.getMessage()); } catch (InstantiationException ie) { // Convert exception to error to preseve the interface. // throw new InstantiationError(ie.getMessage()); } catch (ClassNotFoundException cnfe) { // Convert exception to error to preseve the interface. // throw new NoClassDefFoundError(cnfe.getMessage()); }
We can remove the error handling code and simply instantiate the class.
DataProvider dp = new JDBCProvider();
The final step is to add in the correct import statement
import org.davison.data.jdbc.JDBCProvider; . . . DataProvider dp = new JDBCProvider();
Compile and test at this point as we have code that is complete.
When this is finished and all dependent classes are re-tested, the refactoring is complete.
Another way of creating compile time dependencies is to use class literals. This would still have the overhead of dynamic instantiation. I would not recommend this unless you have good reason; but here is the code converted to use this method.
try { DataProvider dp = (DataProvider) org.davison.data.jdbc.JDBCProvider.class.newInstance(); } catch (IllegalAccessException iae) { // Convert exception to error to preseve the interface. // throw new IllegalAccessError(iae.getMessage()); } catch (InstantiationException ie) { // Convert exception to error to preseve the interface. // throw new InstantiationError(ie.getMessage()); } catch (ClassNotFoundException cnfe) { // Convert exception to error to preseve the interface. // throw new NoClassDefFoundError(cnfe.getMessage()); }