1

https://stackoverflow.com/a/572550/1165790

I want to use this feature in Java because the function that I'm designing is called rarely (but when it is called, it starts a recursive chain) and, therefore, I do not want to make the variable an instance field to waste memory each time the class is instantiated.

I also do not want to create an additional parameter, as I do not want to burden external calls to the function with implementation details.

I tried the static keyword, but Java says it's an illegal modifier. Is there a direct alternative? If not, what workaround is recommended?

I want it to have function scope, not class scope.

Community
  • 1
  • 1
  • Could you post what you've tried so far? You could try something like this: – Buzz Moschetti Sep 28 '13 at 02:14
  • Java has static variables, it's just that their name scope is the class rather than the method. (But I suspect you do not fully appreciate the subtleties of existence scope in Java.) – Hot Licks Sep 28 '13 at 02:16
  • Declaring the single-instance variable as static should do exactly what you need. Seeing your code would help. – Peter Raynham Sep 28 '13 at 02:16
  • I want it to have function scope, not class scope. – Wuschelbeutel Kartoffelhuhn Sep 28 '13 at 02:19
  • Do you need the state only internally during recursion, or should state also be preserved between multiple "external" invocations of your method? – isnot2bad Sep 28 '13 at 02:32
  • 1
    Workarounds: 1) make it class scope, 2) make it object scope, 3) make a new class (possibly an internal [private] class) for that function and pick 1) or 2), 4) add a parameter to an internal private function and keep the interface as it is, 5) switch from recursive to iterative (which may or may not change anything). – Trylks Jan 26 '15 at 14:35

8 Answers8

12

I want it to have function scope, not class scope.

Then you are out of luck. Java provides static (class scoped), instance and local variables. There is no Java equivalent to C's function-scoped static variables.


If the variable really needs to be static, then your only choice is to make it class scoped. That's all you've got.

On the other hand, if this is a working variable used in some recursive method call, then making it static is going to mean that your algorithm is not reentrant. For instance, if you try to run it on multiple threads it will fall apart because the threads will all try to use the same static ... and interfere with each other. In my opinion, the correct solution would be either to pass this state using a method parameter. (You could also use a so-called "thread local" variable, but they have some significant down-sides ... if you are worrying about overheads that are of the order of 200 bytes of storage!)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • If the class gets instantiated 100 times and I have an instance field for the variable, then won't each instantiated object have allocated memory for the variable (irrespective of whether the method was invoked)? – Wuschelbeutel Kartoffelhuhn Sep 28 '13 at 02:50
  • The variable in question is an int, so we have wasted 2 bytes*99, if only one client will actually call the method in question. I like the workaround of using another private function with the additional parameter. – Wuschelbeutel Kartoffelhuhn Sep 28 '13 at 02:58
5

How are you going to keep a value between calls without "wasting memory"? And the memory consumed would be negligible.

If you need to store state, store state: Just use a static field.


Caution is advised when using static variables in multi-threaded applications: Make sure that you synchronise access to the static field, to cater for the method being called simultaneously from different threads. The simplest way is to add the synchronized keyword to a static method and have that method as the only code that uses the field. Given the method would be called infrequently, this approach would be perfectly acceptable.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • <1% of users who instantiate the class would use the method. I don't want to allocate memory for this state each time. I want it to have function scope, not class scope. – Wuschelbeutel Kartoffelhuhn Sep 28 '13 at 02:16
  • 1
    You don't allocate each time the class is instantiated - a static member field is shared between all the instances. Java objects are stored as references, so if you only allocate the actual object when method is first used, only 64 bits of memory will be wasted in the cases it isn't used(=the entire program runs without the method being called even once). 64b is much less memory than what you need to store the code for any hackish workaround. – Idan Arye Sep 28 '13 at 02:23
  • @IdanArye Most 64-bit JVMs use 32-bit references. – Peter Lawrey Sep 28 '13 at 02:34
2

Static variables are class level variables. If you define it outside of the method, it will behave exactly as you want it to.

See the documentation:

Understanding instance and Class Members

The code from that answer in Java...

public class MyClass {
    static int sa = 10;

    public static void foo() {
        int a = 10;

        a += 5;
        sa += 5;

        System.out.println("a = " + a + " sa = " + sa);
    }

    public static void main(String[] args) {
         for (int i = 0; i < 10; i++) {
             foo();
         }
    } 
}

Output: 
$ java MyClass
a = 15 sa = 15
a = 15 sa = 20
a = 15 sa = 25
a = 15 sa = 30
a = 15 sa = 35
a = 15 sa = 40
a = 15 sa = 45
a = 15 sa = 50
a = 15 sa = 55
a = 15 sa = 60

sa Only exists once in memory, all the instances of the class have access to it.

Erich
  • 1,573
  • 1
  • 13
  • 21
2

I agree with Bohemian it is unlikely memory will be an issue. Also, duplicate question: How do I create a static local variable in Java?

In response to your concern about adding an additional parameter to the method and exposing implementation details, would like to add that there is a way to achieve this without exposing the additional parameter. Add a separate private function, and have the public function encapsulate the recursive signature. I've seen this several times in functional languages, but it's certainly an option in Java as well.

You can do:

public int getResult(int parameter){
    return recursiveImplementation(parameter, <initialState>)
}

private int recursiveImplementation(int parameter, State state){
    //implement recursive logic
}

Though that probably won't deal with your concern about memory, since I don't think the java compiler considers tail-recursive optimizations.

Community
  • 1
  • 1
Alex A.
  • 2,646
  • 22
  • 36
2

Probably you got your problem solved, but here is a little more details on static in Java. There can be static class, function or variable.

class myLoader{

static int x;
void foo(){
 // do stuff
}

}

versus

class myLoader{


    static void foo(){

    int x;

    // do stuff
    }

    }

In the first case, it is acting as a class variable. You do not have to "waste memory" this way. You can access it through myLoader.x However, in the second case, the method itself is static and hence this itself belongs to the class. One cannot use any non-static members within this method. Singleton design pattern would use a static keyword for instantiating the class only once. In case you are using multi-threaded programming, be sure to not generate a race condition if your static variable is being accessed concurrently.

ND_27
  • 764
  • 3
  • 8
  • 26
  • " In case you are using multi-threaded programming, be sure to not generate a race condition if your static variable is being accessed concurrently.".... Does it mean that in all the threads the variable x will always have the same value? I mean same value of x in all the threads? – Pushan Gupta May 24 '17 at 20:36
1

The variables set up on the stack in the recursive call will be function (frame) local:

public class foo {
    public void visiblefunc(int a, String b) {
        set up other things;
        return internalFunc(a, b, other things you don't want to expose);          
    }                                                                              

    private void internalFunc(int a, String b, other things you don't want to expose) {
        int x; // a different instance in each call to internalFunc()                                                             
        String bar; // a different instance in each call to internalFunc()
        if(condition) {
            internalFunc(a, b, other things);
        }
    }

}

Buzz Moschetti
  • 7,057
  • 3
  • 23
  • 33
1

Sometimes state can be preserved by simply passing it around. If required only internally for recursions, delegate to a private method that has the additional state parameter:

public void f() { // public API is clean
    fIntern(0); // delegate to private method
}

private void fIntern(int state) {
    ...
    // here, you can preserve state between
    // recursive calls by passing it as argument
    fIntern(state);
    ...
}
isnot2bad
  • 24,105
  • 2
  • 29
  • 50
0

How about a small function-like class?

static final class FunctionClass {
    private int state1;  // whichever state(s) you want.
    public void call() {
        // do_works...
        // modify state
    }

    public int getState1() {
        return state1;
    }
}

// usage:
FunctionClass functionObject = new FunctionClass();
functionObject.call(); // call1
int state1AfterCall1 = functionObject.getState1();
functionObject.call(); // call2
int state1AfterCall2 = functionObject.getState1();
KenIchi
  • 1,129
  • 10
  • 22