【问题标题】:How to define a java object name with a variable?如何用变量定义java对象名?
【发布时间】:2013-10-25 12:45:42
【问题描述】:

我需要使用可通过循环轻松获得的命名模式来创建大量对象。有没有办法像这样从变量中读取对象名称?

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

我不需要为对象分配变量名,只需在分配时从中获取名称即可。

【问题讨论】:

  • 您的用例到底是什么?一开始,创建大量对象在内存中的成本很高,这表明这可能不是正确的解决方案。
  • 您能否重新提出这个问题,以便我们了解您需要什么?
  • 您不能创建 X 个具有唯一变量名的变量。这是没有意义的,因为变量只会在运行时可用,因此它们对你来说毫无用处。您应该将需要创建的所有对象(例如 ints)存储在一个数组中。
  • +1,因为当我开始使用 Java 时,我也想知道同样的事情。他可能首先会问是否有可以做到这一点的功能。其次,Java中有没有可以复制这个的特性

标签: java


【解决方案1】:

您选择的词语表明您没有完全理解变量和对象的工作方式,您需要解决这个问题才能使用 Java。

如果我写:

Item myItem = new Item();

我创建了一个新对象,并且我定义了一个指向该对象的变量。

对象没有名字(它有一个ID,这是一个在运行时分配的数字;大多数程序员可以忽略它)。

变量有一个名称,myItem。变量指向对象。稍后,它可能指向不同的对象。变量可能会超出范围并不再存在,而对象继续存在。

你可能会说,“那不重要。如果我说'对象的名称',我的意思是'指向对象的变量的名称'。”

但这很重要,因为很多对象都会被不止一个变量指向:

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.

...而且很多对象不会被变量直接指向。

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

在 Java(和大多数主流语言)中,您不能在运行时创建变量名。 唯一存在的变量名称是源代码中的字面意思

所以没有什么是这样的:

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

您也不能根据运行时数据按名称访问变量。所以没有什么可以像这样工作:

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

这是一件好事,因为它可以让编译器验证您的代码的某些内容。

在某些语言中,您可能会使用 eval() 实现类似的目标——但您应该远离它!

这是一个提示,如果您正在编写如下代码:

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

...那你做错了什么。它可能有效,但扩展性很差。没有办法将其放入循环中。 (别担心 - 我们大多数人在开始编程时都会遇到这个问题)。

如果您使用的是数组:

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

然后你可以使用循环代替:

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

数组是最简单的“集合”对象。还有集合、列表、地图和许多更高级的集合,以满足大多数需求。

您似乎想使用字符串作为键来存储和访问对象。这样做的方法是使用地图。

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

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

...

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

Map 是一个接口TreeMap 只是一个提供Map 接口实现的类。阅读标准 JRE 提供的 Map 的各种实现。

密钥不必是String。任何实现equals() 的东西都可以用作键。

使用这个:

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

但是,既然您已经说过您需要一个网格,那么使用 2D 数组可能会更好,并在需要时将数字坐标与字母网格参考进行转换。谷歌搜索“2D array Java”,你会发现很多例子。

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;
   }
}

除了标准的 JRE,Map 还有很多其他的实现。例如,Spring 提供了 DefaultRedisMap,其中对象存储在 Redis 数据库中。

更一般地说 - 你在这里问了一个非常基本的问题。您应该阅读任何一本不错的 Java 书籍中关于 Collections API 的章节。

【讨论】:

  • 我想做的不是存储对象,而是使用循环生成它们,以避免花费大量时间复制粘贴同一行144次并手动编辑名称然后让那些难看的文本块在视觉上弄乱我的代码。
  • @TheMather1 这就是这个答案的全部意义:你不能这样做,也不不应该你这样做。使用集合来存储您的对象。
  • @TheMather1 我添加了很多内容来纠正我猜你的一些误解。一个关键部分是唯一存在的变量名,是源代码中的字面意思。您不能在运行时创建变量名。
  • 很好的解释,但是在您的第二个代码 sn-p 中,我认为您的意思是 Item yourItem = myItem; (不带括号)
  • @TheMather1 - 看起来您想在循环中创建对象。为此,您需要创建一个对象数组,并按编号而不是名称来引用它们。 slim 的回答已经向您展示了如何做到这一点。
【解决方案2】:

根本不清楚你想要什么。如果要按名称查找对象,可以使用 Map

例子:

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

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

然后就可以找回来了:

Object obj = map.get(objectName);

【讨论】:

    【解决方案3】:

    容易获得吗?你研究过数组吗?如果你想使用字符串,那么一个字符串数组就足够了,还有 char 和 int 数组。

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

    我建议您阅读数组及其用途,我相信它可以解决您的问题。

    【讨论】:

    • 初始化数组变量时,不需要new。您可以简单地指定String[] myStringArray = {"hello", "world"};int[] myIntArray = {1, 2, 3, 6};
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 2010-11-24
    • 2013-11-26
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    相关资源
    最近更新 更多