DEV Community

Cover image for Lazy Imports in Java?🙂‍↔️
Mohit Tanwani⚡
Mohit Tanwani⚡

Posted on

Lazy Imports in Java?🙂‍↔️

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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
wldomiciano profile image
Wellington Domiciano

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.

my-project
├── bin
│   └── example
│       └── App.class
├── lib
│   ├── bcrypt-0.10.2.jar
│   └── bytes-1.6.1.jar
└── src
    └── example
        └── App.java
Enter fullscreen mode Exit fullscreen mode

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:

package example;

import at.favre.lib.crypto.bcrypt.BCrypt;

class App {
  public static void main(String... args) {
    try {
      String password = "Test@123";
      String storedHashString = "$2RandomHashString";
      boolean isValid = BCrypt.verifyer().verify(password.toCharArray(), storedHashString.toCharArray()).verified;
      System.out.println("Is valid: " + isValid);
    } catch (NoClassDefFoundError e) {
      System.out.println("Class not found. Using something else...");
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

To compile this project, use this command:

javac -d bin -cp 'lib/*' src/example/App.java
Enter fullscreen mode Exit fullscreen mode

The command below runs your app with third-party libraries in the classpath:

java -cp 'lib/*:bin' example.App
Enter fullscreen mode Exit fullscreen mode

And this is the output:

Is valid: false
Enter fullscreen mode Exit fullscreen mode

The command below runs your app without third-party libraries:

java -cp 'bin' example.App
Enter fullscreen mode Exit fullscreen mode

And this is the output:

Class not found. Using something else...
Enter fullscreen mode Exit fullscreen mode

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.