Suppose I have two classes.
public class User {
private String userName;
private String age;
private Address address;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public class Address {
private String city;
private String country;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
I want to set city and country of user using java reflection.
parameter map looks like
address.city=COLOMBO
address.country=SRI LANKA.
what is the best way to access address properties inside user object using java reflection.
Since I am going to create object through CSV.
So when user send attribute with dot (.) its means its object inside another object.
I want to write global reflection method to use through out the application.
One method to create object using CSV
The best way would be to create a new Address object, and then call the setters for this object and finally call the setAddress for the user.
The best pattern of use doesn't change because you are using reflection. I suggest you do the same thing but using reflection.
I think using reflection for that is not the best way. Anyway, as Peter tell you in the first answer, you should create a new object and assign it using the setter.
Related
This question already has answers here:
Why use getters and setters/accessors?
(37 answers)
Closed 1 year ago.
Recently I was going through the concept of Encapsulation in Java. I was wondering if making data variables private along with public setter methods really make sense in simple POJO class? Please refer below POJO:
public class Employee{
private String id;
private String name;
private String department;
private int age;
public Employee(){
}
public Employee(String id, String name, String department, int age){
this.id = id;
this.name = name;
this.department = department;
this.age = age;
}
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
I mean why am I making the name variable private when I can anyway change it using the setter method?
In the general case, it'll be the very basic
public void setName(String name) {
this.name = name;
}
Where it's identical to just doing employee.name = "william hammond". But imagine a case where you'd like to do implement something like a private String normalize(string username) method where you maybe make it all lower case, check for a valid name or prevent unicode entries. If you make name public initially you'll have users doing employee.name = "whatever they want :) 123" and you'll lose the ability to enforce that constraint.
Also see Why use getters and setters/accessors?
Using getters/setters is just considered good practice, but it can often be overkill - like in your example.
If you have methods that mutate the variable before setting, then it's nice to have getters/setters for the basic fields as well to maintain consistent code style.
Here's a good article on it:
https://dzone.com/articles/getter-setter-use-or-not-use-0
Let's have an example:
public class Example {
private String firstName;
private String lastName;
public Example(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
}
This class has 3 properties (firstName, lastName, fullName), but only two fields (firstName, lastName). It makes sense, because a full name can be retrieved by combining first and last name.
However, I've noticed that I call getFullName() a lot of times in my program, but I almost never call getFirstName() and getLastName(). This slows down my program, because I need to create a new string each time getFullName() is called. So, I've refactored my code to have a better performance:
public class Example {
private String fullName;
public Example(String firstName, String lastName) {
this.fullName = firstName + " " + lastName;
}
public String getFirstName() {
return fullName.split(" ")[0];
}
public String getLastName() {
return fullName.split(" ")[1];
}
public String getFullName() {
return fullName;
}
}
Now my code works faster when calling getFullName(), but slower when calling getFirstName() and getLastName(), however It's exactly what I needed. From outside the class, nothing really've changed.
As you can see by the given example, fields describe how your class uses the computer's memory, but not necessarily which properties your class has. This is why fields should be considered an implementation detail and therefore be private to a class.
I have a User class which saves some extra data on the user. This data is stored in/coming from Firestore. I have a couple of fields which are working(name, surname, lastLogin) but a couple of them are not working(blocked).
When I make the field public they work, but when I try to use a setter, it doesn't. I tried cleaning the build and rebuilding it. I know it is not saving the field due to #Exclude, that is intended.
What am I doing wrong? The field type doesn't matter, I've added a new String field which gave the same warning, while name and surname work.
The database:
**userid**
{
"name" : "John",
"surname" : "Doe",
"lastLogin" : **timestamp**,
"blocked" : true
}
The class:
#Keep
public class User
{
private String name;
private String surname;
private Date lastLogin;
private boolean blocked = false;
public User()
{
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getSurname()
{
return surname;
}
public void setSurname(String surname)
{
this.surname = surname;
}
public Date getLastLogin()
{
return lastLogin;
}
public void setLastLogin(Date lastLogin)
{
this.lastLogin = lastLogin;
}
#Exclude
public boolean isBlocked()
{
return blocked;
}
public void setBlocked(boolean blocked)
{
this.blocked = blocked;
}
The problem in your code is that the constructor in the User class is private. That's not the correct way in which you should create a new instance of the class. JavaBeans require a no-argument constructor to be present.
When Cloud Firestore SDK deserializes objects that are coming from the database, it requires that any objects in use, to have this public no-argument constructor, so it can use it to instantiate the object. Fields in the objects are set by using public setter methods or direct access to public members, as you already tried.
Because your constructor is private, the SDK doesn't really know how to create an instance of it. So it is mandatory to change it as public. A correct way to create that class should be:
class User {
private String name;
private String surname;
private long lastLogin;
private boolean blocked = false;
public User() {} //Needed for Cloud Firestore
public User(String name, String surname, long lastLogin, boolean blocked) {
this.name = name;
this.surname = surname;
this.lastLogin = lastLogin;
this.blocked = blocked;
}
//Getters and setters are not mandatory
}
Also please note that the setters and the getters are not required. Setters are always optional because if there is no setter for a JSON property, the Firebase client will set the value directly onto the field.
Edit:
According to your comment:
but it does not explain why some fields are working and others aren't. It should not work at all, right?
Yes, that's right, all should work. The reason why some of them are not working is that the blocked property in your User class is of type boolean while in your database is of type String and this is not correct. Both types must match.
And the private constructor is due to the singleton instance, as far as I know, the constructor should be private to avoid creating new instances of the class.
No, the constructor must be public. I think there is a misunderstanding. Every time you use FirebaseDatabase.getInstance(), a single socket connection between your application and the Firebase servers is opened. From that moment on, all traffic between the application and the database goes over the same socket. So it doesn't matter how many times you create an instance, it will always be a single connection. Regarding your POJO class, there is no need for such a Singleton because Firebase always needs to know how to create an instance of that class, using the public no-argument constructor.
Try to create a constructor with parameters for all class attributes along with a non-parameter constructor and then in the java class where you store in firebase, create object from user and pass it.
for example:
package com.example.spacing.Model;
public class User {
private String username;
private String phone;
private String id;
private String imageURL;
private String email;
public User(String username, String email ,String phone, String id, String imageURL) {
this.username = username;
this.email=email;
this.phone = phone;
this.id = id;
this.imageURL = imageURL;
}
public String getImageURL() {
return imageURL;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public User() {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
and
FirebaseDatabase.getInstance().getReference("Users")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(user);
You can try to add #field:JvmField to your boolean variable inside your User class.
Consider the following class.
public class UserDTO {
private String email;
private String password;
private String country;
private String fName;
private String lName;
private String type;
private String profPicPath;
public UserDTO(String fNme, String lNme, String profPic) {
this.setfName(fNme);
this.setlName(lNme);
this.setProfPicPath(profPic);
}
public String getEmail() {
return email;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getfName() {
return fName;
}
public void setfName(String fName) {
this.fName = fName;
}
public String getlName() {
return lName;
}
public void setlName(String lName) {
this.lName = lName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getProfPicPath() {
return profPicPath;
}
public void setProfPicPath(String profPicPath) {
this.profPicPath = profPicPath;
}
I want to create an object only contains the fName, Lname and profPicPath. I have created a constructor to initialize only these three fields. But when I create an object using this constructor it contains the other properties as well with null values. Is there any approach in Java to create an object only with a selected properties ?
I think you are confused between the domain/model object and DTO object. The domain/model class represents the full set of attributes while you specific DTOs representing subsets of attributes in the domain/model class e.g. the User class is your domain/model class representing the full set of attributes (email, password, country, fName, lName, type, gender, country, profPicPath etc.) and then you can have DTOs like, UserLoginCredentialDTO (with email and password attributes), UserDemographyDTO (with attributes like gender, country etc.).
You can also check https://softwareengineering.stackexchange.com/questions/155768/what-oo-design-to-use-is-there-a-design-pattern for another example.
Apart from this, the comments of JB Nizet and Abra are quite valid and will help you understand this concept better in terms of Java.
yes. the approach is called inheritance. You need to create a BaseUserDTO that contains the subset of properties that is shared between the two entities. (they need to be declared as protected to be accessible to the subclass) UserDTO will extend the base class so it contains all its properties plus its own. the constructor with three properties must call the matching super constructor in order to initialize the shared properties
im trying to learn how to use pattern builder. i could get it to work until i tried to use enum.
I tried to change the code couple of times and each time had different error. right now the error is Incompatible types.
Please can you help bringing this code to working state and if you have suggestions to improve the code it would be great.
thanks.
EDIT:
now it seems to be okay, but how do i use it with the builder inside the main?
this was the code i used
main:
Person person3 = new Person.PersonBuilder("Julliete", "Kaplan" )
.status(); // what should i write here to set the status?
person class
public class Person
{
private final String name;
private final String lastname;
private final int age;
//My enum im trying to use
private Status status;
public enum Status
{
SINGLE ("Single"), MARRIED ("Married"), WIDOWER ("Widower");
private String status;
private Status(String status)
{
this.status = status;
}
public String getStatus()
{
return this.status;
}
}
//builder
private Person(PersonBuilder builder) {
this.name = builder.name;
this.lastname = builder.lastname;
this.age = builder.age;
this.status = builder.status;
}
//GETTERS
public String getName() {
return name;
}
public String getLastname() {
return lastname;
}
public int getAge() {
return age;
}
#Override
public String toString() {
return "Person : "+this.name+", "+this.lastname+", "+this.age;
}
//PersonBuilder
public static class PersonBuilder
{
private final String name;
private final String lastname;
private int age;
private Status status;
public PersonBuilder(String name, String lastname) {
this.name = name;
this.lastname = lastname;
}
public PersonBuilder age(int age) {
this.age = age;
return this;
}
public PersonBuilder status(Status status)
{
this.status = status;
return this;
}
public Person build() {
Person person = new Person(this);
return person;
}
}
Don't define another Status enum inside the builder: reuse the one defined in the Person class.
Otherwise, you've got to map from instances of PersonBuilder.Status to instances of Person.Status: they are entirely separate types.
Currently this mapping is trivial: you can use Person.Status.valueOf(personBuilderStatus.name()) - but you have to ensure that you update both at the same time to have identical values (or at least that PersonBuilder.Status maps to a subset of Person.Status), which is an unnecessary maintenance burden going forwards.
I am having issues with my getter and setter methods for my contact class. Could someone help me better understand these methods? Thanks here's my code I have so far for my contact class getter and setter methods
public class Contact {
public static void main (String []args){
}
private String name;
private String email;
//constructor, validates the email to make sure the '#' character is present
Contact(String name, String email){
this.name = name;
if(email.indexOf("#") >= -1)
System.out.println("invalid email");
else
this.email = email;
}
//method points out the contact's name and email
void getContactList(){
System.out.println(name + "" + email);
}
//setter method for name
void getname(String name){
this.name = name;
}
//setter method for email
void getemail(String email){
this.email = email;
}
//getter method for name
//getter method for email
}
Getters and setters are implemented like so:
// setter
void setFoo(Foo foo) {
this.foo = foo;
}
// getter
Foo getFoo() {
return foo;
}
Currently your "getter" is actually a setter, and you haven't implemented a getter.
Getter/setter pairs are a common way to make variables secure by setting them to private. You can get the vlaue of an object's variable with getVar and set the value with setVar(Obj value).
Your code could be repaired like so:
public class Contact {
private String name;
private String email;
//constructor, validates the email to make sure the '#' character is present
public Contact(String name, String email){
this.name = name;
if(email.indexOf("#") == -1) { //# not present
System.out.println("invalid email");
this.email = null;
}
else
this.email = email;
}
//method points out the contact's name and email
public String getContactList(){
return name + "" + email;
}
//setter method for name
public void setName(String name){
this.name = name;
}
//setter method for email
public void setEmail(String email){
this.email = email;
}
//getter method for name
public String getName() {
return name;
}
//getter method for email
public String getEmail() {
return email;
}
}
I highly recommend you do some more research on common Java paradigms before you begin making programs. Check out what a Java Bean is, what access types are, and so on.