I'm modeling Mysql databases as en exercise in Java. Personal experiment. And I want to store the table collation as a string, since the columns can have different collation then the tables, I need to store that also for each column. It would be very helpful if the column's collation field could just point to the table's collation field. But I know that Java doesn't have pointers.
Do you have an idea on how I can point the field of one object, to he field of another object so the two will always match?
Java has references, which are the good parts of pointers without the ability to do pointer math.
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;
}
}
As far as always pointing to a field in Java, you must keep in mind a few things. Objects are the basic element in an Object-Oriented programming language, not names. As such, you cannot build a reference to an object's internal names, as it is never clear if you are referencing the Object by its base type or by a super type. Since identical names can exist in both super classes and sub classes (which could then hide the super class type), field name references cannot be correctly resolved without knowledge of the actual class instance they are getting resolved upon.
This is by design, not by accident. In fact, external knowledge of a class's member fields is exactly what makes code maintenance so difficult, as there is no "shim" where one can insert code between the caller and the data. By encapsulating the data (putting in behind a method call) one sets the stage for future code maintenance; because, one can then insert code to generate the return values based on possibly changing internal data elements.
An example
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();
}
}
exposes columns as an array of type Column, which isn't necessarily a bad thing, until we decide we want it to be a List of Column so we can dynamically add or remove Columns in a new nifty TableEditor.
Since we exposed the base data element, now we must search through the entire code base to find any use of the field, and rewrite all uses to now use a List interface. Actually, we need to do even more than that because we must also search through every external library that might have used the columns field directly, as multiple JARs unknown to us might have used this public class.
In addition, we will quickly notice that most of what we are doing with columns is really the Table's business, but located in "helpers" and auxillary classes which detract from responsibilities best localized in Table.
Finally, we might even notice that external classes are modifying the columns of a table without the table's knowledge; because, they bypass any code that might alert the table to the change by grabbing the data directly.
If we had simply done
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;
}
}
Then we could have easily converted the base storage to a List and just constructed our "backwards compatible" array of columns from the list. The calling code now doesn't require a change, even if we decide that our previously existing columns field now needs to be a 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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With