If I have an Employee class with a default constructor:
private String firstName;
public Employee(){}
and a setter:
public void setFirstName(String firstName){
this.firstName = firstName;
}
Why does this attempt fail to instantiate and call the setter in the same line?
Employee employee = new Employee().setFirstName("John");
You can also use this syntax:
Employee employee = new Employee() {{
setFirstName("John");
}};
Though keep in mind that it's going to create an anonymous inner class and probably isn't what you want.
Because setFirstName doesn't return anything. If you want to chain methods then setFirstName would have to return Employee.
Another approach is to have a constructor that takes firstName as an argument.
(employee = new Employee()).setFirstName("John");
performs instantiation and calling the setter, as you requested in the headline, but does not declare the variable as suggested in your code example.
(Employee employee = new Employee()).setFirstName("John");
will probably not work, I assume. But you can try.
Of course, you can always stuff multiple statements in one line.
Employee employee; (employee = new Employee()).setFirstName("John");
or
Employee employee = new Employee(); employee.setFirstName("John");
If I were you, I would settle for a parameterized constructor, though.
The method serFirstName is of return type void (nothing). Try:
public Employee setFirstName(String fname) {
this.firstName = fname;
return this;
}
It should be like this:
Employee employee = new Employee();
employee.setFirstName("John");
Although this is a bit overkill, you could try using the builder pattern
public class Employee{
private String firstName;
public static class Builder{
private String firstName;
public Builder firstName(String firstName){
this.firstName = firstName;
return this;
}
public Employee build(){
return new Employee(this);
}
}
private Employee(Builder builder){
firstName = builder.firstName;
}
}
Then you can do the following
Employee e = new Employee.Builder().firstName("John").build();
Because the you want to set employee to the value of .setFirstName("John"); which does not return anything because it is a void
So you could either change your setter to:
public Employee setFirstName(String fname) {
this.firstName = fname;
return this;
}
OR Create a second constructor for Employee
public Employee(String fname){this.firstName = fname;}
Which would set firstname on init.
In order for your code to work, you would have to return the Employee (meaning "this") in the setter method setFirstName.
If you don't own the Employee class (I know this is just a simple example - but for the sake of argument) and cannot modify it, one way to solve that is using functional programming. You could declare yourself a function like this:
static final Function<String, Employee> EMPLOYEE = firstName -> {
Employee employee = new Employee();
employee.setFirstName(firstName);
return employee;
};
And then you can create your employee in one line like this:
Employee jake = EMPLOYEE.apply("Jake");
Maybe not exactly what you want, but still useful.
Related
I am using JPA, and in my DB I have a table student with columns: id, firstname and firstAndLastname
So I did an Entity to mappe data, I can get lastname from another table, but I don't persist it as there is no columns lastname in DB.
How to store in column firstAndLastname that is concatenation of firstname and lastname and store it in specific column, example : firstname : John, lastname : Doe => firstAndLastname : JohnDoe
#Entity
#Table(name = "student")
public class Student implements Serializable {
#Id
#Column(name = "id")
private Integer id;
#Column(name = "firstname")
private String firstname;
#Transient
private String lastname;
#Column(name = "firstAndLastname")
private String firstLastname;
I tried this (and not working) :
public String getFirstLastname() {
return this.firstname+ this.lastname;
}
Any idea ?
Genetate getters/setter for all properties of the Entity.
Instantiate the object to save: Student student = new Student(1,"Mario","Rossi");
Call the setter : student.setFirstLastName(student.getFirstName()+student.getLastName());
myStudentService.save(student);.
If you still haven't figured out how to persist data to the database, that's where you need to start. You don't persist data in the JPA itself, that's just the structure for the object. You will build an instance of the Student object in another Class, set the values, and persist it to the database.
You would set that firstLastName value where/when you are creating an instance of your Student.
This is just a rough explanation. Not explicit code for you.
You would have a class like:
public class SaveStudentService {
public saveStudent(){
Student student = new Student();
student.setFirstName("test");
student.setLastName("lastTest");
student.setFirstLast(student.getFirstName + " "+ student.getLastName);
studentRepo.save(student);
}
}
You'll have your normal getters and setters in your Student class...
public Student getfirstName() {return this.firstName;}
public Student setfirstName(String firstName) {return this.firstName = firstName;}
public Student getfirstLast() {return this.firstLastName;}
public Student setfirstName(String firstLastName) {return this.firstLastName = firstLastName;}
I would recommend 2 approaches:
If you instantiate object by constructor:
public Student(final Integer id, final String firstname, final String lastname) {
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
this.firstLastname = String.join(firstname, lastname);
}
By setter:
public void setFirstLastname(final String firstName, final String lastName) {
this.firstLastname = String.join(firstName, lastName);
}
In addition you can also use Spring AOP and advice save method on your repository but it's less readable and more difficult to maintenance.
#Before("execution(* com.package.StudentRepository.save(..))")
public void updateFirstLastName(final JoinPoint joinPoint) {
final Object[] arguments = joinPoint.getArgs();
// find Student.class object and update firstLastName field
}
Either way - don't perform concatenation outside Student class because it leads to boilerplate and it's harder to maintenance.
But IMHO the best approach is to store firstName and lastName separately in database and use SQL CONCAT function if needed.
Probably a pretty noob question, but I cant figure it out. I have a class Person to store a name that is input from the keyboard
public class Person {
private String firstName;
private String lastName;
public Person()
{
firstName = "";
lastName = "";
}
public Person(String first, String last)
{
setName(first, last);
}
public String toString()
{
return(firstName + " " + lastName);
}
public void setName(String first, String last)
{
firstName = first;
lastName = last;
}
public String getFirstName()
{
return firstName;
}
public String getLastName()
{
return lastName;
}
}
I am trying to call the toString method in a subclass called Patient
public class Patient extends Person {
private int patientID, patientAge;
public Patient()
{
patientID = 0; //for a different part of the class that works
patientAge = 0;
}
#Override
public String toString()
{
return ("Patient Name: "+super.toString());
}
}
I cannot get it to output the name in main when I call the toString method from the Patient class, but when I tested it, it output the name when I call the toString method from the Person class.
The method call in main looks like Patient pnt = new Patient(); System.out.print(Pnt.toString());
it prints out in the console "Patient Name: ". Any feedback on what I am doing wrong or ideas on how to get it to work
Here:
public Person()
{
firstName = "";
lastName = "";
}
Your subclass is missing a reasonable call to a super class constructor. So when you instantiate your Patient objects, the above constructor is used, and all patients end up with "" as first and last name!
When you create a Patient, then a patient should have a name, too! But your constructor in Patient only sets the Patient related fields. And implicitly, the default super constructor is called. Therefore the Person fields are all set to be empty strings!
A much better approach would look like this:
class Person {
private final String firstName;
... lastName
public Person(String firstName, String lastName) {
this.firstName = firstName;
...
and then
class Patient extends Person {
private final int patientID;
public Patient(int patientID, String firstName, String lastName) {
super(firstName, lastName);
this.patientID = patientID;
)
Why is that better: names and IDs don't change (normally). There is no point in having getters for them. You create your object once, and then that data is fixed! There is also no point in having that default constructor in Person. A person with empty names doesn't make sense. Thus: don't create a class that allows you to create "invalid" objects. Your classes model reality. There are no real people without names!
And one other hint: use #Override when overriding methods, so that the compiler can tell you when you get something wrong!
if the problem is to output the name in main when you call the toString method from the Patient class, I think the code bellow will help you.
have you tried to construct the Patient object like this?
public static void main(String[] args) {
Patient p = new Patient();
System.out.println(p.toString());
}
Actually I do not see problem in your code.
Person person = new Person();
person.setName("aa", "bb");
System.out.println(person); // aa bb
Patient patient = new Patient();
patient.setName("cc", "dd");
System.out.println(patient); // Patient Name: cc dd
I think that you set name wrong pr use not correct reference. Check it.
You don't have any constructor for your PATIENT subclass. You don't set any firstName or lastName to any patient.
To keep familiar constructor as you used in your parent class, tru to use:
public Patient() {
super("default_firstName", "default_lastName");
this.patientID = 0;
this.patientAge = 0;
}
public Patient(String firstName, String lastName, int patientAge) {
super(firstName, lastName);
this.patientID = 0; //can be implemented some method for automatically setting numbers
this.patientAge = patientAge;
}
This way you always get firstName and lastName even if constructor will be called empty.
According to you toString method, it's correct and it call super class method:
#Override
public String toString()
{
return("Patient name is "+super.toString());
}
But notice that you return STRING value so to make it visible on the screen remember to use:
System.out.println(patient.toString());
Then it will be visible :)
I have added some comments and code in your Person class that should fix your issues.
public class Person {
private String firstName; //store the first name
private String lastName; //sore the last name
//initialize firstName and lastName to an empty string
public Person() {
firstName = "";
lastName = "";
}
//set firstname and lastname according to the parameters.
public Person(String first, String last) {
//setName(first, last); remove this crap.
// Use the contructor properly when initialize your person object. Like this:
this.firstName = first;
this.lastName = last;
}
//method to output the first name and last name
#Override
public String toString() {
return (firstName + " " + lastName);
}
//method to set firstName and lastName according to the paramters
public void setName(String first, String last) {
//
firstName = first;
lastName = last;
}
}
Im getting class name (string) and the class have few sets method and
since Its dynamic (I can get any class) I need to use all the sets method and update it with data .
how can I do that ?
To get the class field I'm using the following code
className = obj.getClassName();
Class<?> classHandle = Class.forName(className);
for example here I need to update firstName and last name
public class Person {
private String id;
private String firstName;
private String lastName;
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setfirstName(String firstName) {
this.firstName = firstName;
}
or different class here i need to set the salary and the job description
public class Job {
private double salery;
private String jobDescr;
public void setSalery(double salery) {
this.salery = salery;
}
public void setJobDescr(String jobDescr) {
this.jobDescr = jobDescr;
}
}
For starters, What you've done is good. I assume you have a Map<String, Object> of the attributes to be set: attributeMap.
//this is OK
className = obj.getClassName();
Class<?> classHandle = Class.forName(className);
//got the class, create an instance - no-args constructor needed!
Object myObject = classHandle.newInstance();
//iterate through all the methods declared by the class
for(Method method : classHandle.getMethods()) {
//check method name
if(method.getName().matches("set[A-Z].*")
//check if it awaits for exactly one parameter
&& method.getParameterTypes().length==1) {
String attributeName = getAttributeName(method.getName());
//getAttributeName would chop the "set", and lowercase the first char of the name of the method (left out for clarity)
//To be extra nice, type checks could be inserted here...
method.invoke(myObject, attributeMap.get(attributeName));
}
}
Of course, a lot of exception handling is to be done, this is just a basic idea of what is to be done...
Recommended reading:
Class
Class.getMethods()
Method
Method.invoke()
If I have an Employee class with a default constructor:
private String firstName;
public Employee(){}
and a setter:
public void setFirstName(String firstName){
this.firstName = firstName;
}
Why does this attempt fail to instantiate and call the setter in the same line?
Employee employee = new Employee().setFirstName("John");
You can also use this syntax:
Employee employee = new Employee() {{
setFirstName("John");
}};
Though keep in mind that it's going to create an anonymous inner class and probably isn't what you want.
Because setFirstName doesn't return anything. If you want to chain methods then setFirstName would have to return Employee.
Another approach is to have a constructor that takes firstName as an argument.
(employee = new Employee()).setFirstName("John");
performs instantiation and calling the setter, as you requested in the headline, but does not declare the variable as suggested in your code example.
(Employee employee = new Employee()).setFirstName("John");
will probably not work, I assume. But you can try.
Of course, you can always stuff multiple statements in one line.
Employee employee; (employee = new Employee()).setFirstName("John");
or
Employee employee = new Employee(); employee.setFirstName("John");
If I were you, I would settle for a parameterized constructor, though.
The method serFirstName is of return type void (nothing). Try:
public Employee setFirstName(String fname) {
this.firstName = fname;
return this;
}
It should be like this:
Employee employee = new Employee();
employee.setFirstName("John");
Although this is a bit overkill, you could try using the builder pattern
public class Employee{
private String firstName;
public static class Builder{
private String firstName;
public Builder firstName(String firstName){
this.firstName = firstName;
return this;
}
public Employee build(){
return new Employee(this);
}
}
private Employee(Builder builder){
firstName = builder.firstName;
}
}
Then you can do the following
Employee e = new Employee.Builder().firstName("John").build();
Because the you want to set employee to the value of .setFirstName("John"); which does not return anything because it is a void
So you could either change your setter to:
public Employee setFirstName(String fname) {
this.firstName = fname;
return this;
}
OR Create a second constructor for Employee
public Employee(String fname){this.firstName = fname;}
Which would set firstname on init.
In order for your code to work, you would have to return the Employee (meaning "this") in the setter method setFirstName.
If you don't own the Employee class (I know this is just a simple example - but for the sake of argument) and cannot modify it, one way to solve that is using functional programming. You could declare yourself a function like this:
static final Function<String, Employee> EMPLOYEE = firstName -> {
Employee employee = new Employee();
employee.setFirstName(firstName);
return employee;
};
And then you can create your employee in one line like this:
Employee jake = EMPLOYEE.apply("Jake");
Maybe not exactly what you want, but still useful.
what are possibilities of creating immutable bean in Java. For example I have immutable class Person. What's a good way to create instance and fill private fields. Public constructor doesn't seems good to me because of a lot input parameters will occure as class will grow in rest of application. Thank you for any suggestions.
public class Person {
private String firstName;
private String lastName;
private List<Address> addresses;
private List<Phone> phones;
public List<Address> getAddresses() {
return Collections.unmodifiableList(addresses);
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public List<Phone> getPhones() {
return Collections.unmodifiableList(phones);
}
}
EDIT: Specify question more precisely.
You could use the builder pattern.
public class PersonBuilder {
private String firstName;
// and others...
public PersonBuilder() {
// no arguments necessary for the builder
}
public PersonBuilder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Person build() {
// here (or in the Person constructor) you could validate the data
return new Person(firstName, ...);
}
}
You can then use it like this:
Person p = new PersonBuilder.firstName("Foo").build();
At first sight it might look more complex than a simple constructor with tons of parameters (and it probably is), but there are a few significant advantages:
You don't need to specify values that you want to keep at the default values
You can extend the Person class and the builder without having to declare multiple constructors or needing to rewrite every code that creates a Person: simply add methods to the builder, if someone doesn't call them, it doesn't matter.
You could pass around the builder object to allow different pieces of code to set different parameters of the Person.
You can use the builder to create multiple similar Person objects, which can be useful for unit tests, for example:
PersonBuilder builder = new PersonBuilder().firstName("Foo").addAddress(new Address(...));
Person fooBar = builder.lastName("Bar").build();
Person fooBaz = builder.lastName("Baz").build();
assertFalse(fooBar.equals(fooBaz));
You should have a look at the builder pattern.
One good solution is to make your fields final, add your constructor private and make use of Builders in your code.
In our project we combined the Builder pattern with a validation framework so that once an object is created we are sure it's immutable and valid.
Here is a quick example:
public class Person {
public static class Builder {
private String firstName;
private String lastName;
private final List<String> addresses = new ArrayList<String>();
private final List<String> phones = new ArrayList<String>();
public Person create() {
return new Person(firstName, lastName, addresses, phones);
}
public Builder setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder setLastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder addAddresse(String adr) {
if (adr != null) {
addresses.add(adr);
}
return this;
}
public Builder addPhone(String phone) {
if (phone != null) {
phones.add(phone);
}
return this;
}
}
// ************************ end of static declarations **********************
private final String firstName;
private final String lastName;
private final List<String> addresses;
private final List<String> phones;
private Person(String firstName, String lastName, List<String> addresses, List<String> phones) {
this.firstName = firstName;
this.lastName = lastName;
this.addresses = addresses;
this.phones = phones;
}
public List<String> getAddresses() {
return Collections.unmodifiableList(addresses);
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public List<String> getPhones() {
return Collections.unmodifiableList(phones);
}
}
In my example you can see that all the setters in the Builder return the Builder instance so that you can easily chain the setters calls. That's pretty useful.
You could take a look at the Builder pattern presented by Joshua Bloch.
As I said before, combined with a validation framework (see for ex. http://www.hibernate.org/subprojects/validator.html) this is really powerfull.
With interfaces. Do this:
public interface Person {
String getFirstName();
String getLastName();
// [...]
}
And your implementation:
// PersonImpl is package private, in the same package as the Factory
class PersonImpl {
String getFirstName();
void setFirstName(String s);
String getLastName();
void setLastName(String s);
// [...]
}
// The factory is the only authority to create PersonImpl
public class Factory {
public static Person createPerson() {
PersonImpl result = new PersonImpl();
// [ do initialisation here ]
return result;
}
}
And never expose the implementation to the places where you want Person to be immutable.
Initializing in the constructor is nevertheless the simplest and safest way to achieve immutability, as this is the only way to have final fields in your immutable class (which is the standard idiom, and has beneficial effects especially if your class is used in a multithreaded environment). If you have lots of properties in your class, it may be a sign that it is trying to do too much. Consider dividing it to smaller classes, or extracting groups of related properties into compound property classes.
Using a Builder (with a private constructor) is a possibility, however it still needs a way to set the properties of the object being built. So you fall back to the original dilemma of constructor parameters vs accessing the private members. In the latter case you can't declare the properties of the object being built as final, which IMHO is a great minus. And in the former case you still have the same long list of constructor parameters you wanted to avoid in the first place. Just now with a lot of extra boilerplate code on top of it.
You can achieve an "immutable" bean by making a read-only interface and then making the implementation into a mutable bean. Passing around the interface won't allow for mutation, but when you construct the object and have the implementation, you can do all sorts of bean-y things:
public interface Person {
String getFirstName();
String getLastName();
// ... other immutable methods ...
}
public class MutablePerson implements Person {
// ... mutable functions, state goes here ...
}
Use the factory-pattern:
let Person be an interface with only "get"-functions
create a PersonFactory with an appropriate API for building a Person-object
the PersonFactory creates an object which implements the Person-interface and returns this
Have final fields.
Make the class as "final" class by declaring as final public class Person
do not use setXXX() methods to set the value since it will change the state of a variable. however getXXX() methods are allowed.
Use a private constructor so that you can set fields using the constructor itself.
Follow the above guidelines for Immutable class.
Use final fields for all your instance variables. You can create a constructor if you like and choose to not expose setters, e.g.,
public class Person {
private final String firstName;
....
public Person(String firstName, ... ) {
this.firstName = firstName;
}
}