4

I need to create a large number of objects using a pattern of naming easily obtainable through a loop. Is there any way to have an object name be read from a variable, like this?

String Var = "ObjectName";
ClassName Var = new ClassName();

I don't need the object to be assigned a variable name, merely to obtain the name from it at the time of assignment.

The Mather1
  • 53
  • 1
  • 1
  • 4
  • What exactly is your use-case? Creating a lot of objects is costly in memory for a start and suggests maybe this is not the correct solution. – Trisha Oct 25 '13 at 12:48
  • Can you re-word this question, so we can understand what do you need ? – FazoM Oct 25 '13 at 12:48
  • You can't create X amount of variables that has a unique variable name. That makes no sense, as the variables would only be avaiable at runtime, and hence making them useless to you. You should store all objects you need to create - `int`s for example - in an array. – Birb Oct 25 '13 at 12:49
  • I'm creating a 12x12 grid of objects that are to be named according to their place on the X and Y axis, from AA to AL in the top and LA to LL at the bottom. Seeing as manually generating 144 objects is a somewhat tedious job, I've created a loop to generate the names as strings, but when I try to use what I wrote above it tries to use the string's name as the object name rather than its value. – The Mather1 Oct 25 '13 at 12:54
  • 1
    Use a `Map`: http://docs.oracle.com/javase/tutorial/collections/interfaces/map.html – millimoose Oct 25 '13 at 12:55
  • Can't you just make an array of objects and have the name be contained within the object? – Dom Oct 25 '13 at 12:56
  • 3
    +1 because I've also wondered the same thing when I started using Java. He's probably asking first if there is a feature that can do this. Then second, is there a feature in Java that can duplicate this – But I'm Not A Wrapper Class Oct 25 '13 at 12:57
  • Nope. You can use arrays or maps to associate values with "names", you can even generate code automatically (basically write a new .java file from your program) to generate repeated code patterns. But you cannot assign to a runtime-determined variable name or use a runtime-determined name to fetch from a variable. – Hot Licks Oct 25 '13 at 13:04
  • (Besides, if you need to have that many similar names then you're doing something wrong.) – Hot Licks Oct 25 '13 at 13:04
  • @Trisha I don't think by "large number of objects" he means RAM-threatening amounts. – slim Oct 25 '13 at 13:24
  • Even if you are able to assign instance/object name at runtime how are you going to access that instance/object ? Using array or collection will help you, you can access instance using index or name – Abdullah Shaikh Oct 25 '13 at 13:28
  • As an aside, check out Java's capitalisation conventions. People generally expect identifiers beginning with an uppercase letter to be classnames, while variables are expected to begin with a lowercase. Hence: `String string = new String();` -- it helps the reader. – slim Oct 25 '13 at 16:11

3 Answers3

23

Your choice of words shows that you don't fully understand the way variables and objects work, and you need to fix that to get anywhere with Java.

If I write:

Item myItem = new Item();

I create a new object, and I define a variable which points to that object.

The object does not have a name (it has an ID, which is a number assigned at runtime; most programmers can ignore it).

The variable has a name, myItem. The variable points to the object. Later on, it might point to a different object. The variable might fall out of scope and cease to exist, while the object continues to exist.

You might say, "that's not important. If I say the 'name of the object', I mean 'the name of the variable pointing to the object'."

But it is important, because lots of objects will be pointed to by more than one variable:

Item myItem = new Item();
Item yourItem = myItem;
// both variables point to the same object. Neither variable is "more" the
// owner of the object than the other.

... and lots of objects won't be pointed to directly by a variable.

myList.append(new Item()); 
// you can't get at this new object using a direct variable.

In Java (and most mainstream languages), you can't create variable names at runtime. The only variable names that exist, are ones that are literally in the source code.

So there's nothing that works like this:

int number = 1;
Cell cell$number = new Cell(); // can't be done!
Cell currentCell = cell1; 

Nor can you access variables by name, based on runtime data. So there's nothing that works like this:

Cell cell1 = ...;
int number = 1;
Cell currentCell = cell$number; // can't be done!

This is a good thing because it lets the compiler validate certain things about your code.

In some languages you could possibly achieve something like this using eval() -- but you should run a mile from it!

This is a hint that if you're writing code like:

 Cell cell0 = new Cell(...);
 Cell cell1 = new Cell(...);
 ...
 Cell cell99 = new Cell(...);

... then you're doing something wrong. It may work, but it scales badly. There is no way to put this into a loop. (Don't worry - most of us hit this issue when we began programming).

If, instead you'd used an array:

 Cell[] cells = new Cell[];
 cells[0] = new Cell(...);
 cells[1] = new Cell(...);
 ...
 cells[99] = new Cell(...);

Then you could use a loop instead:

 for(int i = 0; i<100; i++) {
     cells[i] = new Cell(...);
 } 

An array is the simplest of "collection" objects. There are also Sets, Lists, Maps, and a host of more advanced collections, to suit most needs.

You seem to want to store and access objects using strings as a key. The way to do this is using a Map.

Map<String,Cell> myMap = new TreeMap<String,Cell>();

myMap.put("AA", new Cell(...));
myMap.put("AB", new Cell(...));

...

Cell currentCell = myMap.get("AA");

Map is an interface. TreeMap is just one class that provides an implementation of the Map interface. Read up on the various implementations of Map provided by the standard JRE.

The key doesn't have to be a String. Anything that implements equals() can be used as a key.

Using this:

for(char c = 'A'; c <= 'L'; c++) {
   for(char d = 'A'; d<= 'L'; d++) {
       myMap.put("" + c + d, new Cell(...));
   }
}

However, since you've said you want a grid, it's probably better to work with a 2D array, and translate the numeric coordinates to and from a lettered grid-reference whenever you need to. Google for "2D array Java", and you'll find plenty of examples.

Cell[][] cells = new Cell[12][12];
for(int x=0; x<12; x++) {
   for(int y=0; y<12; y++) {
       Cell cell = new Cell();
       cell.setName( "" + ('A' + x) + ('A' + y)); // perhaps
       cells[x][y] = cell;
   }
}

Beyond the standard JRE, there are plenty of other implementations of Map. For example, Spring provides DefaultRedisMap, in which the objects are stored in a Redis database.

More generally - you have asked a very basic question here. You should read the chapter on the Collections API in any decent Java book.

slim
  • 40,215
  • 13
  • 94
  • 127
  • What I wish to do is not to store the objects, merely to use a loop to generate them so as to avoid spending a large amount of time copypasting the same line 144 times and editing the names by hand and then have that unsightly block of text visually mess up my code. – The Mather1 Oct 25 '13 at 13:04
  • @TheMather1 That's the whole point of this answer: You can't do it, nor *should* you do it. Use a collection to store your objects. – Anthony Grist Oct 25 '13 at 13:22
  • @TheMather1 You do want to store the objects - in memory. That's why you're asking about creating variable names -- as a way to access the stored objects. The basic Map implementations also store in memory. – slim Oct 25 '13 at 13:27
  • As I've said several times now, I don't want the name to be variable, I just want to use a variable to assign the name, so that a single line used in a loop can be used to generate each of the objects. – The Mather1 Oct 25 '13 at 14:13
  • OK, what do you mean by "name"? Not, apparently, the name of the variable? – slim Oct 25 '13 at 14:19
  • 1
    @TheMather1 I added quite a bit to correct what I guess are some misconceptions you have. A key part is **The only variable names that exist, are ones that are literally in the source code**. You can't create variable names at runtime. – slim Oct 25 '13 at 14:45
  • When you create an object, you do so by making a Class Object = new Class() command. I'm looking for a way that allows me to use a variable in place of "Object", so that by changing the variable, a single loop would allow me to create multiple objects. For instance, the first time the loop runs, the object AA is created, the second time, AB, the third time AC, and so on. – The Mather1 Oct 25 '13 at 15:18
  • 1
    Nice explanation, but in your 2nd code snippet, I think you mean Item yourItem = myItem; (without the parentheses) – NickJ Oct 25 '13 at 15:46
  • 1
    @TheMather1 - looks like you want to create objects in a loop. To do that, you'll need to create an array of objects, and refer to them by number, not by name. slim's answer already shows you how to do that. – NickJ Oct 25 '13 at 15:54
  • @NickJ Thanks, that was the answer I was looking for. – The Mather1 Oct 25 '13 at 15:56
  • I'm really sorry here, but I'm now getting a problem where it won't recognize the cells[][] array when a method is attempted called with it, simply returning a "can't find symbol /n symbol: variable cells" error even though it poses no quarrels with generating it. – The Mather1 Oct 26 '13 at 00:47
  • Sounds like you're trying to reference the variable outside its scope. – slim Oct 29 '13 at 14:28
  • What do you mean with “it has an ID, which is a number assigned at runtime”? If you are confusing object identity with hash codes, the “identity hash code” is not guaranteed to be unique, hash collisions may happen, hence, it is *not* an ID. Objects have an *identity*, which you can check via `reference1 == reference2`, but the nature of this identity is intentionally unspecified. – Holger Oct 17 '18 at 11:28
2

It's not at all clear what you want. If you want to look up objects by name, you could use a Map

Example:

Map<String, Object> map = new HashMap<String, Object>();

String objectName = ...// get name of object
Object object = ...// get object
map.put(objectName, object);

Then it can be retrieved:

Object obj = map.get(objectName);
NickJ
  • 9,380
  • 9
  • 51
  • 74
1

Easily obtainable? Have you looked into Arrays? If you want to use Strings then a string array will suffice, there are also char and int arrays.

    String[] myStringArray = new String{"hello", "world"};
    int[] myIntArray = new int{1, 2, 3, 6};

I suggest you read up on arrays and their uses, I believe it may solve your problem.

slim
  • 40,215
  • 13
  • 94
  • 127
David MacNeil
  • 126
  • 11
  • When you initialize an array variable, you don’t need `new`. You can simply specify `String[] myStringArray = {"hello", "world"};` and `int[] myIntArray = {1, 2, 3, 6};` – Holger Oct 17 '18 at 11:31