I have a class with (say) 50 fields. I only use a few of them per deployment of the program per user need. Is there a way to make the constructor generic yet specific to the deployment?
e.g
public class Employee{
private String id = "default";
private String empcat = "default";
private String empfam = "default";
private String phychar = "default";
private String othchar = "default";
private String shoesty = "default";
private Double shoesiz = 0.0;
private String shoesty = "default";
private Double shirsiz = 0.0;
private String shirsty = "default";
.........50 other fields..
}
"User/Customer 1" - only wants to use the program for shoe and thus instantiates the object with :
Employee obemp = new Employee("John", 11.5, Dockers); (i.e. id, shoesiz and shoesty)
User/Customer 2 - only wants to use the program for shirt and thus instantiates the object with :
Employee obemp = new Employee("John", 42, ABC); (i.e. id, shirsiz and shirsty)
User/Customer 3 - only wants to use the program for family and thus instantiates the object with :
Employee obemp = new Employee("John", "Smith"); (i.e. id, empfam)
The order of the fields during the object creation can be different - depending on the usage in the model.
First of all, I'd suggest breaking your main class down into smaller pieces that manage data which typically goes together (Shoe information, Shirt information, Family information, etc.).
Secondly, I'd suggest you provide customers with a builder pattern to make it easy for them to construct an object with just the pieces that they're likely to need. That way, they can do something like this:
Employee emp = new EmployeeBuilder("John")
.withShirtInfo(shirsiz, shirsty)
.build();
There is no generic way in core java to do this. But you may use some design pattern like - builder pattern.
You may also create an Employee with some minimum criteria like - id. We can assume each Employee have an id. So create an Employee with the id using the Employee(String id) constructor -
public class Employee{
//all properties
public Employee(String id){
this.id = id;
}
//setter methods
}
Suppose you have create an Employee like this -
Employee employee = new Employee("eng134");
After that you can set only required property to employee object using the setter methods -
employee.setShoesiz(9);
employee.setShirsiz(26);
Related
Lets say, Employee class has three properties.
class Employee {
int id;
String name;
String team;
public Employee(){
this.id = id;
this.name = name;
this.team = team;
}
}
I want to remove team from the object before putting into HashMap.
Map<Integer, Employee> empMap = new HashMap<>();
Employee e1 = new Employee(100, "John", "Dev");
Employee e2 = new Employee(101, "Mary", "Dev");
Employee e3 = new Employee(103, "Andy", "QA");
empMap.put(e1.getId(), e1);
empMap.put(e2.getId(), e2);
empMap.put(e1.getId(), e3);
The values in empMap shouldn't have team property in it. Creating new objects would work but it is costly in real time. Is there a way to achieve this without creating new objects.
One option, as you have mentioned, is to create new objects without the team property. Another is to use a façade
public class MapEmpFacade extends Employee {
public MapEmpFacade(Employee emp) {
//define all methods to return the method results from emp, except for getTeam
}
public int getTeam() { return null; } //override getTeam
}
You may review your design to be sure you need the property to be there.
You are holding Employee references in the map, the team property is there and probably is correctly representing an Employee ... you can just avoid using the team property ... or maybe you want to have a Person class.
If you are using those instances from some framework to do something (e.g.: serialization, persistence, etc) it should probably provide a way to ignore/skip a property in your object.
I'm creating a simple Java app that would store and display information for customers.
I want to make the id as an automated generated number but having problems with that, don't know should I set it in get or set methods?
Can anyone help me to use that value as?
Here is an example:
public class Customer{
public Person(String firstName, String lastName, String email, String address, String country){
this.id.set(Integer.parseInt(UUID.randomUUID().toString()));
this.firstName.set(firstName);
this.lastName.set(lastName);
this.email.set(email);
this.address.set(address);
this.country.set(country);
}
private final IntegerProperty id = new SimpleIntegerProperty(this,"Id",0);
private final StringProperty firstName = new SimpleStringProperty(this,"First Name","");
private final StringProperty lastName = new SimpleStringProperty(this,"Last Name","");
private final StringProperty email = new SimpleStringProperty(this,"E-mail","");
private final StringProperty address = new SimpleStringProperty(this,"Address","");
private final StringProperty country = new SimpleStringProperty(this,"Country","");
I also created generic bean methods but it's just simple like this:
public StringProperty firstNamePropery(){
return firstName;
}
public String getFirstName(){
return firstName.get();
}
public void setFirstName(String firstName){
this.firstName.set(firstName);
}
//...rest of the methods...
I tried to use this but doesn't work:
public IntegerProperty idProperty(){
return id;
}
public Integer getId(){
return id.get();
}
public void setId(){
this.id.set(Integer.parseInt(UUID.randomUUID().toString()));
}
Thank you for helping me on this one.
A UUID string looks like this 38400000-8cf0-11bd-b23e-10b96e4ef00d. You can't parse this string into an Integer.
If you want to use UUIDs as the Ids for the customers then, declare the attribute as UUID or String instead of Integer.
EDIT I
Also, I don't need to store it as an Integer value, the string can do
job but just can't get to create that number when creating a new
instance of that class.
To use a UUID as a String:
In the Customer class the id attribute must be of type String instead of Integer (or int).
To get a new String representation of the UUID you call UUID.randomUUID().toString(). The result of this call can be assigned to the customer's id without doing any parsing.
Also note that the signatures of the getter and setter have to change accordingly.
In the current setId() method you are creating a new id. This would override the id assigned when the Customer is created using the call in the constructor. If you want flexibility to assign a new id you can have the setId receive a new UUID string and assign that as a new id to the Customer object.
public class Customer{
public Customer(String firstName, String lastName, String email, String address, String country){
this.id.set(UUID.randomUUID().toString());
}
...
public String getId(){
return this.id;
}
public void setId(String newId){
this.id = newId;
}
}
Note: The class name is Customer and the constructor is Person. This is wrong, both must have the same name. You must have some compiler error telling you this. I will assume the correct name of the class and constructor is Customer
/EDIT I
The use case for UUID is when you need to have a unique id without checking if the id already exists with some other party (for example a database engine or a server in a network application without a central server).
If what you want to use is Integer (or Long) there is no real reason to use a Random number, you can use a sequential number for your ids.
If if is a standalone application in javafx, and you are not using different threads to create customers in parallel, then there isn't much more to worry about.
On the other side if it is a client server application. Then you have take in mind the concurrent access of clients to the server.
If you delegate the id creation as a sequence in the database then, the concurrency issue or generating duplication in the id is taken care by the database itself. This could be an autoincrement field in the same customer table (assuming you are using one), a sequence, or a table acting as a sequence. On another side, if it is a class of yours which is going to generate the ids one by one, then you will have to take care of concurrent requests. You will have to make sure that only one thread can increment the id at a time.
Regarding getters and setters, getXxx() returns the value of xxx attribute. and setXxx(123) would set or assign the value 123 to the attribute xxx;
I was going through refactoring book and couldn't understand these two techniques.
https://refactoring.com/catalog/changeValueToReference.html
And
https://refactoring.com/catalog/changeReferenceToValue.html
Can you please help me understand with an example in Java?
Assume you have two Customer objects/instances, customer1 and customer2. They are actually the same customer, with same ID and name. However they were read at different moments from the database or such. A new Customer() was called twice.
Customer customer1 = new Customer(13L);
Customer customer2 = new Customer(13L);
The refactoring would involve a factory method:
Customer customer1 = customerRepository.findById(13L);
Customer customer2 = customerRepository.findById(13L);
Examples of the latter is for instance JPA, an O/R mapping.
In it's very simplest form it just means switching between the following two options:
class Order
{
// constructor etc...
private String customerName;
public String getCustomerName() {return customerName;}
}
or
class Customer
{
// constructor etc...
private String name;
public String getName() {return name;}
public String setName(String name) {this.name = name;}
}
class Order
{
// constructor etc...
private Customer customer;
public String getCustomerName() {return customer.getName();}
}
Now when a customer's name can change, the 2nd solution is prefered, because you don't need to update the customerName member in every order.
However if a customer's name never changes, the 1st solution might be prefered, because you don't need to manage Customer objects somewhere.
Which version you want to chose and if you need to refactor depends on your actual application.
Strictly speaking, I'm not sure whether this conversion is possible in Java, since you don't have both references and values of objects in Java - all objects are references (which are passed by value).
However, one can consider this similar to the following example:
"Value":
class Order
{
private int orderNum;
private Customer customer;
Order(int orderNum, String customerString)
{
this.orderNum = orderNum;
this.customer = new Customer(customerString);
}
}
// elsewhere:
Order order1 = new Order(1, "I am a customer");
Order order2 = new Order(2, "I am a customer");
Order order3 = new Order(3, "I am a customer");
Order order4 = new Order(4, "I am a customer");
Here each Order has it's own Customer object, even when all or most of those Customer objects are the same.
The above is, of course, just an example. Passing all parameters of another object into a constructor is not good design.
Reference:
class Order
{
private int orderNum;
private Customer customer;
Order(int orderNum, Customer customer)
{
this.orderNum = orderNum;
this.customer = customer;
}
}
Customer customer = new Customer("I am a customer");
Order order1 = new Order(1, customer);
Order order2 = new Order(2, customer);
Order order3 = new Order(3, customer);
Order order4 = new Order(4, customer);
Here we can have a single Customer for many Orders (if we want).
I want to know how can I save different parameters related to one Key in a single list.
For example imagine I have a list of people who have a name, a family name, a salary and a Key to find any unique person in the list.
What can I use to store these information in single list?
What are structures that I can use? Like List, Array List, Hash Map, Map, Set etc.
Do I have to define a new class?
You should probably define a Person class having all the properties you mentioned. Then you can store the people in a Map<Integer,Person> or Map<String,Person>, depending on whether the unique identifier of a Person is an Integer or a String.
If you use the HashMap implementation of Map, you'll be able to locate a Person by its identifier key in expected constant time.
You don't have to, but I would strongly recommend to define a class. It could look like this:
package com.yourcompany.projectname;
public class Person {
public String name;
public String familyName;
public BigDecimal salary;
}
then store it in a HashMap:
public static void main(String[] args) {
Map <String, Person> persons = new HasMap <>();
// define a new person
Person dady = new Person();
dady.name = "Tim";
dady.familyName = "Smith";
dady.salary = new BigDecimal("1234.56");
// store it
persons.put("dady", dady);
// retrieve it
Person misterX = persons.get("dady");
// use it
System.out.println("MisterX: "+misterX.familyName);
}
You can use a Map where a person would be a Person class with the attributes you talked about and the key would be a String that identifies each Person entity.
Then, you could just do something like:
Map<String,Person> peopleMap = new Map<String,Person>();
Person person = new Person(); //let's imagine this person has a string id attribute with a get method defined
peopleMap.put(person.getId(),person); //adds the person to the list
peopleMap.get("p71"); //assume we're looking for a person which id="p71";
The person class could be something in these lines:
public class Person {
private String name;
private String id;
private int age;
public String getId() {
return this.id;
}
//other getter/setters and methods you implement
}
I have a class named Customer which stores the following objects:
private String CustomerFirstName
private String CustomerLastName
private String CustomerID
private String CustomerEmail
now in order to pass data to jasper report, I decided to create an array list which contains these objects, so :
import java.util.ArrayList;
import java.util.Collection;
/* This is CustomerDataSource.java file */
public class CustomerDataSource {
public static Collection<Customer> loadCustomers() throws Exception {
Collection<Customer> customers = new ArrayList<Customer>();
Customer customer = new customer (
/* I need help getting the objects CustomerFirstName / CustomerLastName and etc */
);
customer.addBilling(new Billing ( /* Adding billing info */ ));
customer.getBilling(new Billing ( /* I need to get the object's values*/));
customer.balOwing();
customers.add (customer);
return customers;
}
}
can someone please explain how to add the objects in Customer.java to the array list? (and in general since I need to add objects from different files as well. Thank you
So as I see your problem in your comment, you want to create a constructor.
In your Costumer class
public Costumer(String firstName, String lastName, String ID, String email) {
this.CostumerFirstName = firstName;
this.CostumerLastName = lastName;
this.CostumerID = ID;
this.CostumerEmail = email;
}
So then you can create a new costumer like that:
Customer customer = new Customer ("SampleFirstName","SampleLastName","0000","address#web.com");
You could even add the costumer automatically to the ArrayList by adding it in the constructor.
From your comment, I am guessing you would like to use a constructor?
You will have to add a constructor on your Customer.java.
public Customer(String firstName, String lastName, String id, String email){
this.CustomerFirstName = firstName;
this.CustomerLastName = lastName;
this.CustomerID = id;
this.CustomerEmail = email;
}
You might want to make getter/setter methods for access to above variables.
ArrayList<E>.get(i) performs virtually the exact same function as [] in static arrays. The only difference between the two is that ArrayList<E>.get(i) is simply adapted into the object context. In other words, you can dereference it.
First, you'll need to change the privacy of Customer's fields to public to give the ArrayList<Customers> object access to it.
Then you'll be able to retrieve your class' fields with simply:
customers.get(index).FirstName //or whatever other field