关于子类创建

时间:2017-12-29 14:41:23

标签: java

在子类完全初始化之后,有没有办法如何自动从子类向超类发送通知 i。即完成子类构造函数后?

动机

基类必须提供一些使用类字段列表的默认方法。由于子类字段仅在创建子类后才能在父类中访问,因此基类无法在基类构造函数中读取这些子类字段。一种解决方案是在每个需要处理这些字段的基本方法的开头读取子类字段。由于反射慢,最好使用延迟初始化。

我很好奇Java中是否有一些不广为人知的回调机制允许定义一些“子类创建的回调”,所以我可以在不使用懒惰的情况下初始化这些字段 - 初始化以实现更好的可维护性

我知道可以跟踪对象的重新分配e。 G。通过finalize()ReferenceQueue,所以我想知道如果对象创建有类似的东西。

示例

假设您要创建一个数据库Entity类(我知道有基于ORM的解决方案,但这仅用于说明类似问题),它们将能够生成SQL语句,如CREATE TABLE,INSERT ,UPDATE,DELETE基于实体的类字段。因此,基类将负责读取类字段以及生成这些语句。要创建实体,只需要扩展Entity并使用一些字段注释,例如@Column@Id@AutoIncrement,...

class Entity {
    public String getCreateTableStatement() {
        // lazy-initialize list of class fields and produce statement...
    }

    public String getInsertPreparedStatement() {
        // lazy-initialize list of class fields and produce statement...
    }

    // update, delete, ...
}

子类的示例

public Person extends Entity {
    @Id public int id;
    @Column public String name;
}

AIM

替换延迟初始化是另一种有助于减少重复代码量的模式。理想情况下,子类不必定义任何其他内容,只需要“extends Entity”。

2 个答案:

答案 0 :(得分:2)

有点不清楚你要做什么,但总的来说,许多与对象创建有关的问题都可以通过使用封装创建过程的factory method来解决。这样,您可以在单个构造函数调用中实现更多功能:

public static MySubClass createSubClass() {
    MySubClass subClass = new MySubClass();
    subClass.baseClassMethodThatManipulatesFields();
    return subClass;
}

请注意(正如其他人指出的那样),继承可能不是解决您问题的最佳方法。您在Entity中列出的方法应该由使用反射来初始化类的工厂负责。

答案 1 :(得分:0)

我不是在问为什么。如果你想完全像你回答一样,那么父对象可以通过构造函数完全访问它的子对象。是的,我知道此时子对象尚未完全初始化,但此步骤中提供了注释信息。

这是一个例子:

import org.apache.commons.lang3.reflect.MethodUtils;

import javax.persistence.Id;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.util.ArrayList;
import java.util.List;

    public class Entity {
        protected Entity() {
            List<AccessibleObject> ids = getAccessibleObjectWithAnnotation(Id.class);
            List<AccessibleObject> columns = getAccessibleObjectWithAnnotation(Column.class);
        }

        private List<AccessibleObject> getAccessibleObjectWithAnnotation(Class<? extends Annotation> cls) {
            List<AccessibleObject> res = new ArrayList<>();
            res.addAll(FieldUtils.getFieldsListWithAnnotation(getClass(), cls));
            res.addAll(MethodUtils.getMethodsListWithAnnotation(getClass(), cls));
            return res;
        }
    }