Question

I usually use python/php but currently writing an Android app so playing with java at the moment. I can't figure out why the following piece of my code doesn't work.

It's meant to take a long representing the time the last check occurred (last_check) and add a predefined number of minutes to it (CHECK_INTERVAL) which is currently set to 1 minute.

    Log.i(this.toString(), "Last check: " + Long.toString(last_check));
    long add_to_check = CHECK_INTERVAL * 60 * 1000;
    long next = last_check + add_to_check;
    Log.i(this.toString(), "Add to check: " + Long.toString(add_to_check));
    Log.i(this.toString(), "Next check: " + Long.toString(next));
    scheduleNextRun(next);

My expectation is that the first log will show the last_check time, the second log will show 60000 and the third log will show the sum of those two. However, I am getting the same value for the first log and the third log - it's like my addition isn't working at all but I can't figure out why. I thought I might have had issues with log vs int but have tried adding L to one of the variables and it doesn't make a difference. FYI the second log is showing 60000 as expected.

thanks Aaron

Was it helpful?

Solution

Is CHECK_INTERVAL 0? You wrote that "the second log is showing 60000 as expected" but perhaps CHECK_INTERVAL was 0 the first time this code ran, then initialized, then 1 on a later iteration when you're looking at that part of the log.

Are you initializing CHECK_INTERVAL to something non-zero but after this code runs? Do you have an initialization bug?

This problem will be easy to solve if you step through the code in the debugger and watch the results. If you're not using a debugger, do yourself a huge favor and get Android Studio (a wonderful tool built on IntelliJ IDEA) or Eclipse + ADT (a good tool).

Java initialization is defined in a way that's predictable, portable, and useful, but it can still be tricky. E.g. given

class Foo {
  static final int A2 = A1 * 1000;
  static final int A1 = 60;
}

The JVM first initializes all variables to default values, then runs the initialization expressions in order. Since A1 is 0 when A2's initializer runs, A2 will end up 0.

See Java Puzzlers for more subtle cases such as when one class's initialization code refers to a second class, causing the second class's initialization code to run, which then refers to values in the first class which haven't yet been initialized beyond their default values (0 and null). A class runs its initialization code on first demand, but nothing guarantees that it finishes initializing before those values are used.

Another tricky case happens when one class, C1, refers to a static final value from a second class, C2.A, then you edit the initialization code for A without recompiling class C1. Java has precise rules about when to cache such constants in the first class's .class file, but they aren't the ideal rules, and the compiler doesn't notice that it needs to recompile C1 for this!

BTW 1: If CHECK_INTERVAL is an int, the expression CHECK_INTERVAL * 60 * 1000 will compute an int value and wrap around within a 32-bit signed range. Still, 1 * 60 * 1000 will easily fit in an int.

BTW 2: The first arg to Log.i() is a tag. It's OK to pass in this.toString() [or toString() for short] but the idea is to pass in a constant tag like the current class name that you can use for log filtering.

[Added] Quick intro to Eclipse debugging

In the source code editor, double-click in the left margin to set a breakpoint. Then use the menus or toolbar to "debug as" a Java application rather than "run as". Eclipse will go into its "Debug perspective" (arrangement of views).

https://www.google.com/search?q=eclipse+debugger finds nice tutorials with step-by-step pictures (I checked the first 3; IBM's is the most concise and introduces more features) and videos. The Eclipse docs are good but harder to navigate.

It's all slicker in Android Studio.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top