Java Constructor - java

Good day!
I created overloading constructors as follows:
public ContactsBean(String firstName, String lastName,
String telNumber, String email) {
this.id = count;
count = count + 1;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.telNumber = telNumber;
}
public ContactsBean() {
this.id = count;
count = count + 1;
}
I want to auto-increment the id so i used this variables:
private static int count;
private int id;
My problem is, when I instantiate the ContactsBean() contacts = new ContactsBean(), the value of id is incremented by 2..
2,4,6,8... etc.
Why? How can I do the auto number of ID increment by 1?
Thank you.
EDIT:
Action:
private ContactsBean contacts = new ContactsBean();
private ContactsManager contactsManager = new ContactsManager();
public String add() {
contactsManager.addContacts(contacts);
return SUCCESS;
}
Manager:
private ContactsDAO contactsDAO = ContactsDAO.getInstance();
private List<ContactsBean> contactsList = contactsDAO.getContactsList();
public void addContacts(ContactsBean contact) {
contactsList.add(contact);
}

First, DRY (do not repeat yourself), would be better:
public ContactsBean(String firstName, String lastName,
String telNumber, String email){
this();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.telNumber = telNumber;
}
Second, there is no increment by two in your code. Please paste in your test code.

Try removing the first set of parentheses from
ContactsBean() contacts = new ContactsBean();.
That is, try this constructor:
ContactsBean contacts = new ContactsBean();

I think you are creating two objects of ContactsBean in your other classes may be you are unaware of it. You have to check the code.

Have you tried debugging your code setting a breakpoint on both constructors?
The suggestion of Eng. Fouad is a good tip but it's not gonna solve your problem.
Also note that your counter is not thread-safe (the problem has nothing to do with it, though. In that case your counter would have a lower value than it should)
And if you really need to keep track on how many objects you actually create, I don't think the best way to do this is with a static attribute in a Java Bean...

It might be due to the copy constructor calling the no-arg version of your contstructor.
(Or am I suffering from C++ sickness?)

My suggestion would be to not try to increment the contactID in the contructor, but either get it from the newly created database object where the ID is being incremented by databse via identity specification, or since you are getting the list of contacts base your next id off of contactsDAO.getContactsList().size()+1.
I'd also recommend changing from:
private ContactsDAO contactsDAO = ContactsDAO.getInstance();
private List<ContactsBean> contactsList = contactsDAO.getContactsList();
public void addContacts(ContactsBean contact) {
contactsList.add(contact);
}
To something like:
private ContactsDAO contactsDAO = ContactsDAO.getInstance();
private List<ContactsBean> contactsList;
public void addContacts(ContactsBean contact) {
int id = getContactList().size()+1;
contact.setId(id);
contactsList.add(contact);
}
public List<ContactsBean> getContactList(){
return contactsDAO.getContactsList();
}
alternatively if you are able to remove contacts from the database, this number might not be accurate for the ID. You could create a query based on such as:
select MAX(ID) from contacts
This will return the largest id number used.

private static int count = 0;
private int id;
// ...
public ContactsBean(String firstName, String lastName,String telNumber, String email)
{
this();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.telNumber = telNumber;
}
public ContactsBean()
{
id = ++count;
}

I learned that Struts2 generates the instance of an object(beans) automatically in the Action Classes so no need to instantiate it....
My code before is
private ContactsBean contacts = new ContactsBean();
private ContactsManager contactsManager = new ContactsManager();
public String add() {
contactsManager.addContacts(contacts);
return SUCCESS;
}
//getters and setters
I changed it to..
private ContactsBean contacts;
private ContactsManager contactsManager = new ContactsManager();
public String add() {
contactsManager.addContacts(contacts);
return SUCCESS;
}
//getters and setters
And it works...

Related

Firestore: (21.4.1) [CustomClassMapper]: No setter/field

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.

difference between string and property String in tableview javafx

what is the difference between string and Property String in tableview javafx?
how it changes the tableview if i use data type as String or Property String ??
Can anyone give example to show this difference
Property String is different in Java. Basically you use property String when you want to observe your variable in a TableView. The reason Java does this is that Java uses an MVC Pattern (Model-View-Controller). The model is your stored data, the view is what you see like GUI and the controller is the brains and logic for everything in your application. The Model in Java is done as classes that hold properties rather than just fields. Because when you want to store data into a TableView in JavaFX the proper way is to instantiate objects from a class and the Properties defined in this class becomes the properties of this object, by then you can store the object in the TableView and put some logic to allow the tableView to go find the properties of this object and fill them in the table, if they were Strings rather than properties, JavaFX won't be able to get them and make them observable in the table. I wrote some logic below to give you an idea of how this is done. So first this is a class that acts as a Model:
public class Contact extends SQL_Objects {
private SimpleStringProperty id;
private SimpleStringProperty firstName;
private SimpleStringProperty lastName;
private SimpleStringProperty phone;
private SimpleStringProperty email;
private SimpleStringProperty unitNo;
private SimpleStringProperty street;
private SimpleStringProperty city;
private SimpleStringProperty province;
private SimpleStringProperty zipCode;
private SimpleStringProperty country;
private SimpleStringProperty gender;
private SimpleStringProperty notes;
private SimpleStringProperty relationship;
private final static String[] FIELD_NAMES = { "id", "firstName", "lastName", "phone", "email", "unitNo", "street", "city", "province", "zipCode", "country", "gender", "notes", "relationship" };
public Contact(String id, String firstName, String lastName, String phone, String email, String unitNo, String street, String city, String province, String zipCode, String country, String gender, String notes, String relationship) {
this.id = new SimpleStringProperty(id);
this.firstName = new SimpleStringProperty(firstName);
this.lastName = new SimpleStringProperty(lastName);
this.phone = new SimpleStringProperty(phone);
this.email = new SimpleStringProperty(email);
this.unitNo = new SimpleStringProperty(street);
this.street = new SimpleStringProperty(street);
this.city = new SimpleStringProperty(city);
this.province = new SimpleStringProperty(province);
this.zipCode = new SimpleStringProperty(zipCode);
this.country = new SimpleStringProperty(country);
this.gender = new SimpleStringProperty(gender);
this.notes = new SimpleStringProperty(notes);
this.relationship = new SimpleStringProperty(relationship);
}
public String getId() {
return id.get();
}
public String getFirstName() {
return firstName.get();
}
public String getLastName() {
return lastName.get();
}
public String getPhone() {
return phone.get();
}
public String getEmail() {
return email.get();
}
public String getUnitNo() {
return unitNo.get();
}
public String getStreet() {
return street.get();
}
public String getCity() {
return city.get();
}
public String getProvince() {
return province.get();
}
public String getZipCode() {
return zipCode.get();
}
public String getCountry() {
return country.get();
}
public String getGender() {
return gender.get();
}
public String getNotes() {
return notes.get();
}
public String getRelationship() {
return relationship.get();
}
public static String[] getFieldNames() {
return FIELD_NAMES;
}
Those getters and setters should follow the Standards of naming conventions in Java, so that when you insert and object into the table as i will show below, the table would use the field names and fetch for the getter for each field to get it's value and make it observable in the tabele, so below is an example of the controller to fill the columns and rows of the table:
private void fillColumns() {
try { // starting from 2 so that the id column is not included
for (int i = 2; i <= resultSet.getMetaData().getColumnCount(); i++ ) {
TableColumn column = new TableColumn(resultSet.getMetaData().getColumnName(i));
column.setCellValueFactory(new PropertyValueFactory<Contact, String>(Contact.getFieldNames()[i - 1]));
selectedTable.getColumns().add(column);
}
} catch (SQLException ex) {
Alert alert = new Alert(Alert.AlertType.ERROR, "Type:\n" + ex.getClass().getName() + "\n\nMessage: Unable to get the columns from the database\n\nDetails:\n" + ex.getMessage(), ButtonType.OK);
}
}
The next is to fill the rows, assuming i selected data from the database and stored them in a result set, i will use the next method to go through the records of the resultSet row by row, this method would return false when there is no more rows
private void fillRows() {
shownRecords = 0;
try {
while(resultSet.next()) {
Contact cont = new Contact(Integer.toString(resultSet.getInt(1)), resultSet.getString(2), resultSet.getString(3), resultSet.getString(4), resultSet.getString(5), resultSet.getString(6), resultSet.getString(7), resultSet.getString(8), resultSet.getString(9), resultSet.getString(10), resultSet.getString(11), resultSet.getString(12), resultSet.getString(13), resultSet.getString(14));
tableView.getItems().add(cont);
}
resultSet.beforeFirst();
} catch (SQLException ex) {
Alert alert = new Alert(Alert.AlertType.ERROR, "Type:\n" + ex.getClass().getName() + "\n\nMessage: Unable to get the records from the database\n\nDetails:\n" + ex.getMessage(), ButtonType.OK);
alert.show();
}
}
So as you can see, i used SimpleStringProperty rather than Strings and if u used Strings here JavaFx wouldn't be able to display the results as they somehow are not considered properties of the objects inserted into the table

Create unique ID with constructor

I want to create objects with a name and a unique ID number that increments with the creation of each user.
class user {
static int uid = 0;
String name;
public user (String name){
User.uid = uid++;
this.name = name;
}
}
When creating user objects in a main method and printing out their ID they all return 0. I think there is a simply fix to this but can't seem to find it elsewhere online.
Your code has several problems:
A User doesn't have any ID. All you have is a static ID, thus shared by all users
You're incrementing the static ID, and then assigning its previous value to the ID right after.
You're not respecting the Java naming conventions.
The code should be
class User {
private static int uid = 0;
private String name;
private int id;
public User(String name) {
uid++;
this.id = uid;
this.name = name;
}
// getters
}
or, if you want the IDs to start at 0:
class User {
private static int uid = 0;
private String name;
private int id;
public User(String name) {
this.id = uid++;
this.name = name;
}
// getters
}

ArrayList from user model returns null

So in the app I'm creating I have a user class defined as the following
public class User implements Serializable{
private int id;
private String username;
private String firstName;
private String lastName;
private String email;
private String password;
private String picture;
private ArrayList<String> tags;
private double rating;
private Category favorite;
private boolean star;
private Location homeLocation;
public User(int id, String username, String firstName,String lastName,String picture, ArrayList<String> tags,double rating, Category favorite, boolean star,Location homeLocation,String email,String password) {
this.id = id;
this.username = username;
this.firstName = firstName;
this.lastName = lastName;
this.picture = picture;
this.tags = tags;
this.rating = rating;
this.favorite = favorite;
this.star = star;
this.homeLocation = homeLocation;
this.email = email;
this.password = password;
}
public int getId() {
return id;
}
public String getUsername() {
return username;
}
public String getFirstName() {
return firstName;
}
public String getLastName(){ return lastName;}
public String getPicture(){ return picture;}
public ArrayList<String> getTags() {
return tags;
}
public double getRating(){ return rating;}
public Category getFavorite(){ return favorite;}
public Boolean getStar(){ return star;}
public Location getHomeLocation(){return homeLocation;}
public String getEmail(){return email;}
public String getPassword(){return password;}
public void setId(int id){
this.id = id;
}
Now, when I create a User object I pass an ArrayList<String> tags which, when logged, shows just as intended.
List<String> listTags = Arrays.asList(DummyTags.tagsNewUser);
ArrayList<String> tags = new ArrayList<>();
tags.addAll(listTags);
Log.d("Tags",tags.toString());
user = new User(0,userName,firstName,lastName,picturePlaceHolder,tags,4,category,true,loc,email,password);
However, when I use this user object in, say a profile page, and retrieve the users tags through the getter in the class it always returns null.
user = (User) getArguments().getSerializable("User");
tags = user.getTags();
Doing this always has tags be null, no matter what ArrayList I pass when creating the user object.
I also get a warning in android studio saying that invoking user.getTags() may produce a npe. Every other part of the user model works just fine. I have tried to solve this for a while now and have not been able to find anything relating to my problem so any help would be appreciated!
Try:
Bundle bundle=new Bundle();
bundle.putStringArrayList("tags",tags);
bundle.putSerializable("User",user);
and then retrieve as:
tags = getArguments().getStringArrayList("tags");
The reason that your solution does not work is that ArrayList is not implementing Serializable interface

Data structure for storing phonebook data

What would be the best data structure to store phone book contacts, each consisting of first name, last name and phone number. The user must be able to search by each one of the fields.
There has been similar questions, but none of the answers were clear enough.
Create a POJO type, that stores first name, last name, and phone number (could make it mutable if needed).
class PhoneBookEntry {
public final String firstName;
public final String lastName;
public final String phoneNumber;
public Entry(String firstName, String lastName, String phoneNumber) {
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
}
//... equals + hashcode implementation
}
You can create your phone book like this:
class PhoneBook {
private Map<String, Set<PhoneBookEntry>> firstNameMap;
private Map<String, Set<PhoneBookEntry>> lastNameMap;
private Map<String, Set<PhoneBookEntry>> phoneNumberMap;
public void add(PhoneBookEntry entry) {
Set<PhoneBookEntry> set
= firstNameMap.computeIfAbsent(entry.firstName, k -> new HashSet<>());
set.add(entry);
set = lastNameMap.computeIfAbsent(entry.lastName, k -> new HashSet<>());
set.add(entry);
set = phoneNumberMap.computeIfAbsent(entry.phoneNumber, k -> new HashSet<>());
set.add(entry);
}
public Set<PhoneBookEntry> getByFirstName(String firstName) {
return firstNameMap.get(firstName);
}
public Set<PhoneBookEntry> getByLastName(String lastName) {
return lastNameMap.get(lastName);
}
public Set<PhoneBookEntry> getByPhoneNumber(String phoneNumber) {
return phoneNumberMap.get(phoneNumber);
}
}
Using Maps allows for fast lookup.
As yitzih said, Multiple contacts can have the same first name, last name, or phone number. So a lookup by first name (for instance), will return a set of contacts.
Create a Contact object that stores the variables needed for each contact. Use an ArrayList to store them.
Without having more information about the contact there isn't really any way to use a HashTable, Map or Graph. There is no real key value pair for a HashTable unless you want to use a combination of first and last names, but you would need some way to handle conflicts (if 2 people have the exact same name.), or you would need to forbid having 2 people having the same Contact name (but why would you want to do that?)
Class Contact{
String forename;
String Surname;
String phoneNo;
public Contact(fName, sName, pNo){
forename = fName;
Surname = sName;
phoneNo = pNo;
}
public String getForename(){}
public String getSurname(){}
public String getPhoneNo(){}
}
in the class handling the search,
you declare an arrayList of type Contact, and when searching for a contact say John,
public Contact searchContact(String s){
for(int i = 0; i< ContactList.size(); i++){
if(ContactList.get(i).getForename().equals(s) ||
ContactList.get(i).getSurame().equals(s) ||
ContactList.get(i).getPhoneNo().equals(s)
){
return ContactList.get(i);
}
}
return null;
}
Kind of a vague question, but what the heck, maybe this'll chase away my post-lunch sleepies. I'm assuming a simple String representation of the phone number, but the best data object to store all the possible varieties of world phone numbers along with a method to intelligently search them (e.g. is "(123) 456-7891" the same as "1234567891"?) could be it's own question entirely.
Here a PhoneBook class stores all of the contacts. The methods searchFirst(), searchLast() and searchPhoneNumber() each return lists of matching contacts.
public class PhoneBook {
ArrayList<Contact> contacts;
public PhoneBook() {
contacts = new ArrayList<>();
}
public void addContact(Contact contact) {
contacts.add(contact);
}
public ArrayList<Contact> searchFirst(String first) {
ArrayList<Contact> foundContacts = new ArrayList<>();
for (Contact contact: contacts) {
if (contact.first.equals(first)) {
foundContacts.add(contact);
}
}
return foundContacts;
}
public ArrayList<Contact> searchLast(String last) {
ArrayList<Contact> foundContacts = new ArrayList<>();
for (Contact contact: contacts) {
if (contact.last.equals(last)) {
foundContacts.add(contact);
}
}
return foundContacts;
}
public ArrayList<Contact> searchPhoneNumber(String phoneNumber) {
ArrayList<Contact> foundContacts = new ArrayList<>();
for (Contact contact: contacts) {
if (contact.phoneNumber.equals(phoneNumber)) {
foundContacts.add(contact);
}
}
return foundContacts;
}
class Contact {
String first;
String last;
String phoneNumber;
public Contact(String first, String last, String phoneNumber) {
this.first = first;
this.last = last;
this.phoneNumber = phoneNumber;
}
}
}

Categories

Resources