Как получить доступ к существующим объектам со строковым вводом (Преобразовать строковый ввод в имя объекта)
Я создаю много объектов под названием: Obj1, Obj2.... ObjX
Object Obj1 = new Object();
Object Obj2 = new Object();
Object ObjX = new Object();
Теперь у меня есть функция, где я хочу получить доступ к одному из этих объектов.
public void useObject(int objectNumber) {
String objectName = "Obj" + objectNumber;
objectName.doAnythingWithThisObject();
}
Возможно ли что-то подобное в C# или Java? Я не хочу использовать что-то вроде:
switch(objectNumber) {
case 1:
Obj1.doThis();
break;
case 2:
Obj2.doThis();
break;
Если бы я использовал switch / if-else, я должен был бы повторить много кода, который делает эту вещь менее читаемой, потому что я должен вызывать одну и ту же функцию с разными объектами.
4 ответа
Фактический ответ таков: вы вообще не должны обращаться к своим переменным, используя строки во время выполнения. Случаев, когда это действительно уместно, мало и далеко друг от друга, и ваш пример, хотя и упрощенный, но может использоваться только для иллюстрации, не очень подходит для этого.
Вместо этого, почему бы вам просто не использовать коллекцию или массив для хранения ваших объектов? @TRRohith приводит пример в своем ответе.
Тем не менее, прямой ответ на ваш вопрос, в том, что касается Java, приведен ниже. Хотя код для C# будет другим, языковая функция, которая может использоваться для этой цели, а именно рефлексия, также доступна в C#.
Если Obj1
, Obj2
и т. д. объявляются как статические или экземпляры полей в классе, вы можете получить их значения по их именам, используя отражение (см. соответствующие документы для Java). Если они являются локальными для метода, простого способа сделать это не существует (см. Эти вопросы: для Java, для C#).
Статические поля
class Something {
static Object obj1 = new Object();
static Object obj2 = new Object();
// etc.
}
(Я взял на себя смелость начинать имена полей строчными буквами, как это принято в Java.)
В этом случае вы можете получить значение переменной по ее имени, используя следующий код (вам нужно импортировать java.lang.reflect.Field
):
// Get field, named obj1, from class Something.
Field f = Something.class.getDeclaredField("obj1");
// This line allows you access the value of an inaccessible (non-public) field.
f.setAccessible(true);
// Assigning the value of the field, named obj1, to obj.
// You may want to cast to a more concrete type, if you know exactly what is stored in obj1.
// The parameter for get() is ignored for static fields, so simply pass null.
Object obj = f.get(null);
// Now you can do whatever you want with obj,
// which refers to the same object as static field obj1 of Something.
System.out.println(obj);
Поля экземпляра
class Something {
Object obj1 = new Object();
Object obj2 = new Object();
// etc.
}
Вы можете сделать это почти так же, как для полей экземпляра, вам просто нужен экземпляр класса для передачи f.get()
, Итак, для примера, давайте предположим, что у нас есть экземпляр класса Something
, называется sth
,
// Let's say this is an instance of our class
Something sth = new Something();
// ...
// Get field, named obj1, from class Something.
Field f = Something.class.getDeclaredField("obj1");
// This line allows you access the value of an inaccessible (non-public) field.
f.setAccessible(true);
// Assigning the value of the field, named obj1, to obj.
// You may want to cast to a more concrete type, if you know exactly what is stored in obj1.
// The parameter for get() is the instance of Something,
// for which you want to retrieve the value of an instance field, named obj1.
Object obj = f.get(sth);
// Now you can do whatever you want with obj,
// which refers to the same object as instance field obj1 of sth.
System.out.println(obj);
Локальные переменные
Вам, вероятно, не повезло в этом случае. Опять же, смотрите следующие ссылки: Java, C#.
Вот код:
//Declare this in the class so that it can be called by any method
static Object[] array = new Object[4];
public static void main()
{
//Use this to initialize it
Object[] array = new Object[4];
for(int i=0;i<4;i++)
{
array[i] = new Object();
}
//You can now easily call it
useObject(0);
useObject(1);
useObject(2);
useObject(3);
}
//Your numbers may be off by 1 because we are using an array but that is easily adjusted
public static void useObject(int objectNumber)
{
array[objectNumber].doAnythingWithThisObject();
}
Ответ... нет. Вместо этого используйте массив. Это именно то, для чего они.
ObjectType[] objectArray = new ObjectType[10]; // Or as many as required.
for (int i = 0; i < objectArray.length; i++) {
objectArray[i] = new ObjectType(); // Or whatever constructor you need.
}
// Then access an individual object like this...
ObjectType obj = objectArray[4];
// Or...
objectArray[5].someMethod();