Назначение переменных с динамическими именами в Java

96

Я хотел бы назначить набор переменных в java следующим образом:

int n1,n2,n3;

for(int i=1;i<4;i++)
{
    n<i> = 5;
}

Как я могу добиться этого на Java?

Ашиш Ананд
источник
1
Не могли бы вы прояснить свой вопрос?
Eng. Fouad
4
Вам нужно сделать это для локальных переменных? Почему не элементы массива?
Ray Toal
@ Eng.Fouad: Я хочу получить доступ к переменным по их имени динамически.
Ашиш Ананд
@Ashish Anand, вы имеете в виду stackoverflow.com/questions/6629995/…
mKorbel

Ответы:

111

В Java это не так. В Java нет динамических переменных. Переменные Java должны быть объявлены в исходном коде 1 .

В зависимости от того, чего вы пытаетесь достичь, вы должны использовать массив, a Listили a Map; например

int n[] = new int[3];
for (int i = 0; i < 3; i++) {
    n[i] = 5;
}

List<Integer> n = new ArrayList<Integer>();
for (int i = 1; i < 4; i++) {
    n.add(5);
}

Map<String, Integer> n = new HashMap<String, Integer>();
for (int i = 1; i < 4; i++) {
    n.put("n" + i, 5);
}

Отражение можно использовать для динамической ссылки на переменные, объявленные в исходном коде. Однако это работает только для переменных, которые являются членами класса (т.е. статические поля и поля экземпляра). Это не работает для локальных переменных. См. "Быстрый и грязный" пример @fyr.

Однако делать такие вещи в Java без надобности - плохая идея. Он неэффективен, код более сложен, и, поскольку вы полагаетесь на проверку во время выполнения, он более хрупкий. И это не «переменные с динамическими именами». Его лучше описать как динамический доступ к переменным со статическими именами.


1 - Это утверждение немного неточно. Если вы используете BCEL или ASM, вы можете «объявить» переменные в файле байт-кода. Но не делай этого! В этом безумие!

Стивен С
источник
1
Большое спасибо, получил то, что искал. Последняя часть (Map <String, integer>).
Ашиш Ананд
1
Следует отметить, что даже если бы это было возможно, вы на самом деле этого не делали. Вы ничего от этого не получите; вы фактически потеряете читаемость. Если вы хотите связать их, используйте Map<String, T>вместо этого, не начинайте возиться с вашим фактическим кодом.
Jeroen Vannevel
2
@JeroenVannevel - Вот что я имел в виду под "безумием" :-)
Стивен Си
35

Если вы хотите получить доступ к каким-то динамическим переменным, вы можете использовать отражение. Однако Reflection работает не для локальных переменных. Это применимо только к атрибутам класса.

Грубый, быстрый и грязный пример:

public class T {
    public Integer n1;
    public Integer n2;
    public Integer n3;

    public void accessAttributes() throws IllegalArgumentException, SecurityException, IllegalAccessException,
            NoSuchFieldException {

        for (int i = 1; i < 4; i++) {
            T.class.getField("n" + i).set(this, 5);
        }
    }
}

Вам нужно улучшить этот код различными способами, это всего лишь пример. Это также не считается хорошим кодом.

Fyr
источник
3
Отлично, когда вам нужно преобразовать Android-сенсор event.values ​​[] в набор переменных. event.values ​​[] может иметь длину от 1 до 6, и его удобно преобразовать, в моем случае для маршалинга json без массива.
Farshid T
12

Вам нужен именованный массив. Я хотел написать такой код:

int[] n = new int[4];

for(int i=1;i<4;i++)
{
    n[i] = 5;
}
AlexR
источник
1
Не хочу использовать массивы. Я хочу получить динамический доступ к переменным (n1, n2, n3) в зависимости от некоторого условия.
Ашиш Ананд
10

Вы должны использовать Listили arrayвместо

List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);

Или

int[] arr  = new int[10];
arr[0]=1;
arr[1]=2;

Или даже лучше

Map<String, Integer> map = new HashMap<String, Integer>();
map.put("n1", 1);
map.put("n2", 2);

//conditionally get 
map.get("n1");
Джигар Джоши
источник
7

Динамические имена переменных в Java
Такого не существует.

В вашем случае вы можете использовать массив:

int[] n = new int[3];
for() {
 n[i] = 5;
}

Для более общих (name, value)пар используйтеMap<>

Op De Cirkel
источник
4

Попробуйте так:

    HashMap<String, Integer> hashMap = new HashMap();

    for (int i=1; i<=3; i++) {
        hashMap.put("n" + i, 5);
    }

источник
4

Вы этого не сделаете. Самое близкое, что вы можете сделать, - это работать с Maps, чтобы имитировать это, или определить свои собственные объекты для работы.

Эвертон
источник