在我的程序中,我有两个类,一个叫做GlassPiece,另一个叫做TrackerChip。
这两个对象总是“强烈连接”,也就是说,没有两个GlassPieces可以共享TrackerChip,并且没有两个TrackerChip可以共享一个GlassPiece。因此,在我的setter方法中,我需要注意断开任何旧的引用,如下所示:
public class TrackerChip
{
GlassPiece linkedGlassPiece;
public void setGlassPiece(GlassPiece newGlassPiece)
{
GlassPiece oldGlassPiece = linkedGlassPiece;
linkedGlassPiece = newGlassPiece;
if(oldGlassPiece != null)
{
oldGlassPiece.setTrackerChip(null); //disconnect old GlassPiece
}
if(linkedGlassPiece != null && linkedGlassPiece.getTrackerChip() != this)
{
linkedGlassPiece.setTrackerChip(this); //update counterpart
}
}
}
并且方法GlassPiece.setTrackerChip(TrackerChip)以同样的方式工作。
问题是,上面的代码实际上并不起作用,并且在尝试管理几个不同的GlassPieces和TrackerChips之间的链接时会发生奇怪的事情。但是,如果我用:
替换最后一部分 if(newGlassPiece != null && newGlassPiece.getTrackerChip() != this)
{
newGlassPiece.setTrackerChip(this);
}
然后一切正常。这对我来说似乎很奇怪(我所做的只是用newGlassPiece替换了LinkedGlassPiece,实例变量,参数)。但是在方法的早期,我将引用设置为彼此相等!为什么第一种方法不起作用?
P.S。我可以确认方法中没有无限循环。
答案 0 :(得分:1)
至于为什么这不起作用,你是对的,它不会无限循环,但它不会做你期望的。
老实说,我想不出一种让你按照自己的方式工作的方法。您将不得不添加一些额外的参数,使其不再可重入。也就是说,当你在oldGlassPiece上调用setTrackerChip时,它不会转向并调用相同的TrackerChip,将其引用设置为null。也许只是一个布尔标志,表明它不应该使第二级引用无效。
以下是一些代码:
public class TrackerChip
{
GlassPiece linkedGlassPiece;
public void setGlassPiece(GlassPiece newGlassPiece)
{
setGlassPiece(newGlassPiece, true);
}
public void setGlassPiece(GlassPiece newGlassPiece, boolean reentrant)
{
GlassPiece oldGlassPiece = linkedGlassPiece;
linkedGlassPiece = newGlassPiece;
if(reentrant && oldGlassPiece != null)
{
oldGlassPiece.setTrackerChip(null, false); //disconnect old GlassPiece
}
if(linkedGlassPiece != null && linkedGlassPiece.getTrackerChip() != this)
{
linkedGlassPiece.setTrackerChip(this); //update counterpart
}
}
}
答案 1 :(得分:0)
我建议只使用一对管理关系的静态HashMaps,而不是采用这种方法。那可能会简单得多。如果您的用例不是单线程,则可能存在线程安全问题,但您只需要同步设置它的方法。也许创建一个关系管理对象如下:
public class RelationshipMgr {
HashMap<GlassPiece, TrackerChip> gpMap;
HashMap<TrackerChip, GlassPiece> tcMap;
public void setRelationship(GlassPiece gp, TrackerChip tc) {
gpMap.put(gp, tc);
tcMap.put(tc, gp);
}
}
实际上,在Google Guava库中,甚至有一个类可以用于此类事件BiMap,请查看它。
答案 2 :(得分:0)
如果总是存在一对一的关系,那么考虑将这些类合并为一个可能是值得的。
答案 3 :(得分:0)
我认为这应该有效:
public class TrackerChip {
GlassPiece linkedGlassPiece;
public void setGlassPiece(GlassPiece newGlassPiece) {
if (linkedGlassPiece == newGlassPiece) {
return;
}
if (linkedGlassPiece != null) {
GlassPiece tmp = linkedGlassPiece;
linkedGlassPiece = null;
tmp.setTrackerChip(null);
}
if (newGlassPiece != null) {
linkedGlassPiece = newGlassPiece;
linkedGlassPiece.setTrackerChip(this);
}
}
}