Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add final modifier at runtime in Java

It might sound a bit strange, but is it possible to add the final modifier at runtime?

I have a variable which is marked as public static int/short. At certain point I want to prevent changing its value, and I want to keep its accessibility as a standard static value (ClassName.field).

public class Main {

    private static int a = 0;

    public static void addFinalMod(Field f) {

        Field modifiersField = null;
        try {
            modifiersField = Field.class.getDeclaredField("modifiers");
        }
        catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        modifiersField.setAccessible(true);
        try {
            modifiersField.setInt(f, f.getModifiers() & Modifier.FINAL);
        }
        catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        System.out.println(a);
        try {
            Field f = Main.class.getDeclaredField("a");
            addFinalMod(f);
        }
        catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        a = 10; //I was expecting error/exception here
        System.out.println(a);
    }

Output:

0
10
like image 699
user2749903 Avatar asked Jan 16 '15 19:01

user2749903


People also ask

Can we modify final variable in Java?

Final variable in Java cannot be changed. Once if we have assigned the final variable it can not be changed it is fixed. but if you have declare a blank final variable then you can assign value to it only in constructor.

Can we extend final variable in Java?

In Java final is the access modifier which can be used with a filed class and a method. When a method if final it cannot be overridden. When a variable is final its value cannot be modified further. When a class is finale it cannot be extended.

What does the final modifier in Java do?

The final keyword is a non-access modifier used for classes, attributes and methods, which makes them non-changeable (impossible to inherit or override). The final keyword is useful when you want a variable to always store the same value, like PI (3.14159...). The final keyword is called a "modifier".

Can final keyword be extended?

Classes marked as final can't be extended. One example is the String class.


2 Answers

At certain point I want to prevent changing its value

Do that in application logic. Make the variable only accessible through methods. Keep a flag tracking any change to the variable. After you've applied the change or reached the certain point, raise the flag, and throw an exception for any further attempts at changing the variable.

final is a language keyword/feature for writing your source code and preventing re-assignment of a variable in source code. At runtime, it does (almost) nothing.

like image 66
Sotirios Delimanolis Avatar answered Oct 07 '22 06:10

Sotirios Delimanolis


Use an immutable object:

public class Thing {
    private int value;
    public Thing(int value) { this.value = value; }
    public int getValue() { return this.value; }
}

Then just replace it when it needs modification:

Thing x = Thing(1);
// do some stuff
x = Thing(2);
// more stuff

If you're thinking, "But then they can still modify the value by replacing the object!" well, of course. The only way to prevent that is to lock down some global state (which is actually impossible if it's not a constant), but you're not using global state, right? Global state is a Bad ThingTM.

Global state has a very simple problem: it makes your code much less reusable and more error prone. Error prone is especially true if you're modifying that global state at runtime. "Aw, crap, things are happening in the wrong order." You have no idea how easy that is. Trying to track order of events is the reason mutlithreading is so hard. In terms of reusability, it means that you can't have two independent instances of the thing, which in turn implies you can't really have any two instances of anything that depends on it (at least when it turns out you needed to vary this thing after all).

Even if this isn't a global, then this is some weird state that everyone who has to modify your code (including yourself) is going to have to be aware of and thinking about as they make changes. Does that sound like it's going to make changing things easier or harder? (Hint: the latter.) Don't do this to yourself or your coworkers. Make it simpler. Take a lesson from the Zen of Python: "Simple is better than complex."

So bottom line: if you need an immutable object, use an immutable object. If you need an immutable global that's not a constant, figure out a better way to organize your code.

like image 1
jpmc26 Avatar answered Oct 07 '22 05:10

jpmc26