Вопрос по names, java, dynamic, code-generation – Есть ли возможность динамически генерировать имена переменных в Java?

4

Допустим, мне нужно сгенерировать переменные для хранения некоторого ввода от пользователя (я не знаю, сколько их). Без использованияArray, ArrayList (и другие виды списков и карт) может генерировать мой код (скажем так)String переменные X раз с именами вроде (String var001, String var002, String var003, так далее)? Если да, пожалуйста, предоставьте образец кода.

Спросите своего профессора, хочет ли он, чтобы вы также программировали с завязанными глазами - в этом столько же смысла. Массивы и коллекции существуют именно для этой цели. Я даже не вижу, как вы узнали бы что-нибудь полезное из такого упражнения. Michael Borgwardt
Я надеюсь, что ваш профессор не читает переполнение стека! Как его / ее зовут? Rob Fonseca-Ensor
Я думаю, что ваш профессор имел в виду отражение. Я никогда не использовал отражение Java, но просматривая API, вы не связываете идентификаторы с экземплярами объектов, созданными отражением в Java. Конечно, здесь должно быть какое-то недопонимание. Tamas Czinege
Это очень странный запрос ... что вы имеете в виду - "не знаю, сколько их"? А когда будешь знать? Во время выполнения? Во всяком случае, это действительно похоже на работу для класса коллекции. Почему вы не можете их использовать? Не могли бы вы рассказать нам больше о вашей проблеме? Vilx-
Я знаю, что это странная просьба, но это сложная проблема, которую наш профессор ставит на стол. Поэтому я больше обеспокоен возможностью сделать это независимо от его удобства! Единственный трюк, который обнаружила моя группа, это то, что «Маркус Лойсберг» уже предлагали по этому вопросу ... так есть ли другой способ обойти это? M. A. Kishawy

Ваш Ответ

10   ответов
1

но это идеальный кандидат для использования одной из коллекций Java.

Либо используйте динамически размещенный массив:

String[] arr = new String[RUNTIME_SIZE];

Или список, который может изменить его размер во время выполнения:

List list = new ArrayList<String>();
Для записи, это возможно в PHP. Смотрите & quot; Переменные переменные & quot; в руководстве.
Извините, я не вижу ни одного тега PHP в этом вопросе ...
3

поэтому пойду. Напишите программу, которая просто записывает исходный код Java. В большинстве случаев это может быть шаблон, и у вас просто будет цикл, в котором будет записано столько строк & quot; строка UserString003 & quot; введите переменные, как вы хотите.

Да, это ужасно Но, как вы сказали, это проблема концептуальной задачи для домашней работы, так что пока никто не примет это за "хорошо" код, это может решить проблему.

2

Переменные переменные), поэтому он думал, возможно ли это в Java.

Я лично не думаю, что это возможно, не так, как вы предлагаете. Что можно сделать, это генерация классов во время выполнения с использованием таких инструментов, какJavassist сделать более мощный механизм отражения. Таким образом, вы можете создать класс с нужными вам переменными (string1, string2 и т. Д.) Во время выполнения.

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

2

которым я реализовал и помог мне легко исправить свое решение без особых проблем.

// Создание списка массивов

List accountList = new ArrayList(); 




for(int k=0;k < counter;k++){
        accountList.add(k, (String)flowCtx.getValueAt("transitId"+m));
}

Итерация цикла и добавление объектов в массив с индексом.

// Получение объекта во время выполнения с помощью индекса

String a = accountList.get(i));
что такое flowCtx здесь?
5

really хотите сделать что-то подобное, вы можете сделать это с помощью генерации байт-кода с помощьюКАК М или какая-то другая библиотека.

Вот код, который сгенерирует класс с именем & quot; foo.bar.ClassWithFields & quot; который содержит поля "var0"; в "var99". Конечно, нет никакого другого способа, кроме отражения, получить доступ к этим полям, потому что они не существуют во время компиляции, а Java является статически типизированным языком.

import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;

import java.lang.reflect.Field;

public class GeneratedFieldsExperiment {

    public static byte[] generateClassWithFields(int fieldCount) throws Exception {
        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "foo/bar/ClassWithFields", null, "java/lang/Object", null);

        for (int i = 0; i < fieldCount; i++) {
            fv = cw.visitField(ACC_PUBLIC, "var" + i, "Ljava/lang/String;", null, null);
            fv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }

    public static void main(String[] args) throws Exception {
        MyClassLoader loader = new MyClassLoader();
        Class<?> c = loader.defineClass("foo.bar.ClassWithFields", generateClassWithFields(100));

        System.out.println(c);
        System.out.println("Fields:");
        for (Field field : c.getFields()) {
            System.out.println(field);
        }
    }

    private static class MyClassLoader extends ClassLoader {
        public Class<?> defineClass(String name, byte[] b) {
            return defineClass(name, b, 0, b.length);
        }
    }
}
Некоторые комментарии к коду действительно помогут :) спасибо! M. A. Kishawy
Он использует библиотеку ASM для генерации класса - байтовый массив имеет тот же формат, что и файлы .class, которые создает компилятор Java, - а затем загружает его в JVM с помощью пользовательского загрузчика классов. ASM работает на уровне байт-кода Java (аналогично ассемблерному коду), поэтому для понимания приведенного выше кода сначала необходимо изучить некоторый байт-код Java (документация ASM хороша для этого:download.forge.objectweb.org/asm/asm-guide.pdf). Некоторые другие библиотеки манипулирования байт-кодом могут быть проще в использовании, чем ASM, потому что они имеют более высокий уровень, чем чистый байт-код. Я думаю, что Javassist - одна из таких библиотек.
2

как это выглядит очень 1980-х годов. Значение предварительно объектно-ориентированного программирования. Так что если вы когда-нибудь создаете программное обеспечение для жизни - НЕ ДЕЛАЙТЕ ЭТОГО.

Но так как это, кажется, домашнее задание ...

Когда мы говорим об именованной переменной в Java, мы имеем в виду то, что скомпилировано. В отличие от некоторых языков сценариев, в Java нет простого способа сделать это.

Так что либо вы используете скомпилированный класс во время выполнения, как предложил Маркус Лозберг.
Или вы обманываете и используетеAPI сценариев Java и использовать языки сценариев. Таким образом, вы можете создавать код (в виде строки) во время выполнения.

Java Scripting API очень интересен :) Спасибо за новую информацию! M. A. Kishawy
4

Создайте файлы с этими именами. Надеюсь, это сработает для вашего профессора.

Или используйте Java Scripting API, упомянутый ранее:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");

engine.put("x", "hello"); // you can add any variable here
// print global variable "x"
engine.eval("println(x);");
// the above line prints "hello"

EDIT

Похоже, что внутри будет использоваться Карты :) То же самое с файлом свойств, настройками API или деревьями DOM (они используют векторы). Так что, если ваш профессор очень разборчив, используйте файлы.

Спасибо за информацию :) M. A. Kishawy
0

правильно ли я вас понял, но если вы пытаетесь использовать динамически создаваемые имена для ваших переменных, тогда да, определенно - я делаю это так:

// rndRng() creates random numbers in specified range
// this would output dynamically created variable like "name89"
String myDynamicalyCreatedName = "name" + Utils.rndRng(0, 100);
final UberShader $myDynamicalyCreatedName = new UberShader();

Как вы можете видеть, точка-ключ здесь - это знак "$" это в основном говорит "создать имя переменной из строки, которая дается после этого знака", и это в основном это - работает для меня уже несколько лет как обаяние ... надеюсь, это то, что вы хотели, и это помогает немного решить вашу проблему.

Я думаю, что происходит то, что вы создаете переменную с именем$myDynamicalyCreatedName, ЗначениеmyDynamicalyCreatedName не имеет значения. По факту,myDynamicalyCreatedName даже не нужно существовать.
Видите, я не гуру JAVA, поэтому, пожалуйста, не задавайте мне этот повторяющийся вопрос, я не знаю, почему или как, но это определенно работает для меня - все компилируется без помех и работает как шарм, если бы не каждый новый материал тот же класс (в данном случае Chrome) перезапишет предыдущий, чего у него нет: у всех есть свои уникальные имена или лучше сказать не имена, подобные .setName (), но & quot; names & quot; когда вы их инициализируете (английский не мой родной язык, извините) ... Кстати, я бы попробовал System.out.println ($ name);
Я не думаю, что язык Java работает так, как вы думаете. Вы можете исключить строку, где вы определяетеmyDynamicallyCreatedName и код все равно будет делать то же самое. Он просто создает переменную с именем$myDynamicalyCreatedName.
Может быть, вы не используете Java? Если динамически созданные имена работали таким образом, вы должны быть в состоянии сделать это:String name = "myVar"; int $name = 1; System.out.println(myVar);  Но это даже не скомпилируется.
Ну, как ни странно, это определенно работает: часть моего кода создает материалы (например, цвета с определенными атрибутами поверхности - металлический, блестящий, стеклянный и т. Д.), У меня есть 3 разных цвета конкретного материала (скажем, «хром»). ), у каждого материала должно быть уникальное имя - теперь я использую один и тот же сценарий для всех материалов Chrome, и у каждого из созданных им есть свое уникальное динамически создаваемое имя, как я описал выше ... теперь скажите мне, что не так, как я вижу, как оно работает ежедневно! ;-)
2

var0, var1, var2 и используйте их в своем коде.

Какая разница при использовании var [0], var [1], var [2], .....

BUT

Вы можете динамически генерировать Java-класс во время выполнения, который реализует интерфейс, который вы используете в своем обычном коде. Затем вы компилируете этот класс с помощью компилятора (например, Janino), а затем загружаете класс во время выполнения. Чем вы создали класс динамически.

Но мне интересно, нужно ли это для вашего использования.

EDIT

Я не знаю, для какого варианта использования вы используете эти параметры, но динамические аргументы вы можете использовать в Java, как этопример отсюда

// calculate average
        public static double average( double... numbers )
        {
           double total = 0.0; // initialize total

          // calculate total using the enhanced for statement
          for ( double d : numbers )              
             total += d;                          

          return total / numbers.length;
       } // end method average
2

что вы можете сгенерировать класс Java во время выполнения или, возможно, использовать какой-нибудь скрипт-движок, такой какBeanshell чтобы сгенерировать переменные, вы можете даже построить класс по его байт-коду. Но я не могу видеть, как вы будете использовать эти переменные в своем коде, вы также должны создать код для работы с этими переменными или использовать для этого отражение ...

A naive solution:
create a class with all variables from var000 to var999 with a getter for each... but that's not really dynamically!

Похожие вопросы