Grundsätzlich habe ich ein veränderbares Objekt in Java und auf seinen Zustand wird sowohl zugegriffen als auch durch verschiedene Methoden einer bestimmten Klasse geändert. Die im Objekt gespeicherten Daten werden auch von einer anderen Klasse verwendet. Der Unterschied besteht jedoch darin, dass die zweite Klasse die Daten nicht ändern darf, nur um sie zu verwenden.Einen unveränderlichen Verweis auf ein veränderbares Objekt in Java zurückgeben
In C++ würde ich normalerweise nur eine const
Referenz auf das Objekt übergeben, aber ich weiß, dass es keine direkte Entsprechung in Java gibt.
Nur um zu klären, der folgende Code-Schnipsel zeigt, was ich im Sinn haben:
public interface Figure
{
void onSizeChanged(SizeInfo info);
void draw();
}
public class FigureView extends View
{
private Figure figure;
private SizeInfo sizeInfo;
...
public void onResize()
{
//Modify the state of sizeInfo, then pass it to the figure.
figure.onSizeChanged(sizeInfo);
}
}
Lasst uns sagen, dass SizeInfo
ein großes Objekt ist, so will ich nicht eine element Kopie machen, aber nur passieren es als Referenz. Der obige Code ermöglicht es Figure
, auf die Daten des SizeInfo
Objekts zuzugreifen, aber es ermöglicht auch das Figure
, das Objekt zu ändern. Fehler, die durch ein solches Verhalten verursacht werden, können schwer zu verfolgen sein. Daher möchte ich eine "unveränderliche Referenz" an die SizeInfo
übergeben.
Die beste Lösung, die ich bisher gefunden habe, ist eine nicht-statische innere Klasse von SizeInfo
zu schaffen, die von Getter besteht nur:
public class SizeInfo
{
//These represent the large set of data inside the class.
private long foo;
private double bar;
private Export mExport = new Export();
//Setters (only available if you have a direct reference to SizeInfo):
public void incrementFoo()
{
foo++;
}
public void setBar(double bar)
{
this.bar = bar;
}
//SizeInfo getters:
public long getFoo()
{
return foo;
}
public double getBar()
{
return bar;
}
public double getBaz()
{
return bar * foo;
}
//A non-static inner class:
public class Export
{
public long getFoo() { return foo; }
public double getBar() { return bar; }
public double getBaz() { return bar * foo; }
}
public Export export() { return mExport; }
}
Mit diesem Code, müssen Sie nur die Methodensignatur in Figure
ändern von onSizeChanged(SizeInfo)
bis onSizeChanged(SizeInfo.Export)
und übergeben sizeInfo.export()
an die Methode statt sizeInfo
, damit es wie erwartet funktioniert. Dies ist sehr einfach von der Client-Seite zu verwenden, aber die Code-Redundanz, die dadurch verursacht wird, dass jeder Getter zweimal wiederholt werden muss, ist definitiv nicht elegant. Die Alternative, die Getter nur in SizeInfo.Export
zu platzieren und jede sizeInfo.getBaz()
durch sizeInfo.export().getBaz()
zu ersetzen, ist noch schlimmer. Deshalb suche ich einen eleganteren Ansatz.
Ich realisiere, dass dieses bestimmte Beispiel möglicherweise nicht glaubhaft in Bezug auf SizeInfo
ist zu groß, um nur ein memberwise Klon zu erstellen. Es gibt jedoch unzählige andere Beispiele. Zum Beispiel, wenn ich ein veränderliches Objekt hätte, das die ARGB-Daten eines Bildes repräsentiert (vielleicht weil das Bild Pixel für Pixel unter Verwendung einiger mathematischer Formeln erzeugt wurde), und es dann an eine Methode übergeben wollte, die nicht in der Lage sein sollte Um es zu ändern, würde das Problem immer noch auftreten.