我正在将Mysql数据库建模为Java中的练习。个人实验。并且我想将表排序规则存储为字符串,因为列可以具有与表不同的排序规则,我还需要为每个列存储它。如果列的collation字段只能指向表的collation字段,那将非常有用。但我知道Java没有指针。
你是否知道如何将一个物体的场地指向另一个物体的场地,以便两者始终匹配?
答案 0 :(得分: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中的字段,您必须记住一些事情。对象是面向对象编程语言中的基本元素,而不是名称。因此,您无法构建对对象内部名称的引用,因为如果您通过其基类型或超类型引用Object,则永远不会清楚。由于相同的名称可以存在于超类和子类中(这可以隐藏超类类型),因此如果不了解它们正在解析的实际类实例,就无法正确解析字段名称引用。
这是设计上的,不是偶然的。事实上,类的成员字段的外部知识正是使代码维护变得如此困难的原因,因为没有“垫片”可以在调用者和数据之间插入代码。通过封装数据(置于方法调用之后),可以为将来的代码维护设置阶段;因为,可以插入代码以根据可能更改的内部数据元素生成返回值。
一个例子
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
公开为Column
类型的数组,这不一定是坏事,直到我们决定我们希望它是List
Column
所以我们可以在新的漂亮Column
中动态添加或删除TableEditor
。
由于我们公开了基础数据元素,现在我们必须搜索整个代码库以查找该字段的任何用法,并重写所有用法,现在使用List
接口。实际上,我们需要甚至更多,因为我们还必须搜索可能直接使用columns
字段的每个外部库,因为我们不知道的多个JAR可能已经使用了这个公共类。
此外,我们很快就会注意到,我们使用columns
做的大部分内容实际上都是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 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();
}
}
答案 1 :(得分: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充当pass by value。在Objects的情况下,它充当引用传递。如果您将一个基元包装在一个通常建议的对象中,它将作为一个引用。但是,虽然字符串是对象,但它们也可以作为值传递。但是弦乐很奇怪。
答案 2 :(得分:1)
Java变量通过引用传递。因此,如果您已声明Object obj
,那么obj
将始终是您当前范围内同一对象的引用。将obj
传递给方法时,您不会传递对象的副本,而是传递对象的副本。
此外,Java还有用于实现Iterable
接口的集合的迭代器,您可能需要查看它。这些行为类似于List
或类似内容中的特定位置的指针。
答案 3 :(得分:0)
创建一个包含所有可能的排序规则类型列表的枚举,并将一个名为collationType的成员/属性添加到表和列类中,并将相同的枚举成员分配给它们相同的对象。