给定字段引用的对象,没有本地方法可以找到字段的所有者。JVM 记录指向每个对象的引用数,以便它可以进行垃圾收集,但它不会跟踪引用的所有者。
您可以将所有字段的值存储在将Map
它们映射到其所有者的 a 中:
import java.util.*;
public class Super
{
static Map<Object, Super> owners = new IdentityHashMap<Object, Super>();
// IdentityHashMap will not work with primitives due to autoboxing,
// but HashMap requires all field values to have sensible implementations
// of hashCode() and equals().
/** Gets the owner associated with a field. */
public static Object getOwner(Object field)
{
return owners.get(field);
}
/** Establishes ownership over a field. */
protected void own(Object field)
{
owners.put(field, this);
}
/** Removes an ownership, but only if this is the owner. */
protected void disown(Object field)
{
if (owners.get(field) == this) owners.remove(field);
}
/** Shorthand for disown(oldField); own(newField). */
protected <T> T change(T oldField, T newField)
{
disown(oldField);
own(newField);
return newField;
}
}
public class SubA extends Super
{
protected String s;
protected Integer i;
public SubA(String aString, Integer anInt) { setS(aString); setI(anInt); }
public void setS(String aString) { s = change(s, aString); }
public void setI(Integer anInt) { i = change(i, anInt); }
public String toString() { return "SubA(" + s + "," + i + ")"; }
}
public class SubB extends Super
{
protected Object o;
public SubB(Object anObject) { setO(anObject); }
public void setO(Object anObject) { o = change(o, anObject); }
public String toString() { return "SubB(" + o + ")"; }
}
public class Demo
{
public static void main(String[] args)
{
String s1 = "String1", s2 = "String2", s3 = "String3";
Integer i1 = 111, i2 = 222;
Object o1 = new Object(), o2 = new Object();
SubA a1 = new SubA(s1, i1), a2 = new SubA(s2, i2);
SubB b = new SubB(o1);
p("s1 owner = %s", Super.getOwner(s1)); // SubA(String1,111)
p("s2 owner = %s", Super.getOwner(s2)); // SubB(String2,222)
p("s3 owner = %s", Super.getOwner(s3)); // null
p("i1 owner = %s", Super.getOwner(i1)); // SubA(String1,111)
p("i2 owner = %s", Super.getOwner(i2)); // SubA(String2,222)
p("o1 owner = %s", Super.getOwner(o1)); // SubB(java.lang.Object@...)
p("o2 owner = %s", Super.getOwner(o2)); // null
p("s1 -> s3, o1 -> o2");
a1.setS(s3);
b.setO(o2);
p("s1 owner = %s", Super.getOwner(s1)); // null
p("s3 owner = %s", Super.getOwner(s3)); // SubA(String3,111)
p("o1 owner = %s", Super.getOwner(o1)); // null
p("o2 owner = %s", Super.getOwner(o2)); // SubB(java.lang.Object@...)
}
static void p(String fmt, Object... args)
{
System.out.format(fmt, args);
System.out.println();
}
}
或者,您可以通过继承或使用包装类使字段值本身维护对其所有者的引用:
public class OwnableObject
{
protected Object owner;
public OwnableObject(Object anOwner) { owner = anOwner; }
public Object getOwner() { return owner; }
public void setOwner(Object anOwner) { owner = anOwner; }
}
public class MyString extends OwnableObject
{
protected String str = null;
public MyString(Object anOwner) { super(anOwner); }
public String toString() { return str; }
public void set(String aString) { str = aString; }
}
public class FieldWrapper<E> extends OwnableObject
{
protected E value = null;
public FieldWrapper(Object anOwner) { super(anOwner); }
public E getValue() { return value; }
public void setValue(E aValue) { value = aValue; }
}
public class Demo
{
protected MyString s = new MyString(this);
protected FieldWrapper<Integer> i = new FieldWrapper<Integer>(this);
public void setS(String aString) { s.set(aString); }
public void setI(int anInt) { i.setValue(anInt); }
public String toString() { return "Demo(" + s + "," + i.getValue() + ")"; }
public static void main(String[] args)
{
Demo d1 = new Demo();
Demo d2 = new Demo();
MyString f1 = d1.s;
FieldWrapper<Integer> f2 = d1.i;
OwnableObject f3 = d2.s;
OwnableObject f4 = d2.i;
d1.setS("one");
d2.setS("two");
d1.setI(1000);
d2.setI(2000);
p("f1 = %s, owner = %s", f1, f1.getOwner());
p("f2 = %d, owner = %s", f2.getValue(), f2.getOwner());
p("f3 = %s, owner = %s", f3, f3.getOwner());
p("f4 = %s, owner = %s", f4, f4.getOwner());
}
static void p(String fmt, Object... args)
{
System.out.format(fmt, args);
System.out.println();
}
}