繁体   English   中英

如何在Java中模拟指针类型操作,或者Java是按引用传递或按值传递?

[英]How to Simulate Pointer Type Action in Java, or Is Java Pass-By-Reference or Pass-By-Value?

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

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

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

}

columnsColumn类型的数组,这不一定是一件坏事,直到我们决定让它成为Column List ,以便我们可以在新的漂亮TableEditor动态添加或删除Column

由于我们公开了基本数据元素,因此现在我们必须搜索整个代码库以查找该字段的任何用法,并重写所有用法以现在使用List接口。 实际上,我们需要做的甚至更多,因为我们还必须搜索可能直接使用了columns字段的每个外部库因为我们未知的多个JAR可能已经使用了此公共类。

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

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

如果我们只是做了

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

}

然后,我们可以轻松地将基本存储转换为List然后从列表中构造我们的“向后兼容”列数组。 现在,即使我们确定以前存在的columns字段现在需要是Map of String to DataTypeMap 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();
  }

}

首先是一些定义。 并且请记住,术语传递不涉及用于管理数据的底层机制。 它指的是您可以期望对该数据进行操作而获得的结果。

所有数据都存储在存储位置中。 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充当按值传递。 对于对象,它充当引用传递。 而且,如果通常建议将原语包装在对象中,则按引用将其用作pas。 但是,尽管字符串是对象,但它们也可以作为按值传递。 但是字符串很奇怪。

Java变量通过引用传递。 因此,如果您已声明Object obj ,那么obj将始终是当前作用域中对同一对象的引用。 obj传递给方法时,不是传递对象的副本,而是传递对该对象的引用。

此外,Java还为实现Iterable接口的集合提供了Iterators,您可能需要研究一下。 它们的作用类似于指向List或类似List特定位置的指针。

您创建一个具有所有可能的排序规则类型的列表的枚举,然后将名为collat​​ionType的成员/属性添加到Table和Column类,然后将相同的Enum成员分配给相同的对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM