Java constructor bypass setter validation - java

When learning Java constructor and mutator, I found out that setter can be used to perform validation. But if we directly use constructor to create a new instance, wouldn't it bypass the validation in setter? Below is the sample code:
public static void main(String[] args){
Person p1 = new Person("My Name", "My Gender"); //bypass setter validation
p1.setGender("Female"); //validation is performed
}
public class Person{
public Person(String name, String gender){
this.name = name;
this.gender = gender;
}
public void setGender(String gender){
if(gender.equals("Male") || gender.equals("Female")){
this.gender = gender;
}
else{
this.gender = "undefined";
}
}
}
I have seen some mentioned that you can call the setter in the constructor, but seems like it is not a good approach as a lot of forums mentioned that it will cause some "overridden" issue. If that's the case, is there anything I can do to make sure that the setter validation can be performed when I'm calling my constructor?
Thanks in advance!

Calling the setter in the constructor should only be done if either the class or the setter is final. Otherwise a sub class may override it, and do other things that attempt to use fields that haven't been initialized yet.
One easy fix is to make the field final. You then only have to validate it in the constructor, because there is no need for a setter. Another possibility is to duplicate the validation. But then you're duplicating code, and your first instinct should be to refactor it into a utility method.
Which can lead to something like this (and I'm swapping the operands to the equals calls to be null-safe):
public class Person {
public Person(String name, String gender) {
this.name = name;
setValidGender(gender);
}
public void setGender(String gender) {
setValidGender(gender);
}
private void setValidGender(String gender) {
if ("Male".equals(gender) || "Female".equals(gender)) {
this.gender = gender;
} else {
this.gender = "undefined";
}
}
}

public boolean validateGender(String p_gender){
if(p_gender.equals("Male") || p_gender.equals("Female")){
return true;
}
else{
return false;
}
So, how about something like the above?
Then, use that in both setGender(String gender) and the constructor that you're looking to perform the validation in?
public Person(String name, String gender){
this.name = name;
if(validateGender(gender)){
this.gender = gender;
}
else{
this.gender = "undefined";
}
}

Use the builder pattern and do the validation as a part of the builder.
So here's the deal. Performing field validation while the object is being instantiated is dangerous because you want to avoid two things:
Invalid data is in a "valid" object (do not assume a default gender)
Object is half-instantiated (if you throw an exception during object construction, weird things happen
So instead, use a separate object that builds it out for you, and does the validation in place.
public PersonBuilder {
public Person person = new Person(); // blank person object
public static PersonBuilder getInstance() {
return new PersonBuilder();
}
public PersonBuilder withName(final String name) {
// do your validation here, and if it fails, you can blow up
person.setName(name);
return this;
}
public PersonBuilder withGender(final String gender) {
// do your validation here, and if it fails, you can blow up
person.setGender(gender);
return this;
}
public Person build() {
return person;
}
}
// Usage
Person person = PersonBuilder.getInstance().withName("Tom").withGender("Male").build();

Related

#NotNull implication on Getter and Setter of a Parameter

Believing and using Which #NotNull Java annotation should I use?, I have a class which has certain fields marked as #NotNull [package javax.validation.constraints] to pass on to the clients. The class also implement the default getter and setter for such fields. Sample class below -
public class MyClass
{
public MyClass() {
}
#NotNull
private String name;
private Boolean bool;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean isBool() {
return bool;
}
public void setBool(Boolean bool) {
this.bool = bool;
}
}
I am left a little puzzled up with the usage of the getter as follows in the business logic -
if(new MyClass().getName() !=null) {
//do something
}
Is this null check not redundant, (if not) curious to know WHY?
Also if its redundant, would like to give a thought of setting a null value and getting the value of the param. Gave this a try as -
void test() {
myClass.setName(null);
if (myClass.getName() == null) {
System.out.println("It should not be null"); // this got printed
}
}
#NonNull is only a hint for your tooling, it does not affect how the java language itself handles nulls. It also requires every interaction to be properly annotated to ensure all mistakes are found.
This happens in your case, while the name field is annotated the methods interacting with that field are not, so the tooling cannot make any assumptions about those methods and their nullability.
However if you introduce more annotations like this:
public void setName(#Nullable String name) {
this.name = name; // should now have a warning
}
#NonNull
public String getName() {
return name;
}
Now the tooling should indicate new MyClass().getName() != null as always true. It also warns in setName that you're setting a nullable value to a non-null property and that is probably wrong.
The way that is fixed:
public void setName(#NonNull String name) {
// setName(null) would cause a warning
// Also add an exception if the annotation is ignored.
this.name = Objects.requireNonNull(name);
}
/* or */
public void setName(#Nullable String name) {
if (name == null) return; // Guard against setting null
this.name = name;
}

Should getters have validation in java? [duplicate]

This question already has answers here:
Can I write validation logic in setter methods?
(7 answers)
Closed 7 years ago.
Should getters have validation in java(for example. checking if something is null)? or should they simply get whatever it is suppose to get with one return statement. To me this is how i usually do it.
public class GetterDemo
{
private String name;
private int age;
public GetterDemo(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return this.name;
}
public int getAge()
{
return this.age;
}
}
Now suppose that the constructor has an array of hobbies from a class called hobbies.
public class Hobbies
{
private String hobby;
private String category;
public Hobbies(String hobby, String category)
{
this.hobby = hobby;
this.category = category;
}
public String getHobby()
{
return this.hobby;
}
public String getCategory()
{
return this.category;
}
}
Now, lets update version of GetterDemo with an array of hobbies in the constructor as i said above. and it has a next method to get the next hobby in the array everytime its called.
public class GetterDemo
{
private String name;
private int age;
private int count = 0;
private Hobbies[] hobbies;
public GetterDemo(String name, int age, Hobbies[] hobbies)
{
this.name = name;
this.age = age;
this.hobbies = hobbies
}
public Hobbies getNextHobby()
{
//Create a counter.
Hobbies result;
if (this.hobbies == null || this.hobbies.length == 0
|| this.count >= this.hobbies.length) //Called more then length times.
return null;
result = this.hobbies[count];
count++;
return result;
}
public String getName()
{
return this.name;
}
public int getAge()
{
return this.age;
}
public void reset()
{
this.count = 0;
}
}
Okay so thats a little code example. There might be errors, probably many as I blankly coded it.
To explain in terms of testing for null(JUnit testing). If I call getNextHobby() hobby length times or more it will return null and I can AssertNull() and it will pass. However, for example, if I do AssertNull where the array of hobbies is Null and I try getNextHobby.getCategory(), it will throw a NullPointerException even though I want it to be null. Would the only way to fix this would be to create a method that checks for this? or a getter that checks for null somehow? Possibly the code below?
public boolean checkNull()
{
boolean result = false;
if (getNextHobby().getCategory() == null || getNextHobby().getHobby())
result = true;
return result;
}
I assume that it is a matter of taste.
I prefer that setters and getters do only what they suppose to do which means set some value or get some value. My reasons are the following:
The signature of the method should explain what this method is doing and as we know good method should do one thing well. Thus when you start adding some validation I would assume that you need to change the signature otherwise the caller might assume that only set/get operation happens.
Every IDE has an opportunity to generate getters and setters and for some reason they don't generate some validations for the parameters of the getter method thus I assume that you shouldn't do it as well.
I try to separate getters and setters from other methods, thus if I need to kind of get the value, however, it is not exactly a getter because you need to do some other actions, I prefer to use other words like fetch, retrieve, obtain. In this case it will be very clear that you don't need to test getters and setters because they don't really do anything, however, fetch and others you must.

How to use encapsulation?

After I read online E-book.They said the benefit of encapsulation is "A class can change the data type of a field and users of the class do not need to change any of their code.". I don't understand what they say in the point. What is the main meaning of the point? Can you give an example,please?
Let's take a simple class Vehicles, which maintains a list:
public class Vehicles {
private ArrayList<String> vehicleNames;
Vehicles() {
vehicleNames = new ArrayList<String>();
}
public void add(String vehicleName) {
vehicleNames.add(vehicleName);
}
}
This will be used by a client in the following way:
public class Client {
Public static void main(String []args) {
Vehicles vehicles = new Vehicles();
vehicles.add("Toyota");
vehicles.add("Mazda");
}
}
Now if Vehicles changes its internal private vehicleNames field to be a LinkedList instead, Client would be unaffected. That is what the book is talking about, that the user/client does not need to make any changes to account for the changes in the class due to encapsulation.
Encapsulation is really important in Object-Oriented Programming. Using encapsulation, you can hide information from users who use your class library/API.
"And why do I need to hide stuff from the users?", you ask. There are a lot of reason. One main reason is that some users who are naughty or just don't know what the API is doing may mess with your classes and stuff. Let me give you an example.
Suppose you have a class here:
public class Computer {
public int coreCount;
}
As you can see here, coreCount is declared public. That means all other classes can access it. Now imagine a naughty person do this:
Computer myPC = new Computer ();
myPC.coreCount = 0;
Even fools can tell that this doesn't make any sense. It might also affect your program's other stuff. Imagine you want to divide by the core count. An Exception would occur. So to prevent this, we should create setters and getters and mark the field private.
C# Version:
public class Computer {
private int coreCount;
public int CoreCount {
get {return coreCount;}
set {
if (value > 0)
coreCount = value;
}
}
}
Java version
public class Computer {
private int coreCount;
public int getCoreCount () {return coreCount;}
public void setCoreCount (int value) {
if (value > 0)
coreCount = value;
}
Now no one can set the core count to non-positive values!
Here's an example of encapsulation. Say we have a Person class, like so
class Person {
private String name;
private String email;
public String getName() { return this.name; }
public String getEmail() { return this.email; }
public void setName(String name) { this.name = name; }
public void setEmail(String email) { this.email = email; }
}
And at some point, we decide we need to store these values not as a couple strings, but as a HashMap (for some reason or another).
We can change our internal representation without modifying the public interface of our Person class like so
class Person {
HashMap<String, String> data;
public Person() {
this.data= new HashMap<String, String>();
}
public String getName() { return this.data.get("name"); }
public String getEmail() { return this.data.get("email"); }
public void setName(String name) { this.data.put("name", name); }
public void setEmail(String email) { this.data.put("email", email); }
}
And from the client code perspective, we can still get and set Strings name and email without worrying about anything else.

Using setter methods or direct reference to variable inside constructor?

Both methods work, however which is the proper way to do it?
Method one:
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object(String name){
this.name = name;
}
}
Method two:
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//Changed this.name = name to setName(name)
public Object(String name){
setName(name);
}
}
I've searched around but couldn't find an exact question that referred to this. If there is one, free to post the link and I'll remove the question
My first thought was to use the setter in the constructor. So if you want to change how the name is stored, or if you want to add any other behavior while setting the name, you just have to change it once.
But thinking just a bit more on this, I think using direct access to the variable is better if the class is not final and the method is not private. Otherwise someone could extend your, override the method, causing your constructor to call their method with unpredictable behavior.
Rule of thumb: If the class is not final, you should only call private methods in the constructor.
While using a setter in the constructor reduces code duplication, calling overrideable methods (ie non final / non private methods) in a constructor is discouraged - it can lead to weird bugs when extending a class.
Consider the following case (based off of your example):
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//Changed this.name = name to setName(name)
public Object(String name){
setName(name);
}
}
With the following subclass:
public class SubObject extends Object {
private String Id;
#Override
public void setName(String name) {
super.setName(name + Id);
}
public SubObject(String name){
super(name);
this.id = "1";
}
}
Creating an instance of SubObject will cause a null pointer, as setName() is called in the constructor, but the implementation of setName() relies on the Id field having been initialized.
Someone extending a class should not have to go check the source code of the super class to ensure the constructor isn't calling overrideable methods.
If all the setter and constructor do is a simple assignment, it doesn't matter which of the two ways you choose.
However, if you need to perform some validations before assigning the new value to the member, it makes sense to have that logic in a single place, which means calling the setter method from the constructor is the better option.
I would NOT use the setter in the constructor. This because if someone added any other behavior while setting the name in the setter, I'd consider it a collateral effect.
If setName() coontains some inner logic about how the name should be set, then I would choose 2. On the other hand, if setName() contains some aditional code that needs to be run when name is set, i would choose 1.
Let me make a bit more complex situation so I can express my point:
class Person {
private String firstName;
private String lastName;
private boolean wasRenamed;
//getters...
public Person(String fullName) {
???
}
public void setFullName(String fullName) {
???
}
}
Here we have Persons with first and last names, also we want to keep record who was renamed and who not. Let's say fullName contains first and last name separated by space. Now let's look at 2 different approaches you provided in your question:
Not call setFullName() in costructor: This will lead to code duplicity (spliting fullName by space and assigning it to first and last name.
Do call setFullName() in costructor: This will add extra trouble with the wasRenamed flag, since setFullName() has to set this flag. (This could be solved by simply resetting the flag back to false in constructor after calling setFullName(), but let's say we don't want to do that)
So I would go with a combination of 1 and 2, and split the inner logic of setting the name and the additional code that needs to run before/after name is set into different methods:
class Person {
private String firstName;
private String lastName;
private boolean wasRenamed;
//getters...
private void setFullName0(String fullName) {
//split by space and set fields, don't touch wasRenamed flag
}
public Person(String fullName) {
setFullName0(fullName);
}
public void setFullName(String fullName) {
setFullName0(fullName);
wasRenamed = true;
}
}

How to create a POJO?

Recently I've started hearing about "POJOs" (Plain Old Java Objects). I googled it, but still don't understand the concept well. Can anyone give me a clear description of a POJO?
Consider a class "Person" with variables "id, name, address, salary" -- how would I create a POJO for this scenario? Is the code below a POJO?
public class Person {
//variables
People people = new People();
private int id;
private String name;
private String address;
private int salary;
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public int getSalary() {
return salary;
}
public void setId() {
this.id = id;
}
public void setName() {
this.name = name;
}
public void setAddress() {
this.address = address;
}
public void setSalary() {
this.salary = salary;
}
}
A POJO is just a plain, old Java Bean with the restrictions removed. Java Beans must meet the following requirements:
Default no-arg constructor
Follow the Bean convention of getFoo (or isFoo for booleans) and setFoo methods for a mutable attribute named foo; leave off the setFoo if foo is immutable.
Must implement java.io.Serializable
POJO does not mandate any of these. It's just what the name says: an object that compiles under JDK can be considered a Plain Old Java Object. No app server, no base classes, no interfaces required to use.
The acronym POJO was a reaction against EJB 2.0, which required several interfaces, extended base classes, and lots of methods just to do simple things. Some people, Rod Johnson and Martin Fowler among them, rebelled against the complexity and sought a way to implement enterprise scale solutions without having to write EJBs.
Martin Fowler coined a new acronym.
Rod Johnson wrote "J2EE Without EJBs", wrote Spring, influenced EJB enough so version 3.1 looks a great deal like Spring and Hibernate, and got a sweet IPO from VMWare out of it.
Here's an example that you can wrap your head around:
public class MyFirstPojo
{
private String name;
public static void main(String [] args)
{
for (String arg : args)
{
MyFirstPojo pojo = new MyFirstPojo(arg); // Here's how you create a POJO
System.out.println(pojo);
}
}
public MyFirstPojo(String name)
{
this.name = name;
}
public String getName() { return this.name; }
public String toString() { return this.name; }
}
POJO:- POJO is a Java object not bound by any restriction other than those forced by the Java Language Specification.
Properties of POJO
All properties must be public setter and getter methods
All instance variables should be private
Should not Extend prespecified classes.
Should not Implement prespecified interfaces.
Should not contain prespecified annotations.
It may not have any argument constructors
Example of POJO
public class POJO {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
A POJO is a Plain Old Java Object.
From the wikipedia article I linked to:
In computing software, POJO is an
acronym for Plain Old Java Object. The
name is used to emphasize that a given
object is an ordinary Java Object, not
a special object, and in particular
not an Enterprise JavaBean
Your class appears to already be a POJO.
POJO class acts as a bean which is used to set and get the value.
public class Data
{
private int id;
private String deptname;
private String date;
private String name;
private String mdate;
private String mname;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMdate() {
return mdate;
}
public void setMdate(String mdate) {
this.mdate = mdate;
}
public String getMname() {
return mname;
}
public void setMname(String mname) {
this.mname = mname;
}
}
When you aren't doing anything to make your class particularly designed to work with a given framework, ORM, or other system that needs a special sort of class, you have a Plain Old Java Object, or POJO.
Ironically, one of the reasons for coining the term is that people were avoiding them in cases where they were sensible and some people concluded that this was because they didn't have a fancy name. Ironic, because your question demonstrates that the approach worked.
Compare the older POD "Plain Old Data" to mean a C++ class that doesn't do anything a C struct couldn't do (more or less, non-virtual members that aren't destructors or trivial constructors don't stop it being considered POD), and the newer (and more directly comparable) POCO "Plain Old CLR Object" in .NET.
According to Martin Fowler
The term was coined while Rebecca Parsons, Josh MacKenzie and I were preparing for a talk at a conference in September 2000. In the talk, we were pointing out the many benefits of encoding business logic into regular java objects rather than using Entity Beans. We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it’s caught on very nicely.
Generally, a POJO is not bound to any restriction and any Java object can be called a POJO but there are some directions. A well-defined POJO should follow below directions.
Each variable in a POJO should be declared as private.
Default constructor should be overridden with public accessibility.
Each variable should have its Setter-Getter method with public accessibility.
Generally POJO should override equals(), hashCode() and toString() methods of Object (but it's not mandatory).
Overriding compare() method of Comparable interface used for sorting (Preferable but not mandatory).
And according to Java Language Specification, a POJO should not have to
Extend pre-specified classes
Implement pre-specified interfaces
Contain pre-specified annotations
However, developers and frameworks describe a POJO still requires the use prespecified annotations to implement features like persistence, declarative transaction management etc. So the idea is that if the object was a POJO before any annotations were added would return to POJO status if the annotations are removed then it can still be considered a POJO.
A JavaBean is a special kind of POJO that is Serializable, has a no-argument constructor, and allows access to properties using getter and setter methods that follow a simple naming convention.
Read more on Plain Old Java Object (POJO) Explained.
there are mainly three options are possible for mapping purpose
serialize
XML mapping
POJO mapping.(Plain Old Java Objects)
While using the pojo classes,it is easy for a developer to map with the database.
POJO classes are created for database and at the same time value-objects classes are created with getter and setter methods that will easily hold the content.
So,for the purpose of mapping in between java with database, value-objects and POJO classes are implemented.
import java.io.Serializable;
public class Course implements Serializable {
protected int courseId;
protected String courseName;
protected String courseType;
public Course() {
courseName = new String();
courseType = new String();
}
public Course(String courseName, String courseType) {
this.courseName = courseName;
this.courseType = courseType;
}
public Course(int courseId, String courseName, String courseType) {
this.courseId = courseId;
this.courseName = courseName;
this.courseType = courseType;
}
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getCourseType() {
return courseType;
}
public void setCourseType(String courseType) {
this.courseType = courseType;
}
#Override
public int hashCode() {
return courseId;
}
#Override
public boolean equals(Object obj) {
if (obj != null || obj instanceof Course) {
Course c = (Course) obj;
if (courseId == c.courseId && courseName.equals(c.courseName)
&& courseType.equals(c.courseType))
return true;
}
return false;
}
#Override
public String toString() {
return "Course[" + courseId + "," + courseName + "," + courseType + "]";
}
}
public class UserInfo {
String LoginId;
String Password;
String FirstName;
String LastName;
String Email;
String Mobile;
String Address;
String DOB;
public String getLoginId() {
return LoginId;
}
public void setLoginId(String loginId) {
LoginId = loginId;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getMobile() {
return Mobile;
}
public void setMobile(String mobile) {
Mobile = mobile;
}
public String getAddress() {
return Address;
}
public void setAddress(String address) {
Address = address;
}
public String getDOB() {
return DOB;
}
public void setDOB(String DOB) {
this.DOB = DOB;
}
}
File-setting-plugins-Browse repositories
Search RoboPOJOGenerator and install, Restart Android studio
Open Project and right click on package select on Generate POJO from JSON
Paste JSON in dialogbox and select option according your requirements
Click on Generate button
If a class is not bogged down from a framework or a library, then an object created from that class is recognized as a POJO.
Let's see some examples:
class MyServlet extends HttpServlet{
//....
}
The sole meaning of MyServlet class is given by the HttpServlet class. Therefore the objects created from the MyServlet are not POJOs.
class MyClass implements Serializable{
//...
}
The Serializable interface does not give a meaning to the class MyClass. Therefore the objects created from the MyClass are POJOs.

Categories