Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize static final variables based on cmd args?

Coursework brief requires me to assign an optional cmd argument to a static final variable.

I have tried doing it in main() but compiler complains "cannot assign a value to final variable". I've tried doing it in a static method called by main() but same error. I've heard about static blocks being used in other answers but I need to be able to reach cmd args when I decide what to assign. I've also got some headaches over argument parsing as both arguments should have default values unless one is provided. Any bonus advice is very welcome.

public class FibonacciNim {
    private static Scanner myScanner = new Scanner(System.in);
    private static final int NO_OF_HEAPS;
    private static final int TOKENS_PER_HEAP;

    public static void main(String[] args) {
        // set heaps and tokens using args
        if (args.length == 0) {
            NO_OF_HEAPS = 3;
            TOKENS_PER_HEAP = 9;
        } else {
            boolean usageCorrect = false;
            for (int i = 0; i < args.length-1; i++) {
                if (args[i].equals("-heaps")) {
                    try {
                        NO_OF_HEAPS = Integer.parseInt(args[i+1]));
                        usageCorrect = true;
                    } catch (NumberFormatException e) {
                        usageCorrect = false;
                    }
                } else if (args[i].equals("-tokens")) {
                    try {
                        TOKENS_PER_HEAP = Integer.parseInt(args[i+1]);
                        usageCorrect = true;
                    } catch (NumberFormatException e) {
                        usageCorrect = false;
                    }
                }
            }
        }

        ...

    }

    ...

}

Thanks for reading!

like image 700
Bob Avatar asked Nov 04 '19 22:11

Bob


People also ask

How do you initialize a static final variable?

The only way to initialize static final variables other than the declaration statement is Static block. A static block is a block of code with a static keyword. In general, these are used to initialize the static members. JVM executes static blocks before the main method at the time of class loading.

Can we initialize final variable in static block?

Yes of course: static final variables can be initialized in a static block but.... you have implicit GOTOs in that example ( try/catch is essentially a 'GOTO catch if something bad happens'). If an exception is thrown your final variables will not be initialized.

Can we declare static variable as final?

A developer needs to combine the keywords static final to achieve this in Java. The static keyword means the value is the same for every instance of the class. The final keyword means once the variable is assigned a value it can never be changed.

Can constructor initialize static final variable?

If you declare a static variable in a class, if you haven't initialized it, just like with instance variables compiler initializes these with default values in the default constructor. Yes, you can also initialize these values using the constructor.


2 Answers

You can't...actually, really assign something from the command line to a static final variable. (You might be able to by extremely dirty hackery, but this is probably not the intent of the assignment.)

What might be possible is that you're supposed to create a mutable static final and assign it to the contents of that. That's terrible practice and you really shouldn't do it in real life, but it's at least plausible. For example, you might write

static final String[] argHolder = new String[1];
public static void main(String[] args) {
  ...
  argsHolder[0] = args[0];
  ...
}
like image 185
Louis Wasserman Avatar answered Nov 09 '22 23:11

Louis Wasserman


Static Final variables can only be assigned at initialization.

public class MyClass {

  private static final int NO_OF_HEAPS = 3;

}

Non-static final variables can be assigned in line or in the constructor:

public class MyClass {

  private final int NO_OF_HEAPS;

  public MyClass() {
    NO_OF_HEAPS = 9;
  }

}

You could; however, set your static variables to "essentially" final by changing them to a mutable item such as an AtomicInteger

public class FibonacciNim {
  private static Scanner myScanner = new Scanner(System.in);
  private static final AtomicInteger NO_OF_HEAPS = new AtomicInteger(0);
  private static final AtomicInteger TOKENS_PER_HEAP = new AtomicInteger(0);

  public static void main(String[] args) {
    // set heaps and tokens using args
    if (args.length == 0) {
        NO_OF_HEAPS.set(3);
        TOKENS_PER_HEAP.set(3);
    }
    ...
  }
}

As far as parsing command line arguments you can check out JCommander http://jcommander.org/

It provides functionality to parse command line arguments and populate a POJO to use so you do not have to parse them yourself.

like image 4
locus2k Avatar answered Nov 09 '22 23:11

locus2k