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;
}
Related
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();
Using Lombok to build Phone object. How to skip setting an attribute say "name" using the Builder pattern, if for some reason it would be null
protected Phone createPhone(String number, String name) {
return Phone.builder()
.number(number)
.name(name)
.type(PhoneType.MOBILE)
.build();
}
It is possible to "override" builder methods in Lombok. For example you could do it this way (simplified Phone):
#Builder
#Getter #Setter
public class Phone {
private String number;
private String name;
public static class PhoneBuilder {
// Lombok does not generate name "setter" but uses this instead
public PhoneBuilder name(String name) {
if (null == name) {
// throw or ignore or whatever
throw new NullPointerException("Name NULL");
}
this.name = name;
return this;
}
}
}
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.
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;
}
}
In the below code, I have two objects of same class. One object (A - employeeObjectInDatabase) has all the fields set. Another object (B - employeeObjectForUpdate) has only few of the fields set. basically I need to set not null values of Object B to Object A. Below code has 'if not null' check for each field to set the value. Is there any other better way to get this done?
Is there a better way to replace the code between comments "BLOCK 1 BEGIN" and "BLOCK 1 END"?
In case of classes with few fields, checking for if not null is easy, but in case of 20+ fields there is a lot of if not null check required, hence thought of getting expert opinion.
Sample:
public class Employee {
private String id;
private String name;
private String department;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public static void main(String[] args) {
Employee newEmployeeObject = new Employee();
newEmployeeObject.setId("A100");
newEmployeeObject.setName("Albert");
newEmployeeObject.setName("Physics");
//newEmployeeObject is persisted into database
Employee employeeObjectForUpdate = new Employee();
employeeObjectForUpdate.setId("A100");
employeeObjectForUpdate.setName("Albert Einstein");
//Inorder to update only the fields that are not null
Employee employeeObjectInDatabase = employeeDao.getEmployee();
//BLOCK 1 BEGIN
if (null != employeeObjectForUpdate.getName())
employeeObjectInDatabase.setName(employeeObjectForUpdate.getName());
if (null != employeeObjectForUpdate.getDepartment())
employeeObjectInDatabase.setDepartment(employeeObjectForUpdate.getDepartment());
//BLOCK 1 END
//persist employeeObjectInDatabase as it has the updated information
}
}
You can move the null check in your setter method
public void setName(String name) {
if(name!=null){
this.name = name;
}
}
Then in your main method, you can you simply call the following:
employeeObjectInDatabase.setName(employeeObjectForUpdate.getName());
If in your Data Access layer when you will populate the db values to your object, the same principle will be applied. That is if the Db column value is null, it wont be setting to the property
You could create a member method to transfer non-null field values to a given object of the same type using reflection.
The following shows a solution using org.apache.commons.beanutils.BeanUtilsBean. See if it helps.
Helper in order to copy non null properties from object to another ? (Java)
Add copy method to Object B. This method should copy its non null values to Object A and return it.And also you can use reflection in this method.
look at this post;
Copy all values from fields in one class to another through reflection