Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 强制调用所有方法_Java - Fatal编程技术网

Java 强制调用所有方法

Java 强制调用所有方法,java,Java,我经常使用对象来存储从数据库中获取的实体的属性。我在对象中使用私有变量,然后使用getter和setter来设置值。因此,为了初始化对象,我调用对象的所有setter。但是不可能跟踪所有的设置者,我经常忘记设置一些变量。有没有一种方法可以强制设定设定者的呼叫。我当然可以使用构造函数来初始化变量,但是使用构造函数来设置10-12个属性会使代码看起来很糟糕。我希望以这样一种方式使用接口和子类,即它们的工作方式与实现接口的所有方法所必需的方式相同,但这里不是实现而是调用它们 com.mysql.jdb

我经常使用对象来存储从数据库中获取的实体的属性。我在对象中使用私有变量,然后使用getter和setter来设置值。因此,为了初始化对象,我调用对象的所有setter。但是不可能跟踪所有的设置者,我经常忘记设置一些变量。有没有一种方法可以强制设定设定者的呼叫。我当然可以使用构造函数来初始化变量,但是使用构造函数来设置10-12个属性会使代码看起来很糟糕。我希望以这样一种方式使用接口和子类,即它们的工作方式与实现接口的所有方法所必需的方式相同,但这里不是实现而是调用它们

com.mysql.jdbc.PreparedStatement getInternships = (PreparedStatement) Connection.con.prepareCall("CALL getInternships()");

        rs=getInternships.executeQuery();
        Internship current;
        while(rs.next()){
            current=new Internship();
            current.setId(Integer.parseInt(rs.getString("id")));
            current.setTitle(rs.getString("title"));

            current.setCategory(rs.getString("category"));
            current.setOpening(rs.getDate("opening"));
            current.setClosing(rs.getDate("closing"));
            current.setDuration(Integer.parseInt(rs.getString("duration")));
            current.setStatus(rs.getString("status"));
            current.setApplicants(Integer.parseInt(rs.getString("applicants")));
            current.setSeats(Integer.parseInt(rs.getString("seats")));
            current.setHired(Integer.parseInt(rs.getString("hired")));
            list.add(current);
        }
实习班

package internships;
import java.util.Date;
public class Internship {
private String title,category,status,about,eligibility,information;
private int id,duration,applicants,seats,hired;
private Date opening,closing;
/**
 * @return the opening
 */
public Date getOpening() {
    return opening;
}
/**
 * @param opening the opening to set
 */
public void setOpening(Date opening) {
    this.opening = opening;
}
/**
 * @return the hired
 */
public int getHired() {
    return hired;
}
/**
 * @param hired the hired to set
 */
public void setHired(int hired) {
    this.hired = hired;
}
/**
 * @return the seats
 */
public int getSeats() {
    return seats;
}
/**
 * @param seats the seats to set
 */
public void setSeats(int seats) {
    this.seats = seats;
}
/**
 * @return the applicants
 */
public int getApplicants() {
    return applicants;
}
/**
 * @param applicants the applicants to set
 */
public void setApplicants(int applicants) {
    this.applicants = applicants;
}
/**
 * @return the closing
 */
public Date getClosing() {
    return closing;
}
/**
 * @param closing the closing to set
 */
public void setClosing(Date closing) {
    this.closing = closing;
}
/**
 * @return the duration
 */
public int getDuration() {
    return duration;
}
/**
 * @param duration the duration to set
 */
public void setDuration(int duration) {
    this.duration = duration;
}
/**
 * @return the category
 */
public String getCategory() {
    return category;
}
/**
 * @param category the category to set
 */
public void setCategory(String category) {
    this.category = category;
}
/**
 * @return the status
 */
public String getStatus() {
    return status;
}
/**
 * @param status the status to set
 */
public void setStatus(String status) {
    this.status = status;
}
/**
 * @return the title
 */
public String getTitle() {
    return title;
}
/**
 * @param title the title to set
 */
public void setTitle(String title) {
    this.title = title;
}
/**
 * @return the id
 */
public int getId() {
    return id;
}
/**
 * @param id the id to set
 */
public void setId(int id) {
    this.id = id;
}
/**
 * @return the about
 */
public String getAbout() {
    return about;
}
/**
 * @param about the about to set
 */
public void setAbout(String about) {
    this.about = about;
}
/**
 * @return the eligibility
 */
public String getEligibility() {
    return eligibility;
}
/**
 * @param eligibility the eligibility to set
 */
public void setEligibility(String eligibility) {
    this.eligibility = eligibility;
}
/**
 * @return the information
 */
public String getInformation() {
    return information;
}
/**
 * @param information the information to set
 */
public void setInformation(String information) {
    this.information = information;
}

}
这里有一个建议:

  • 定义一个包含所有字段(类别、开始、结束、持续时间等)的“数据”类,例如,
    InternishipData
  • 实习
    类中,定义一个setter方法:
    setData(实习数据)
    。无论何时需要配置
    实习
    ,都可以使用此设置器
  • 在setter内部,检查所提供的
    internishipData
    对象的所有字段是否已正确初始化。如果不是,您可以抛出异常,或者从setter返回
    false
    ,并从外部检查返回的值
(注意,如果您想将数据传递给
实习生
构造函数,可以使用类似的方法)


这使您可以在单个位置检查所有字段(使用
setData
)方法,这对于您当前的方法来说是很难做到的,因为您有一堆setter,您不知道从客户端代码调用它们的顺序。

这是另一个运行时想法——我能想到的唯一编译时答案是引入新的PMD/FindBugs规则,并让IDE在每次保存时运行这些

对于要避免“未初始化”值的每个类,您需要声明一个
位集
,以跟踪已设置的字段,以及一个名为
字段
枚举
,该枚举将为您计算字段并将字段名与其对应的
位集
索引相关联

// keeps track of initialized fields
private BitSet initialized = new BitSet(Fields.values().length);

// field-names not included here will not be considered included in BitSet
enum Fields {
   title,category,status,about,eligibility,information,
   id,duration,applicants,seats,hired,
   opening,closingopening
}
只有在
字段
中的所有字段至少设置一次时,才会返回true:

public void isFullyInitialized() {
   return initialized.cardinality() == initialized.size();
}
这将是一个样本设定者:

/**
 * @param opening the opening to set
 */
public void setOpening(Date opening) {
   this.opening = opening;
   initialized.set(Fields.opening.ordinal()); // <- do this in all setters
}
/**
*@param打开要设置的开口
*/
公开开标(开标日期){
这个。打开=打开;

initialized.set(Fields.opening.ordinal());//这个简单的反射有趣吗

我们将使用实习类的一个较轻的变体。用@NotNull标记最后不应为null的字段。是的,这不适用于基元字段,但除非构造函数强制,否则您的字段可以具有未定义的状态,该状态由值null表示。使用基元将隐藏该事实

class Internship {
    @NotNull
    private String name;

    private String status;

    public Internship() {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}
下面是对注释及其处理器的完整测试,该处理器是一个名为validateNotNullFields的漂亮方法。它获取对象的每个字段,甚至是私有字段和在超类中定义的字段。如果在一个值为null的字段上发现注释,则抛出一个IllegalArgumentException。如果您喜欢我的解决方案,您可能会布莱希望对此进行调整,并正确输出字段名称,甚至毫无例外地选择解决方案

public class Test {
    public static void main(String... args) {
        Internship a = new Internship();
        a.setName("Karl");
        a.setStatus(null);
        validateNotNullFields(a);

        System.out.println("ok");

        try {
            Internship b = new Internship();
            b.setName(null);
            b.setStatus(null);
            validateNotNullFields(b); // throws IllegalStateException!
            System.out.println("not ok");
        } catch (IllegalStateException ise) {
            System.out.println("ok");
        }

    }

    static void validateNotNullFields(Object candidate) throws IllegalStateException {
        if (candidate == null) {
            throw new IllegalArgumentException("argument candidate must not be null!");
        }
        Class<?> clazz = candidate.getClass();

        while (!Object.class.equals(clazz)) {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                Annotation annotation = field.getAnnotation(NotNull.class);
                if (annotation == null) {
                    continue;
                }

                field.setAccessible(true);

                try {
                    if (field.get(candidate) == null) {
                        throw new IllegalStateException(
                                "Field " + field.getName() + " must not be null at this point!");
                    }
                } catch (IllegalArgumentException | IllegalAccessException ex) {
                    throw new RuntimeException(ex);
                }
            }
            clazz = clazz.getSuperclass();
        }
    }
}
公共类测试{
公共静态void main(字符串…参数){
实习a=新实习();
a、 设置名称(“卡尔”);
a、 设置状态(空);
validateNotNullFields(a);
System.out.println(“ok”);
试一试{
实习b=新实习();
b、 集合名(空);
b、 设置状态(空);
validateNotNullFields(b);//抛出非法状态异常!
System.out.println(“不正常”);
}捕获(非法状态){
System.out.println(“ok”);
}
}
静态void validateNotNullFields(对象候选)引发IllegalStateException{
if(候选者==null){
抛出新的IllegalArgumentException(“参数候选者不能为null!”);
}
Class clazz=candidate.getClass();
而(!Object.class.equals(clazz)){
Field[]fields=clazz.getDeclaredFields();
用于(字段:字段){
Annotation=field.getAnnotation(NotNull.class);
if(注释==null){
继续;
}
字段。setAccessible(true);
试一试{
if(field.get(candidate)==null){
抛出新的非法状态异常(
“Field”+Field.getName()+“此时不能为空!”;
}
}捕获(IllegalArgumentException | IllegalAccessException ex){
抛出新的运行时异常(ex);
}
}
clazz=clazz.getSuperclass();
}
}
}

您可以使用一种方法,在每次调用时为您读取所有字段,而不是事后检查是否已设置了每个字段。不再有内存丢失:

static void load(Object target, ResultSet rs) throws Exception {
    Class<?> clazz = target.getClass();

    ResultSetMetaData rsmd = rs.getMetaData();
    for (int i=0; i<rsmd.getColumnCount(); i++) {
        Field field = clazz.getDeclaredField(rsmd.getColumnName(i+1));
        field.setAccessible(true);
        int type = rsmd.getColumnType(i+1);
        switch (type) {
            case Types.DATE: {
                field.set(target, rs.getDate(i+1));
            }
            case Types.VARCHAR: {
                field.set(target, rs.getString(i+1));
            }
            case Types.BIGINT: {
                field.set(target, rs.getInt(i+1));
            }
            default: {
                throw new IllegalArgumentException(
                   "Unhandled field type: " + type);
            }
        }
    }
}
静态无效加载(对象目标、结果集rs)引发异常{
Class clazz=target.getClass();
ResultSetMetaData rsmd=rs.getMetaData();

对于(int i=0;i可能重复签出,虽然它可以强制调用所有方法,但我不确定它是否真的可以使您的代码更干净……这篇文章对我帮助不大,因为对我来说,我不打算使用默认值,而是希望在实例化objectI时必须使用所有setterg调用setter——只需迭代ResultSet的列并自动调用setter。请参见下面的答案。因为调用所有这些setter都是错误的