Все ли константы времени компиляции включены?

Скажем, у меня есть класс вроде этого:

class ApplicationDefs{
public static final String configOption1 = "some option";
public static final String configOption2 = "some other option";
public static final String configOption3 = "yet another option";
}

Многие из других классов в моем приложении используют эти параметры. Теперь я хочу изменить один из параметров и развернуть только скомпилированный класс. Но если эти поля встраиваются в потребительские классы, это становится невозможным?

Можно ли отключить встроенную константу времени компиляции?

Ответ 1

Вы можете использовать String.intern(), чтобы получить желаемый эффект, но должны прокомментировать ваш код, потому что об этом мало кто знает. то есть.

public static final String configOption1 = "some option".intern();

Это предотвратит встроенное время компиляции. Поскольку это относится к той же самой строке, которую компилятор разместит в perm, вы ничего не создаете.

В качестве альтернативы вы всегда можете сделать

public static final String configOption1 = "some option".toString();

однако это не будет использовать скомпилированную intern'd-строку, она создаст новую в старом gen. Не очень большое дело, и его может быть легче читать. В любом случае, поскольку это немного странно, вы должны прокомментировать код, чтобы сообщить тем, кто его поддерживает, тем, что вы делаете.

Edit: Нашел еще одну ссылку SO, которая дает ссылки на JLS, для получения дополнительной информации об этом. Когда использовать intern() для строковых литералов

Ответ 2

Нет, это часть JLS, я боюсь. Это кратко затронуто в Java Puzzlers, но у меня нет моей копии.

Я думаю, вы можете подумать о том, что эти константы определены в файле свойств, и периодически добавляйте их в класс.

Ссылка: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313

Ответ 3

Собственно, если вы удалите ключевое слово final, константы перестанут быть константами времени компиляции, а затем ваша конфигурация будет работать, как вы хотите.

Однако настоятельно рекомендуется, что если это действительно какая-то конфигурация, которую вы пытаетесь сделать, вы должны перейти к более управляемому пути, чем константы в каком-либо файле класса.

Ответ 4

Нет. Вы могли бы заменить их статическим вызовом метода, хотя, например:

class ApplicationDefs {

    public static String configOption1() { return "some option"; }

}

Конечно, это не красиво, но это выполнит ваше требование.:)

Ответ 5

Вы можете запретить встраивание, создавая постоянные постоянные константы компиляции...

Например, null не является постоянной времени компиляции. Любое выражение, включающее постоянную времени не компиляции, не является константой времени компиляции, хотя javac может выполнять постоянную фальцовку внутри единицы компиляции.

public static final String configOption1 = null!=null?"": "some option";

Ответ 6

Здесь нет ничего, что говорит, что эти значения должны быть встроены. Вы просто объявляете некоторые члены public, static. Эти другие классы используют значения этих членов. Никакой вставки не задано. Даже ключевое слово final

Но для причин производительности некоторые JVM могут встроить эти значения в эти другие классы. Это оптимизация. Никакая оптимизация не должна изменять поведение программы. Поэтому, если вы измените определение этих членов, JVM должен un-inline использовать предыдущие значения.

Вот почему нет возможности отключиться. Либо JVM не является встроенным, и нет проблем, либо если он встроен, JVM гарантирует un-inlining.

Я не уверен, что произойдет, когда вы импортируете статически этот класс. Я думаю (не уверен), что инкрустация выполнена и может вызвать проблемы, о которых вы говорите. Если это так, вы можете в основном удалить статический импорт, и вы в порядке.