3

我正在将 Mysql 数据库建模为 Java 中的练习。个人实验。而且我想将表排序规则存储为字符串,因为列可以具有与表不同的排序规则,所以我也需要为每一列存储它。如果列的排序规则字段可以只指向表的排序规则字段,那将非常有帮助。但我知道 Java 没有指针。

您是否知道如何将一个对象的场指向另一个对象的场,以便两者始终匹配?

4

4 回答 4

6

Java 有引用,这是指针的优点,但不能进行指针数学运算。

public class Table {

  // name does not store a String, it stores a reference to a String
  private String name;

  // tableName is not passed in by copy, tableName's reference is passed in.
  public Table(String tableName) {
    // this is not a copy assignment, but a reference assignment
    name = tableName;
  }

}

至于总是指向 Java 中的一个字段,您必须记住一些事情。对象是面向对象编程语言中的基本元素,而不是名称。因此,您无法构建对对象内部名称的引用,因为永远不清楚您是通过其基类型还是通过超类型来引用该对象。由于相同的名称可以存在于超类和子类中(然后可以隐藏超类类型),如果不知道它们正在解析的实际类实例,就无法正确解析字段名称引用。

这是设计使然,而不是偶然。事实上,类成员字段的外部知识正是使代码维护如此困难的原因,因为没有“垫片”可以在调用者和数据之间插入代码。通过封装数据(放入方法调用之后),为未来的代码维护奠定了基础;因为,然后可以插入代码以根据可能更改的内部数据元素生成返回值。

一个例子

public class Table {

  public Column[] columns;

  public String name;

  public Table() {
    name = ...;
    columns = ...;
  }

}

public class CreateTableDDL {

  public String statement(Table table) {
    StringBuilder buffer = new StringBuilder();
    buffer.append("CREATE TABLE ");
    buffer.append(table.name);
    buffer.append(" (");
    for (int i = 0; i < table.columns.length; i++) {
      Column column = table.columns[i];
      ...
    }
    ...
    return buffer.toString();
  }

}

暴露columns为 type 的数组Column,这不一定是坏事,直到我们决定我们希望它是 a Listof ,这样我们就可以在新的 niftyColumn中动态添加或删除s 。ColumnTableEditor

由于我们暴露了基础数据元素,现在我们必须搜索整个代码库以找到该字段的任何用途,并将所有用途重写为现在使用List接口。实际上,我们需要做的还不止这些,因为我们还必须搜索每个可能columns直接使用该字段的外部库,因为我们不知道的多个 JAR 可能使用了这个公共类。

此外,我们很快就会注意到,我们所做的大部分工作columns实际上都是Table's 业务,但位于“帮助者”和辅助类中,这些类有损于表中最好本地化的职责。

最后,我们甚至可能注意到外部类正在修改表的列,而表并不知情。因为,它们绕过了任何可能通过直接抓取数据来提醒表注意更改的代码。

如果我们只是做了

public class Table {

  private Column[] columns;

  private String name;

  public Table() {
    name = ...;
    columns = ...;
  }

  public Column[] getColumns() {
    Column[] copy = new Column[columns.length];
    for (int i = 0; i < columns.length; i++) {
      copy[i] = columns[i].clone();
    }
    return copy;
  }

}

然后我们可以轻松地将基本存储转换为 aList并从列表中构建我们的“向后兼容”列数组。调用代码现在不需要更改,即使我们决定我们以前存在的columns字段现在需要是Map of String to DataType.

 public class CreateTableDDL {

  public String statement(Table table) {
    StringBuilder buffer = new StringBuilder();
    buffer.append("CREATE TABLE ");
    buffer.append(table.getName());
    buffer.append(" (");
    for (int i = 0; i < table.getColumns().length; i++) {
      Column column = table.getColumn(i);
      ...
    }
    ...
    return buffer.toString();
  }

}
于 2012-06-14T19:38:16.283 回答
3

首先是一些定义。请记住,术语传递并不是指用于管理数据的底层机制。它指的是您可以期望对该数据的操作会给您带来什么结果。

所有数据都存储在内存位置。这在 JVM 之间是如何定义的,并且与讨论无关。

指针是一个变量,它存储数据的内存位置,而不是实际数据。

引用是存储某种索引值的任何变量的通用术语,该索引值引用某些数据。所以指针是一种引用。在这个讨论中,我们关心的唯一类型。

现在在参考语言中,内存中的实际数据在分配期间不会被操作。数据保存在内存中。并且引用被分配一个值,告诉计算机去内存位置获取实际数据。当您将一个变量分配给另一个变量时,您分配的值与告诉计算机数据的内存位置相同的值。所以两个参考索引相同的数据。如果您更改实际数据,则两个引用都会索引新更改的数据。一次操作可以改变许多仅受计算机能力限制的变量。一个通用代码示例如下:

a = <valueof 1>; //"1" is now stored in memory, and a is a index to "1" in memory.
b = a; //b now indexes the same memory location as a. They both index the "1" in memory.

a = <value of 2>; //"2" now replaces "1" at the indexed memory location.
output a; //In this case would get the index value the language uses.
output b; //You'd get the same index value as a since they index the same memory location.
output <valueof a>; //Now you get "2", because however it's done in the language you have extracted the data in the memory location indexed by a.
output <valueof b>; //Same output as before as b indexes the same memory location as a.

在值传递语言中,b 仍然会得到 1,a 现在会得到 2。这是因为 b 不会被分配与 a 相同的引用。它将被分配该值作为新的参考。通用代码看起来相同,但会给您不同的结果。

a = <valueof 1>; //"1" is now stored in memory, and a is a index to "1" in memory.
b = a; //b now indexes a new memory location that now also stores "1".

a = <value of 2>; //"2" now replaces "1" at the indexed memory location.
output a; //You get "2" because a pass by value language will be designed to give you value, not the index.
output b; //You get "1" because when b was assigned to match a, a stored "1". But b is independent of a once assignment is complete.

混淆来自这样一个事实,即在某些情况下,Java 使用按引用传递机制来实现按值传递设计。在原语的情况下,Java 充当按值传递。在对象的情况下,它充当引用传递。而且,如果您将原语包装在通常推荐的对象中,它将充当引用传递。但是,虽然字符串是对象,但它们也可以作为值传递。但是字符串很奇怪。

于 2012-06-14T23:55:50.603 回答
1

Java 变量通过引用传递。因此,如果您已声明Object obj, thenobj将始终是对当前范围内同一对象的引用。传递obj给方法时,传递的不是对象的副本,而是对它的引用。

此外,Java 还具有用于实现该接口的集合的迭代器Iterable,您可能想研究一下。这些行为就像指向 aList或类似中特定位置的指针。

于 2012-06-14T19:42:00.450 回答
0

您创建一个包含所有可能排序规则类型列表的 Enum,并向 Table 和 Column 类添加一个名为 collat​​ionType 的成员/属性,并将相同的 Enum 成员分配给它们相同的对象。

于 2012-06-14T19:42:38.403 回答