0

Related to this question regarding static methods, but I didn't feel my question was clearly answered, as mine has a few details I'm unsure about.

I have a small handmade api class (just a .class, nothing fancy) who has a javax client object instantiated at the global level.

final private static Login login = new Login("emadden", "password");
final private static String baseUrl = "http://example.com";

private static Client client = ClientBuilder.newClient().register(JacksonJsonProvider.class);
private static WebTarget target;
private static Invocation.Builder builder;
private static Response response;

Because javax client objects are rather large, I wanted to keep myself and anyone else who might want to use the api from accidentally creating a bunch of these rather large client objects, so all of the attributes (including the client) and methods, with the exception of the api constructors, are static.

// example method
public static Response getFrom(String pathUrl) throws RuntimeException{
    try {
        target = (WebTarget) client.target(baseUrl).path(pathUrl); // TODO: remove cast
        builder = target.request(MediaType.APPLICATION_JSON);
        response = builder.get();
        response.close();
        if (response.getStatus() == 204) {
            System.out.println("GET successful");
        } else if (response.getStatus() != 200) {
            throw new RuntimeException("Failed : HTTP error cod : "
                    + response.getStatus());
        }
    } catch(RuntimeException e) {System.out.println(e.getMessage());}
    return response;
}

Now then, in the class (main.class) that I'm using the api class in, is a global variable, an ArrayList named data, that is instantiated by a static method call to the api class as such.

// Global scope
private static ArrayList<List> data = api.getFrom(baseUrl + pathUrl).readEntity(ArrayList.class)

Nowhere is the api class instantiated in main, but the api.getFrom method does reference the api's global client object, so would that mean that simply calling this method creates an instance of the client object? Would calling it again somewhere else create another?

In the end, I just removed 'static' from the methods, kept the attributes static, allowing me to access the api non-statically with instance of the api in main, but I'm nervous about the possibility of someone creating an instance of the api, then passing it as a parameter, inadvertently creating a copy of it.

So, for knowledge sake, and possibly keeping what I described above from happening, what would happen when calling api.getFrom() from a static context, like I had done originally? Does it create instances of it's global variables, only to discard them once we're outside the scope of the method call? Did I do right just caving in and dropping static from the methods or is there a better way to ensure I, or another user won't be accidentally creating instances of the api and a bunch of big client objects?

Community
  • 1
  • 1
EMadden
  • 13
  • 4
  • 1
    Maybe you should ask yourself why you feel the need to create these big client objects. Better to learn how to use a database properly and partition what you pass. – duffymo Sep 13 '15 at 16:20
  • Also, do you know what _scope_ is? – Sotirios Delimanolis Sep 13 '15 at 16:23
  • You haven't included enough information to answer the question. You can only say; It depends. – Peter Lawrey Sep 13 '15 at 16:25
  • 1
    "...so would that mean that simply calling this method creates an instance of the client object?" Objects don't fall out of trees someone shakes. There is one, and only one, operation to create objects. – laune Sep 13 '15 at 16:29
  • 1
    "...someone creating an instance of the api, then passing it as a parameter, inadvertently creating a copy of it." Again: just by passing on a reference to an object does not pull another object out of some hat. Where did you get this notion? – laune Sep 13 '15 at 16:31
  • @duffymo, I'm doing my best with the time allotted (I have little to no DB exp and no time to get it) and going off of what I saw in the Oracle documentation clients: "Initialization as well as disposal of a Client instance may be a rather expensive operation. It is therefore advised to construct only a small number of Client instances in the application." https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/Client.html – EMadden Sep 13 '15 at 16:33
  • @laune probably thinking it copies the object like in C++ – Dici Sep 13 '15 at 16:33
  • @SotiriosDelimanolis: fixed. Sorry about that. And yea, I'm pretty sure I understand scope well enough, although it's been a while since I've programmed in Java. – EMadden Sep 13 '15 at 16:38
  • @laune: You're still not answering the key question. What DOES happen when I call that method? Will it just try to access the client that's not actually there then? Am I mistaken that parameters are by passed by value, thus "copying" the object and operating on the copy, not the object itself? – EMadden Sep 13 '15 at 16:38
  • @EMadden personally I did not really get your problem. Some small, relevant code might be useful instead of just words and words – Dici Sep 13 '15 at 16:38
  • @EMadden there is **never** an automatic copy of an object in Java, Yet, you keep referring to *that* method, and that's not clear to me what you mean by that. Could you at the very least provide its signature ? – Dici Sep 13 '15 at 16:39
  • "What DOES happen when I call that method?" Which method? You are very funny. – laune Sep 13 '15 at 16:43
  • I agree. Too much words, not enough code, or not the *right* words – Dici Sep 13 '15 at 16:45
  • api.getFrom() is the method I'm referring to. Added more code per your requests. – EMadden Sep 13 '15 at 16:48
  • I'm unfamiliar with the rules here still, would it be appropriate to delete this post and re post with the added code and such since there are no answers yet? – EMadden Sep 13 '15 at 16:49
  • Just edit to provide missing info. – laune Sep 13 '15 at 16:50
  • target, builder are only useful during the call to getFrom, response is the object to be returned. Neither of these should be static in class; they should be local to the method. (Scope? Scope!) – laune Sep 13 '15 at 16:54
  • @laune: I wasn't going to add the whole file to the post. That method was clearly commented as an example method, implying there were others like it. I assure you, target, and builder are used in other methods. Those objects don't come with a warning about multiple instances like client does though, so I suppose I could make them method local, but how would I benefit from that? (sincere question) – EMadden Sep 13 '15 at 17:07

1 Answers1

0

In java the concept of scope is relative to class. There are no global variable instead there are class members. When you define a static method variable it is shared among objects as you are expecting. But the real intention is of static variables is to be used without any object of the class (accessed using class name instead of object). This imposes a limitation that a static method can only access the static members of the class (non-static members are only created when an object is instantiated using constructor).

Because the client is rather large, I wanted to keep myself and anyone else who might want to use the api from accidentally creating a bunch of these rather large client objects, so all of the attributes (including the client) and methods, with the exception of the api constructors, are static.

Seems like you want to implement singleton pattern. Make all your methods static.

so would that mean that simply calling this method creates an instance of the client object? Would calling it again somewhere else create another?

No a static members not instantiated, you have to instantiate the static members using static block. static blocks are executed when the class is loaded (once at the beginning of program).

Hope this simple example helps

public class MyApi {
    private static ArrayList<List> data;

    static {
    data =  // initaion logic
    }
}

More on static blocks tutorial
Documentation on initialization using static blocks

shanmuga
  • 4,329
  • 2
  • 21
  • 35
  • Thank you! I had only learned Java in a classroom environment and never had to worry too much about this sort of stuff. All I really knew was that static fields can only be accessed by class name and other static methods. I never knew about static blocks. I can see now how my idea of "creating instances of static variables" is completely wrong. I'll be sure to look more into singleton pattern examples as well. – EMadden Sep 13 '15 at 17:14