I am an experienced Python user, and I love how everything is built-in. One feature I use daily is lazy imports. Recently, I was working with Java and wanted to do something similar. Although I couldn't find any good articles on the topic, I managed to figure it out. Here is a sample implementation based on the bcrypt library use case.
Before using lazy import, I would import the function at the top and use it later in the function.
import at.favre.lib.crypto.bcrypt.BCrypt;
// Using it somewhere in the program
String password = “Test@123”
String storedHashString = "$2RandomHashString”
isValid = BCrypt.verifyer().verify(password.toCharArray(), storedHashString.toCharArray()).verified
Above, you can see example code where I am using the Bcrypt library's functions to verify a password. However, I wanted to import Bcrypt lazily. Here is what I did:
// Directly wrote this where I wanted to use this function.
Class<?> bCryptClass = Class.forName("at.favre.lib.crypto.bcrypt.BCrypt"); // Get the instance of the class
Method verifyerMethod = bCryptClass.getMethod("verifyer"); //Get the method from class.
Object verifyer = verifyerMethod.invoke(null); // Invoke verifyer method and store instance in the variable.
Method verifyMethod = verifyer.getClass().getMethod("verify", char[].class, char[].class);
Object result = verifyMethod.invoke(verifyer, password.toCharArray(), storedHashString.toCharArray()); // Final invoke the verify method.
Boolean ans = (Boolean) result.getClass().getField("verified").get(result); // get the verified field.
Few things to notice here:
- I didn’t import the Bcrypt library at the top.
- It will be imported at runtime. If the jar file is not present, it will throw a ClassNotFoundException. So, add a try-catch block if needed.
- My goal was to achieve this because, in my case, the library might or might not exist in the environment.
Let me know if you have a better way to do this. I hope you find it helpful.
P.S. I'm a noob at Java, so don't quote me on this :P
Top comments (1)
Congrats for your solution!
I have a suggestion: Maybe you do not need reflection.
In Java we have a two-phase process: The compilation process and the execution
process.
Each phase has its own classpath.
You can have your library in compilation classpath, so you can import them
normally.
And your execution classpath can or cannot have your library.
I'm going to show you an example.
Suppose we have the following project structure.
The
lib
directory is where we put our third-party libraries.The
src
directory is where we put our own code.And the
bin
directory is where the compiler put the generated class files.This is the
App.java
code:To compile this project, use this command:
The command below runs your app with third-party libraries in the classpath:
And this is the output:
The command below runs your app without third-party libraries:
And this is the output:
In summary, while reflection can be very useful, the possibility of having
different classpaths for compilation and execution allows you to solve your
problem without losing the benefits of static typing.