Roshan Upreti
Roshan Upreti

Reputation: 2052

Pass a constructor argument to a static block

I have a class like this

public class CustomRestClient {

private static String dbString;

public CustomRestClient(String db) {
    this.dbString = db;
}

static {       
    try {
        Client.setServer(Client.Server.LOCAL);
        AuthenticationProvider provider = new AuthenticationProvider();
        provider.setCredentialsProvider(new SimpleCredentialsProvider("user", "pass", dbString, "secretkey"));
        Client.setAuthenticationProvider(provider);
        Client.login();
    } catch (ClientException e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {
    CustomRestClient customRestClient = new CustomRestClient("db");
 }
}

I'm trying to pass the constructor argument inside the static block

provider.setCredentialsProvider(new SimpleCredentialsProvider("user", "pass", dbString, "secretkey"));

For example, CustomRestClient customRestClient = new CustomRestClient("db"); should set the dbString field inside the static block to db. But when I run the program it says the dbString field is null. I have no idea what I'm doing wrong

Upvotes: 2

Views: 602

Answers (3)

Ori Marko
Ori Marko

Reputation: 58772

static block is executed before you create the CustomRestClient object

You should move the static block to static method and call it

public static void login(String db) {
        Client.setServer(Client.Server.LOCAL);
        AuthenticationProvider provider = new AuthenticationProvider();
        provider.setCredentialsProvider(new SimpleCredentialsProvider("user", "pass", dbString, "secretkey"));
        Client.setAuthenticationProvider(provider);
        Client.login();
}

And call it:

CustomRestClient.login("db")

Or (without static) move the method inside a constructor with String argument

private String dbString;

public CustomRestClient(String db) {
    this.dbString = db;
    try {
        Client.setServer(Client.Server.LOCAL);
        AuthenticationProvider provider = new AuthenticationProvider();
        provider.setCredentialsProvider(new SimpleCredentialsProvider("user", "pass", dbString, "secretkey"));
        Client.setAuthenticationProvider(provider);
        Client.login();
    } catch (ClientException e) {
        e.printStackTrace();
    }

}

Upvotes: 2

Thilo
Thilo

Reputation: 262534

That does not work because the static block runs during initialization of the class, before any instance is created or constructor runs.

And there is no way to pass parameters into that. The only thing it could do is load a static value from another place that you set up first. Reading from external configuration (system properties and such) is also an option.

You probably want to replace your static things with a singleton instance (with maybe a static method to initialize it) --- or even better a "regular" instance that you can then inject as a dependency into whatever code needs to use your CustomRestClient (that would make it easier if you ever need to work with multiple sets of connection settings).

Upvotes: 1

Eran
Eran

Reputation: 393851

It's wrong to put that block of code in a static initializer block, since it depends on a constructor parameter, which is passed to the constructor after the static block is executed.

If that initialization depends on an instance specific parameter (different instances of CustomRestClient can receive different dbStrings), it should be moved to an instance method (i.e. not static).

On the other hand, if dbString should remain a static variable, it should be initialized by some static method, not the constructor. In that case, your static initializer block should be moved to that static method. It would be your responsibility to execute that static method.

Upvotes: 1

Related Questions