反射:抛出java.lang.NullPointerException

时间:2014-04-25 13:52:22

标签: java reflection

1.for (Field field : fields) {
2.    if (p.contains(field.getName())) {
3.        if(field.getType().toString().split("[.]")[2].equals("String"))
4.            callableStatement.setString(field.getName(), field.get(obj).toString());
5.        else if(field.getType().toString().split("[.]")[2].equals("Integer"))
6.            callableStatement.setInt(field.getName(), (int)field.get(obj));
7.        System.out.println(field.get(obj).toString());
8.    }
9.}

这是我的代码。使用反射我从类对象中获取数据,在上面的循环中,我设置了过程输入的参数。但是,它会保存一些整数值,并在第7行的某些位置抛出java.lang.NullPointerException

接受这些值:

this.DI_StDate = Common.getDateStamp(date); // Integer
this.DI_StTime = Common.getTimeStamp(date); // Integer

来自Common.java

public static Integer getDateStamp(Date d) {
    return Integer.parseInt(requiredDate.format(d));
}

public static Integer getTimeStamp(Date d) {
    return Integer.parseInt(requiredTime.format(d));
}

抛出异常:

this.FileOpsId = new Integer(1);            // Integer
this.FileTypeOpsId = 1;                     // Integer

请建议我出错的地方。

这些是我的班级成员:

public class DIConnect {
    public Integer PROC_ID;
    public String APIKey;
    public String Username;
    public String pwd;
    public String StreamKey;

    public Integer DI_StDate;
    public Integer DI_StTime;

    public String FileNamePath;
    public Integer FileOpsTypeId;
    public String ConfigLabel;
    public Integer FileOpsId;

    public Integer End_Date;
    public Integer End_Time;

    public DIConnect(String FileNamePath, String ConfigLabel, Integer FileOpsTypeId, Integer StartDate, Integer StartTime) {
        this.FileNamePath = FileNamePath;
        this.ConfigLabel = ConfigLabel;
        this.FileOpsTypeId = FileOpsTypeId;
        this.DI_StDate = StartDate; // accepted
        this.DI_StTime = StartTime; // accepted
        this.FileOpsId = new Integer(1); // NOT ACCEPTED
    }
}

这是main()方法中的调用。

DIConnect DIC = new DIConnect(filePath, "File", 1, Common.getDateStamp(date), Common.getTimeStamp(date));
DIC.InsertFileOperation();

DIConnect.java:

public Integer InsertFileOperation() {
        String[] params = {"FileNamePath", "FileOpsId", "ConfigLabel", "DI_StDate", "DI_StTime"};
        DatabaseOperation db = new DatabaseOperation();
        if(db.openConnection()) {
            this.PROC_ID = db.executeProcedure("sp_InsertIntoFileOpsMaster", params, this);
            db.closeConnection();
        }
        return this.PROC_ID;
    }

Database.java

public Integer executeProcedure(String proc, String[] params, Object obj) {
        int Id = 0;
        try {
            String paramString = StringUtils.repeat("?, ", params.length + 1).trim();
            paramString = paramString.substring(0, paramString.length() - 1);
            proc = "{CALL " + proc + "(" + paramString + ")}";
            callableStatement = conn.prepareCall(proc);

            Class cls = obj.getClass();
            Field[] fields = cls.getFields();
            List<String> p = Arrays.asList(params);

            for (Field field : fields) {
                if (p.contains(field.getName())) {
                    if(field.getType().toString().split("[.]")[2].equals("String"))
                        callableStatement.setString(field.getName(), field.get(obj).toString());
                    else if(field.getType().toString().split("[.]")[2].equals("Integer"))
                        callableStatement.setInt(field.getName(), (int)field.get(obj));
                    System.out.println(field);                        
//                    System.out.println(field.get(obj).toString());
                }
            }
            callableStatement.registerOutParameter("Id",java.sql.Types.INTEGER);
            callableStatement.executeUpdate();
            Id = callableStatement.getInt("Id");

        } catch (SQLException | IllegalArgumentException | IllegalAccessException ex) {
            Logger.getLogger(DatabaseOperation.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex){
          System.out.println(ex.getMessage());
        } finally {
            return Id;
        }
    }

输出

public java.lang.Integer airteldemo.DIConnect.DI_StDate
public java.lang.Integer airteldemo.DIConnect.DI_StTime
public java.lang.String airteldemo.DIConnect.FileNamePath
public java.lang.String airteldemo.DIConnect.ConfigLabel
null

3 个答案:

答案 0 :(得分:1)

正如我猜测field.get(obj)(有时)返回null所以你应该检查它是null还是以某种方式(取决于代码的逻辑)不允许它成为null {{1}}。

我将此作为答案原因发布,鉴于您提供的信息我们可以告诉您问题出在哪里,而不是导致问题的原因。

答案 1 :(得分:1)

您的代码存在一些问题。


首先,字段在java中可以具有空值。如果您正在使用Object类型的参数,则只需接受此参数并将null值映射到SQL值,这可能基于有关数据库列类型的推理。

使用field.get(obj).toString()

,而不是使用不null字段值的String.valueOf(field.get(obj))

第二

else if(field.getType().toString().split("[.]")[2].equals("Integer"))

因为假定java.lang.Integer因为ClassCastException而失败而被破坏,因为(Integer) null与任何int值不对应而不是空的,并且它可能会失败IndexOutOfBoundsException 1}}当field.getType()类似于shortpackage.Integer时。

取而代之的是

Integer.class.equals(field.getType()) || Integer.TYPE.equals(field.getType())

Integer.TYPEint基元类型的伪类。


第三,您似乎在编写自己的数据库抽象层。那里有大量的ORB可以为你做这件事。我鼓励你改用其中一个。

答案 2 :(得分:0)

我发现了这个错误。 callablestatement获取被调用过程的签名。参数应作为区分大小写的参数传递。我的程序正在接收FileOpsTypeID,我正在通过FileOpsTypeId。改变案例使其有效。

抱歉延迟回复。对不起,我没有提供完整的细节(程序)。