1

Here is a json which comes in the request param. I am constructing a class with getter and setter for accessing the values in json so that I could be able to pass the class object to different methods and able to access the member variables in them.

public class RequestParams {
    private String student_id;
    private String student_name;
    private String student_role_number;
    private String department_name;
    private String stream;

    private JSONObject studentDetails;

    public RequestParams(HttpServletRequest request) {
        this.studentDetails = request.getParameter(“studentdetails”);
    }

    public String getStudentId() {
        if(this.student_id == null) {
            this.setStudentId();
        }
        return this.student_id;
    }
    public String getStudentName() {
        if(this.student_name == null) {
            this.setStudentName();
        }
        return this.student_name;
    }
    public String getRoleNumber() {
        if(this.student_role_number == null) {
            this.setRoleNumber();
        }
        return this.student_role_number;
    }
    public String getDepartmentName() {
        if(this.department_name == null) {
            this.setDepartmentName();
        }
        return this.student_name;
    }
    public String getStream() {
        if(this.stream == null) {
            this.setStream();
        }
        return this.stream;
    }
    public void setStudentId() {
        this.student_id = this.studentDetails.getString("student_id");
    }
    public void setStudentName() {
        this.student_name = this.studentDetails.getString("student_name");
    }
    public void setRoleNumber() {
        this.student_role_number = this.studentDetails.getString("role_number");
    }
    public void setDepartmentName() {
        this.department_name = this.studentDetails.getString("department_name");
    }
    public void setStream() {
        this.stream = this.studentDetails.getString("stream");
    }
}

Have the following doubts,

  1. Constructing as class object to reference it from different methods - Is this a good one? Am I going wrong?
  2. How to organise my getter setter so that only set is called only for the first time and for the next calls the value is returned directly? Is there a better way to avoid the null check each time

if(this.student_id == null) {

this.setStudentId();

}

  1. Is there any advantage of accessing the methods and variables within the class with this. ?

PS: I could not invoke all the setter initially from the constructor because all the values declared in the class need not be necessarily present in the json. So, I thought that it would be better if I could initialise the member variable with value during first access.

  • I have found your design a little bit convoluted. Why can't you initialize to null those params that are not present in the json object? If they were not during the construction phase, they won't be either during the "setter" call. At the end , in both cases the values will be null. – Laiv Mar 18 '17 at 11:27
  • 1
    @Rajasuba Your question #3 (about this.) is already answered by stackoverflow.com/questions/2411270/… - basically there are some cases when it is required, but other than those, it is mostly a matter of style/preferences and consistency. – Eugene Podskal Mar 18 '17 at 11:30
6

Your member variables are redundant. You should either store the JSONObject or the Strings but not both of them. This will avoid consistency issues.

Here is a suggestion:

public class RequestParams {
    private final String student_id;
    private final String student_name;
    private final String student_role_number;
    private final String department_name;
    private final String stream;

    public RequestParams(HttpServletRequest request) {
        JSONObject studentDetails = request.getParameter(“studentdetails”);
        this.student_id = studentDetails.getString("student_id");
        this.student_name = studentDetails.getString("student_name");
        this.student_role_number = studentDetails.getString("role_number");
        this.department_name = studentDetails.getString("department_name");
        this.stream = studentDetails.getString("stream");
    }

    public String getStudentId() {
        return this.student_id;
    }
    public String getStudentName() {
        return this.student_name;
    }
    public String getRoleNumber() {
        return this.student_role_number;
    }
    public String getDepartmentName() {
       return this.student_name;
    }
    public String getStream() {
        return this.stream;
    }
}

Note that the member variables can be made final and the class is immutable now.

  • Thank you for your suggestions.. I would like to add - In my case the json may not contains all the field all the time.. So initializing the class variables with json.getString - for the filed that is not there seems to be an overhead.. So, I have opted for lazy initialization method.. – rm -rf star Mar 19 '17 at 5:41
  • Please suggest me a better approach to handle this.. – rm -rf star Mar 19 '17 at 5:41
  • 1
    @RajasubaSubramanian: Holding the JSONObject for the whole lifetime of the object has probably more overhead than storing the strings. The JSONObject somehow has to store the complete information from the JSON file, including the attribute names. – Frank Puffer Mar 19 '17 at 10:38
  • ` Holding the JSONObject for the whole lifetime of the object has probably more overhead than storing the strings.` you are right. But I would like to know how it could cause overhead? – rm -rf star Mar 19 '17 at 11:12
  • @RajasubaSubramanian: I was refering to memory usage. The JSONObject is probably implemented as a map of key value pairs. So each entry has two strings. Even if some entries are missing, it probably takes up more memory than the solution I suggested. – Frank Puffer Mar 19 '17 at 11:25
2

Such initialization approach is called Lazy initialization

lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed.

Some languages/platforms provide a standard way to express such a construct (like C#'s Lazy<T> class), while in others you have to implement it yourself/find some third party library solution.

As far as I can see there is no standard implementation of this pattern in Java, so you can either make a simple custom one, or use one from popular third-party libraries.

Assuming that the chosen lazy implementation is called Lazy<T> your class would look like:

public class RequestParams {
    private Lazy<String> student_id;

    private JSONObject studentDetails;

    public RequestParams(HttpServletRequest request) {
        this.studentDetails = request.getParameter(“studentdetails”);
        this.studentId = new Lazy<String>(() -> this.createStudentId());
    }

    public String getStudentId() {
        return this.student_id.value();
    }

    public String createStudentId() {
        return this.studentDetails.getString("student_id");
    }
}

P.S.: Do not forget that primitive custom Lazy<T> implementation(like the one behind this link) is not thread-safe, that may or may not be acceptable.

P.S.1: Also, I am not exactly sure that it is such a good idea to use HttpServletRequest as a constructor parameter - it couples RequestParams with http-related classes, that may slightly complicate maintenance and unit-testing, and reduce the possibility of class reuse.

P.S.2: While Lazy<T> approach is a proper generic solution, in this particular case, where initialization is actually relatively cheap, I'd rather follow the @Frank Puffer's suggestion and fully initialize this class in the constructor, thus making it immutable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.