2009-07-28 2 views
4

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

+5

Это очень странно запрос ... что вы имеете в виду - «не знаю, сколько есть»? А когда будешь знать? Во время выполнения? Во всяком случае, это действительно выглядит как работа для класса коллекции. Почему вы не можете их использовать? Не могли бы вы рассказать нам больше о вашей проблеме? –

+0

Я знаю, что это странный запрос, но это сложная проблема, которую наш профессор ставит на стол. Поэтому я больше заинтересован в возможности делать это независимо от его удобства использования! Единственный трюк вокруг этого, что обнаружила моя группа, - это то, что «Маркус Лаусберг» уже предложил в отношении этой проблемы ... так и есть ли другой способ? –

+2

Надеюсь, ваш профессор не прочитает переполнение стека! Как его/ее зовут? –

ответ

2

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

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

List accountList = new ArrayList(); 




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

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

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

String a = accountList.get(i)); 
+1

Что такое flowCtx здесь? – Yatin

2

Вы имеете в виду вы хотите создать переменные с именами

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

В чем разница при использовании уага [0], уаг [1], вара [2], .....

НО

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

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

EDIT

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

// 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 
1

Это невозможно, но это идеальный кандидат на использование одной из коллекций java.

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

String[] arr = new String[RUNTIME_SIZE]; 

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

List list = new ArrayList<String>(); 
+1

Для записи это возможно на PHP. См. «Переменные переменные» в руководстве. –

+1

Извините, я не вижу никаких PHP-тег в этом вопросе ... –

2

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

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

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

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

+0

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

2

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

Наивное решение:
создать класс со всеми переменными из var000 в var999 с геттером для каждого ... но это на самом деле не динамически!

3

Без использования массива, ArrayList (и других видов списков и карты)

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

Или же используйте 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

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

+0

Спасибо за информацию :) –

2

Я еще не видел этого ответа, поэтому я поеду за ним. Напишите программу, которая просто выписывает исходный код Java. Большинство из них могут быть шаблоном, и у вас будет только цикл, в котором будет записываться столько переменных типа «строка UserString003», сколько вы хотите.

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

4

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

Вот код, который будет генерировать класс с именем «foo.bar.ClassWithFields», который содержит поля «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); 
     } 
    } 
} 
+0

Некоторые комментарии к коду действительно помогут :) спасибо! –

+2

Использует ASM библиотека для создания класса - массив байтов находится в том же формате, что и файлы .class, которые производит компилятор Java, а затем загружает его в JVM. пользовательский загрузчик классов. ASM работает на уровне байт-кода Java (аналогично ассемблеру), поэтому, чтобы понять вышеприведенный код, вам сначала нужно изучить некоторый байт-код Java (документация ASM хороша для этого: http://download.forge.objectweb.org/asm/ ASM-guide.pdf). Некоторые другие библиотеки манипулирования байт-кодами могут быть проще в использовании, чем ASM, потому что они более высокого уровня, чем чистый байт-код. Я думаю, что Джавассист - одна из таких библиотек. –

2

Похоже, ваш профессор PHP смещенной на функцию (Variable variables), так что он имел в виду, если это было возможно в Java.

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

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