我将CustomObject
声明为原始类型<T>
。当我使用List<CustomObject>
新实例填充CustomObject
时,我无法将其作为Object
取回,仅作为public class CustomObject<T> {
private String name;
private T value;
// getters and setters
}
。
public class CustomObject {
private class SubCustomObject<T> {
private String name;
private T value;
}
public CustomObject() {
this.customObject = new SubCustomObject();
private SubCustomObject customObject;
// getters and setters
}
但是很明显,当我使用子类时,一切都在按预期工作;
public class CustomObject<T> {
private String name;
private T value;
private boolean isGroup;
// getters and setters
private void setValue(T value) {
if (value instanceof String) {
this.value = value;
this.isGroup = false;
}
if (value instanceof CustomObject) {
if (isGroup()) {
((List<CustomObject>) this.value).add((CustomObject) value);
} else {
this.value = (T) new ArrayList<CustomObject>();
this.isGroup = true;
setValue(value);
}
}
}
}
public void getItemByName(String name) {
// say the list is already populated
for (CustomObject object : listOfCustomObject) {
String nameField = object.getName();
if (name.equals(nameField) {
System.out.println(nameField);
}
}
}
有没有办法让第一个例子表现得像第二个例子,并避免使用额外的对象,所以我可以这样做:
public void getItemByName(String name) {
// say the list is already populated
for (Object object : listOfCustomObject) {
String nameField = ((CustomObject)object).getName();
if (name.equals(nameField) {
System.out.println(nameField);
}
}
}
而不是这一个:
public class MetadataEntry {
public MetadataEntry() {
this.entity = new Entry();
}
private class Entry<T> {
private String name;
private T value;
private boolean isGroup;
private void setValue(T value) {
if (value instanceof String) {
this.value = value;
this.isGroup = false;
}
if (value instanceof MetadataEntry) {
if (isGroup()) {
((List<MetadataEntry>) this.value).add((MetadataEntry) value);
} else {
this.value = (T) new ArrayList<MetadataEntry>();
this.isGroup = true;
setValue(value);
}
}
}
}
private Entry entity;
public void setName(String name) {
this.entity.name = name;
}
public String getName() {
return this.entity.name;
}
public void setValue(String value) {
entity.setValue(value);
}
public void setValue(MetadataEntry value) {
entity.setValue(value);
}
public boolean isGroup() {
return this.entity.isGroup;
}
public List<MetadataEntity> getChildNodes() {
if (isGroup()) {
return (List<MetadataEntry>) this.entity.value;
}
return null;
}
public String getValue() {
if (!isGroup()) {
return (String) this.entity.value;
}
return null;
}
}
//将此行为应用于此并避免使用内部类。
ControlValueAccessor
答案 0 :(得分:0)
您不能列出不同类型的X,Y,Z并将其放在W类型的单个容器中。您需要在原始类型上定义一个边界参数,以便您的项目和列表具有相同的类型。可能你的T应该受某些接口类型的限制,或者它应该扩展一些类。
答案 1 :(得分:0)
这是我的建议。我放弃了仿制药。现在有一个带有两个子类的抽象内部类,而不仅仅是一个内部类,一个用于组,一个用于不是组的条目。好消息:任何地方都不需要演员表。
public class MetadataEntry {
private String name;
static abstract class Entry {
abstract Entry setValue(String value);
abstract Entry setValue(MetadataEntry value);
abstract boolean isGroup();
abstract List<MetadataEntry> getChildNodes();
abstract String getSimpleValue();
}
static class SimpleEntry extends Entry {
private String value;
public SimpleEntry(String value) {
this.value = value;
}
@Override
Entry setValue(String value) {
this.value = value;
return this;
}
@Override
Entry setValue(MetadataEntry value) {
return new GroupEntry(value);
}
@Override
public boolean isGroup() {
return false;
}
@Override
public List<MetadataEntry> getChildNodes() {
return null;
}
@Override
public String getSimpleValue() {
return value;
}
}
static class GroupEntry extends Entry {
List<MetadataEntry> value;
public GroupEntry(MetadataEntry value) {
this.value = new ArrayList<>();
this.value.add(value);
}
@Override
Entry setValue(String value) {
return new SimpleEntry(value);
}
@Override
Entry setValue(MetadataEntry value) {
this.value.add(value);
return this;
}
@Override
public boolean isGroup() {
return true;
}
@Override
public List<MetadataEntry> getChildNodes() {
return value;
}
@Override
public String getSimpleValue() {
return null;
}
}
private Entry entity;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setValue(String value) {
entity = entity.setValue(value);
}
public void setValue(MetadataEntry value) {
entity = entity.setValue(value);
}
public boolean isGroup() {
return this.entity.isGroup();
}
public List<MetadataEntry> getChildNodes() {
return entity.getChildNodes();
}
public String getValue() {
return entity.getSimpleValue();
}
}
我使用了类似于1987年所说的关于返回其自身实例的类的想法。我将它应用于内部类只是为了让外部类的用户免于关心这个诡计。如果您愿意,我相信它可以应用于外部类。那么你将在外层有一个带有两个子类的abstrat类,并且不再需要内部类。这是你要求的事情之一,所以你可能更喜欢它,但它需要付出代价:任何在外层上调用setValue()
的人都需要记住他们有一个新的实例。
答案 2 :(得分:0)
我将CustomObject声明为
<T>
的原始类型。
这没有意义。您要么具有原始类型,要么具有泛型,而不是通用的原始类型。
当我使用新的实例填充列表时,我无法将其作为
CustomObject
取回,仅作为Object
。
因为您的列表不是通用的(总是很糟糕)。当您声明List<Something>
时,它会在Something
来电时返回get
。 Something
可以是通用的或原始类型。 List<CustomObject<String>>
将不接受CustomObject<Integer>
,并且使用原始类型List<CustomObject>
将以灾难结束,因此原始类型存在危险。
现在让我们来看看你的代码。班级
public class CustomObject<T> {
private String name;
private T value;
}
定义对任何类型的行为相同的对象。从本质上讲,你所拥有的仅仅是一个荣耀的Object
,并附有String
作为其名称。
然而,现在你做了
private void setValue(T value) {
if (value instanceof String)
// ...
if (value instanceof CustomObject)
// ...
}
分隔不同类型的行为。如果泛型类型不是String
或CustomObject
?
让我们尝试解决您的问题。由于仿制药旨在统一行为,因此,让我们看一下您试图获得的统一行为:
public void getItemByName(String name) {
for (CustomObject object : listOfCustomObject) {
String nameField = object.getName();
// ...
}
}
}
基本上,您要求listOfCustomObject
中的所有项都实现String getName()
方法。就我的问题而言,这就是我的意思。这意味着您的CustomObject<T>
应该使用该方法实现接口或扩展类(称为Superthing
)。然后,您只需将列表声明为List<? extends Superthing>
。
至于CustomObject
本身,它并不需要是通用的,因为你暗示你只想处理2种类型的泛型(你有2 if
s,但没有else
处理一般情况)。看起来你想要的是2个不同的类,其中不同的行为都实现或扩展了一个共同的超类型。
尝试这样的事情:
abstract class AbstractEntry {
private String name;
protected boolean isGroup;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public boolean isGroup() {
return isGroup;
}
}
class MetaEntry extends AbstractEntry {
AbstractEntry value;
MetaEntry(AbstractEntry value) {
this.value = value;
// handle isGroup
}
public void setValue(AbstractEntry value) {
this.value = value;
}
public AbstractEntry getValue() {
if (!isGroup)
return value;
return null;
}
}
class StringEntry extends AbstractEntry {
String value;
StringEntry(String value) {
this.value = value;
isGroup = false;
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
答案 3 :(得分:0)
我认为不需要列表,因为它总是只包含一个元素。正如@Ole V.V所述,该要求自然要求使用组合,事实上,通用不符合您的要求。以下是我将如何解决您的要求:
public interface Named {
public String getName();
public String getValue();
}
public class CustomObject implements Named {
private String name;
private String value;
private boolean isGroup;
// getters and setters
private boolean isGroup() {
return isGroup;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public class CustomObject2 implements Named {
private String name;
private CustomObject value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value.getValue();
}
public void setValue(CustomObject value) {
this.value = value;
}
}
public class DriverCustomObject {
public static void main(String arg[]) {
CustomObject t = new CustomObject();
t.setName("key1");
t.setValue("value1");
CustomObject2 t2 = new CustomObject2();
t2.setName("complex");
t2.setValue(t);
List<Named> list = new ArrayList<Named>();
list.add(t);
list.add(t2);
for (Named l : list) {
System.out.println(l.getName());
System.out.println(l.getValue());
}
}
}