这是一个实际问题,但我不确定它是否有实际答案。如果您有一个包含 10 个子类的父类(super class),那么将这 10 个子类放在一个集合中的最简单方法是什么?现在(这可能是糟糕的设计),我将它们放在父类(super class)的静态集合字段中。
然而,这个问题的动机来了,因为我已经获得了其中一个子类的字段之一的标识,但我需要对同一子类中的不同字段的引用。
例如,假设子类具有以下字段:
public class SampleSubClass extends SampleSuperClass{
...
private Object1 o_1;
private Object2 o_2;
private Object3 o_3;
...
}
在程序的其他地方,我只有 o_2 的标识,我想在 o_3 处获取。 理论上,可能有一种比将 SampleClass 的所有实例都放在某个集合中更简单的方法。例如,也许在我的梦想中,有一种软件语言,其中父类(super class)确实携带有关其子类的信息,并且父类(super class)本身充当集合。
但没关系。现在对我来说,将集合放在程序中的某个地方似乎是一个好方法,就是使用 HashMap /哈希表,并将其用作父类(super class)的静态成员。
请告诉我有更好的方法。有没有办法通过仅引用对象中的字段 B 来引用对象中的字段 A?
例如,假设我有一个 ActionPerformed 方法,它有一个包含在 ActionEvent 对象参数中的源对象。我如何找到拥有/包含该源对象的类的实例?设计这个的最佳方法是什么?
最佳答案
在给定字段引用的对象的情况下,没有本地方法可以找到字段的所有者。 JVM 记录指向每个对象的引用数,以便进行垃圾收集,但它不会跟踪引用的所有者。
您可以将所有字段的值存储在一个 Map
中,将它们映射到它们的所有者:
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();
}
}
关于Java:如何使用父类(super class)设计集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16929296/