Java可以轻松快速地创建实例getter

时间:2018-03-24 11:58:40

标签: java hashmap attributes instance getter

我正在存储LOAD CSV WITH HEADERS FROM "file:///output.csv" AS line MERGE (sub:Item {name:line.source}) MERGE (sup:Item {name:line.target}) WITH sub, sup, line CALL apoc.create.relationship(sub, line.Relationshiptype, NULL, sup) YIELD rel RETURN sub, rel, sup HouseCarClothes等类; FacialFeaturesPerson的所有部分:

HashMap

外部使用:

public class Person {
    private HashMap<String, PersonalItem> map = new HashMap<String, PersonalItem>();

    public void init(){
        map.put("house", new House());
        map.put("car", new Car());
        map.put("clothes", new Clothes());
        //etc...

    }

    public PersonalItem getPersonalItem(String name){
        return map.get(name);
    }
}

如果我使用以下代码,我怎么能这样做:

public static void main(String[] args){
Person person = getPerson(args);

//if i want to use car.setColor(blue); i have to do:

    ((Car) person.getPersonalItem("car")).setColor(blue);

//or if i want to use house.setExterior(wooden); i have to do:

    ((House) person.getPersonalItem("house")).setExterior(wooden); 

}

如果输入为&#34; house,它将起作用,person.getPersonalItem("house").setExterior(wooden); 将返回getPersonalItem。&#34;我不想每次都写出一个吸气剂:

Object instanceof House

有替代方案吗?

5 个答案:

答案 0 :(得分:4)

你可以使用的一个(脏?)技巧是使用Class对象作为地图的键而不是任意名称,并直接在getter中向下转换:

public class Person {
    private Map<Class<? extends PersonalItem>, PersonalItem> map = new HashMap<>();

    public void init() {
        map.put(House.class, new House());
        map.put(Car.class, new Car());
        map.put(Clothes.class, new Clothes());
        //etc...

    }

    public <T extends PersonalItem> T getPersonalItem(Class<T> cls) {
        return (T) map.get(cls);
    }

你仍然有一个演员阵容,但它只限于一个地方,当使用 Person类时你不必知道它:

person.getPersonalItem(House.class).setExterior(wooden);

这种方法的缺点是一个人不能拥有两个相同类型的个人物品。

答案 1 :(得分:1)

您尝试做的事情在类型安全方面并不安全 执行可能在运行时发生的强制转换以避免多重方法并不是一件好事 在你的情况下,我想知道从地图访问值是否真的有意义 如果Map定义Person类的状态,则为每个类使用相应的字段和getter 如果您有很多并且不想编写/污染您的类,您可以在编译时使用Lombok为您生成getter(以及其他样板代码)。

作为Mureinik的替代方法,您可以在getPersonalItem()方法中使用泛型来从调用的客户端推断类型。通过这种方式,您可以在地图中有多个对象具有相同类型的条目。

@SuppressWarnings("unchecked")
public <T extends PersonalItem> T getPersonalItem(String name, Class<T> clazz){
    return (T) map.get(name);
}

并调用它:

person.getPersonalItem("myHouse", House.class).setExterior(stone);
person.getPersonalItem("mySecondHouse", House.class).setExterior(wooden);

答案 2 :(得分:1)

听起来你正在使用字符串+ map方法来避免显式getter(和setter)。但是你扔掉了所有的编译时类型信息。所以编译器可以在这里给你很多帮助。实际上,其他答案中的方法不会保护您免于意外地将Car类型与"house"相关联。

如果需要考虑详细程度,可以使用其他选项来保留编译时类型:

  1. 代码生成(例如ImmutablesLombok)。这些都很好,但需要额外的工具和构建步骤。

  2. 使用Kotlin,特别是data classes。它们尽可能简洁,Kotlin与Java有很好的互操作性。

  3. 我强烈主张#2 - 我使用这种方法经历了高效益和低摩擦(即在Kotlin中定义类型,然后从Java代码库中消费它们)。

答案 3 :(得分:1)

我会使用一个文件或数据库表,其中存储可能的关键字,链接到类,如

  

人:房子,汽车,衣服;房子:车主,车库

等等,如果它是一个文件,如果它是一个数据库表,那么

  

属性(id,className,propertyName)

可以提供帮助。无论输入是什么,你都可以编写一个生成类的代码,比如PersonDefinition,其中定义了getter和setter(当然,你也可以处理属性类型,为了简单起见我省略了这个) / p>

然后确保从Person继承PersonDefinition,并且无论何时构建项目,预构建事件都应生成PersonDefinition class,因此您将拥有所有你需要的安装者和吸气剂。

答案 4 :(得分:1)

使用泛型的解决方案和类对象作为地图的关键似乎对我来说最好。但是,如果是一个类,例如House尚未添加到地图中:

person.getPersonalItem(House.class).setExterior(wooden);

可以在IDE中使用代码完成进行编程,但在运行时会给出空指针。以前有人给出了解决方案:

public <T extends PersonalItem> T getPersonalItem(String name){
 return (T) map.get(name);
 }

这确实只涵盖问题的代码重复部分,并且遭受同样的危险。但是,如果你需要编码:

House house = (House)person.getPersonalItem("house");

更清楚的是,你必须确定&#34; house&#34; key实际上存在于地图中。