I'm working on this lab where I'm creating a hypothetical disaster management system for people to put information about disasters with Java. Within the code, there are two classes with the same name User. The tutorial for the lab says that line 75 with user u2 is supposed to use an Emergency Contact class by using the following code:
User u2 = new User("Marlena", "Evans","6088861222", "me#daysofourlives.com");
However, with this, the console brings up this error:
'User(java.lang.String, java.lang.String, java.lang.String, java.lang.String)' in 'User' cannot be applied to '(java.lang.String, java.lang.String, boolean, int, java.lang.String, java.lang.String)'
so I changed it to:
User u2 = new User("Marlena", "Evans", false, 30, "6088861222","me#daysofourlives.com");
which removed the error.
I need a fresh set of eyes on this. Can someone look at this and tell me why the tutorial's code isn't working?
Here is what the code is supposed to look like:
and here is my code:
//import java.sql.Timestamp (package already active)
public class User {
private String firstName;
private String lastName;
private boolean gender; //true - male; false - female
private int age;
private BloodType blood;
private String telephone;
private String email;
private User emergencyContact;
public void setContact(User u){
this.emergencyContact = u;
}
public User (
String firstName,
String lastName,
boolean gender,
int age,
String blood,
String telephone,
String email
) {
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.age = age;
this.blood = BloodType.fromString(blood);
this.telephone = telephone;
this.email = email;
}
public String getFirstName(){
return this.firstName;
}
public String getLastName(){
return this.lastName;
}
public boolean getGender(){
return this.gender;
}
public int getAge() {
return this.age;
}
public String getTelephone(){
return this.telephone;
}
public String getEmail() {
return this.email;
}
public BloodType getBlood() {
return this.blood;
}
public User getEmergencyContact() {
return this.emergencyContact;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO
//Here is an example of using the new user constructor
User u1 = new User("John","Black",true,25, "6085551234","jb#daysof" +
"ourlives.com");
//This example uses the Emergency Contact Constructor to create a new emergency contact
User u2 = new User("Marlena", "Evans", false, 30, "6088861222","me#daysofourlives.com");
u1.setContact(u2); //This means Marlena is the Emergency Contact for John
System.out.println("User: " + u1.firstName + " has an emergency contact of: " + u1.emergencyContact.getFirstName());
}
public User (
String firstName,
String lastName,
boolean gender,
int age,
String telephone,
String email
){
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.age = age;
this.email = email;
}
}
Thank you and as always, let me know if you need more context to help me.
You are missing an additional constructor with the reduced number of arguments that constructor call in line 75 is using.
Add this to your User class:
public User(String firstName, String lastName, String telephone, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.telephone = telephone;
this.email = email;
}
Also, in the main class, you are accessing firstName and emergencyContact fields, but these are private fields, so either set them to public or add a setter method.
Related
I created a User class with a Builder Pattern for the purpose of serializing it to a JSON String for POST. Now, the requirements have changed and I need the ability to PATCH an existing record, updating one or more fields but not all fields in a recordset. The example below has 5 fields in its User class but imagine if it had 30 or even 40 fields including the int type.
import com.google.gson.*;
class User
{
//All final attributes
private final String firstName;
private final String lastName;
private final int age;
private final String phone;
private final String address;
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//All getter, and NO setter to provide immutability
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
public String getAddress() {
return address;
}
public static class UserBuilder
{
private String firstName;
private String lastName;
private int age;
private String phone;
private String address;
public UserBuilder() {
}
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public UserBuilder lastName(String lastName) {
this.firstName = lastName;
return this;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
//Return the finally consrcuted User object
public User build() {
User user = new User(this);
return user;
}
}
}
public class TestUserBuild {
public static void main(String[] args) {
// TODO Auto-generated method stub
User user = new User.UserBuilder().
//No last name
//No age
//No phone
//no address
.firstName("Super")
.build();
System.out.println(user); // User: Super, null, 0, null, null
Gson gson = new Gson();
System.out.println(gson.toJson(user)); // {"firstName":"Super","age":0}
}
}
I didn't specify the age and, yet, there it is in the JSON string. I thought the builder pattern would facilitate creating any number of JSON string permutations, i.e. update the first name and last name, update the first name only, update the age only, update last name and phone number only, etc...
Is the builder pattern approach not the correct solution for this problem? If it is an acceptable solution, how can I leverage the builder pattern to serialize the User class to a JSON string but with only the fields of my choosing? Is there something I can leverage in the Gson library to realize this task such as creating a custom type adapter? Maybe I can create a custom type adapter that takes all field as inputs, checks if each one is NULL, or 0 for Integers, and then build the JSON string with just the deltas.
Your "age" field is worth 0 because "int" has a default value. Use "Integer" if you want the age field to default to null.
Some of the advantages of the Builder pattern are immutability (you can choose to allow a class to be modified only at creation time by the builder, removing all setters from the class), and that it's more concise for instantiating a class with multiple attributes.
But you don't need to keep your Builder pattern immutable. If I understand your need correctly, you could keep the builder pattern for versatility during object creation, and keep the setters on the class to be able to update fields easily.
import com.google.gson.*;
class User {
//Your attributes don't need to be final
private String firstName;
private String lastName;
private int age;
private String phone;
private String address;
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//getters AND setters (omitted for brevity)
//builder class stays as is, omitted for brevity
public class TestUserBuild {
public static void main(String[] args) {
User user = new User.UserBuilder()
.firstName("Super")
.build();
//when you need to update
user.setAge(42);
}
}
The question is, why do you want immutability if you need to update fields periodically? Should you remove the immutability constraint altogether (by leaving setters in the class)? Do you need to be able to update specific combinations of fields according to particular business rules? If the latter is true, I would recommend moving away from an anemic model (a "bag of getters and setters") and adding domain-specific methods which take care of updating the relevant fields. Your User class would then look like this:
class User {
//Your attributes don't need to be final
private String firstName;
private String lastName;
private int age;
private String phone;
private String address;
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//getters ONLY (omitted for brevity)
//no setters, only domain-relevant methods which update fields as needed
public void setIdentity(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void setCoordinates(String phone, String address) {
this.phone = phone;
this.address = address;
}
}
//builder class stays as is
public class TestUserBuild {
public static void main(String[] args) {
User user = new User.UserBuilder()
.firstName("Super")
.build();
//update identity (say, your frontend has an "identity" page with only firstName and lastName on it
user.setIdentity("Chris", "Neve");
//your frontend page allowing user to update coordinates
user.setCoordinates("+331231231", "7th av, NYC");
}
}
I am fairly new to Java. I am getting an error "The constructor Family(String, String, int) is undefined". Im not sure what this means. Need a bit of help here please.
EDIT: I was missing the extra 3 parameters and also was missing quotes around 31.
Main.java
public class Main {
public static void main(String[] args){
Family person = new Family("CHRIS", "PEREZ", 31);
String person1 = person.getPerson();
System.out.println(person1);
}
}
Family.java
public class Family {
String firstName;
String lastName;
int age;
int phoneNumber;
String dob;
String married;
public Family(String firstName, String lastName, int age, int phoneNumber,
String dob, String married) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.phoneNumber = phoneNumber;
this.dob = dob;
this.married = married;
public String getPerson() {
return ("Hi my name is"+this.firstName+" "+ this.lastName+"."+"I am "+this.age+" years old.");
}
}
This is because your Family class only has a six-argument constructor requiring all of the six fields to be provided. Your call:
Family person = new Family("CHRIS", "PEREZ", 31);
only provides three of the six required. You could override the constructor, for instance:
public Family(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
...
}
but you should do something with the rest of the fields that you didn't provide here that you provide in the other constructor.
You're calling the Family class constructor like this:
Family person = new Family("CHRIS", "PEREZ", 31);
But the only constructor in the class is defined like this:
public Family(String firstName, String lastName, int age, int phoneNumber,
String dob, String married) {
See that it has more parameters than you're passing in: phoneNumber, dob, married. In Java you have to give values to all parameters:
Family person = new Family("CHRIS", "PEREZ", 31, 123456, "5/Apr/1975", "who's asking");
Or, you need to define a new constructor that needs only firstName, lastName and age.
How do you create a java object that uses a variable from another class, or calls the entire constructor?
For example, accountNumber, firstName, lastName, phone are all variables passed in address is comprised of street, city, state, and zip, and has already been created:
Address address = new Address(street, city, state, zip);
Data is comprised of only megabytes, and has already been created:
Data data = new Data(megabytes);
This is what I have for the customer object:
Customer customer = new Customer(accountNumber, firstName, lastName, address, phone, data);
This is supposed to be an "overloaded constructor", but I don't understand what that means.
This is the constructor I have so far:
public Customer(String accountNumber, String firstName, String lastName, Address address, int phone, Data megabytes)
{
this.accountNumber = accountNumber;
this.firstName = firstName;
this.lastName = lastName;
this.address = address;
this.phone = phone;
this.megabytes= megabytes;
}
I get the error:
The constructor Customer(String, String, String, Address, int, Data) is undefined
At a glance everything seems fine. I hoped you saved the file before compiling.
Since you mentioned that you didn't understand what an overloaded constructor is, I'll try my best to explain that.
An overloaded constructor has the same constructor name but it differs from other constructors in the following ways -
It has different number of formal arguments
The order of type of formal parameters of the constructor are different
Here is an example -
public class Customer {
private String firstName;
private String lastName;
private int phoneNumber;
public Customer() {
// default constructor
}
public Customer(String firstName) {
this.firstName = firstName;
}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Customer(String firstName, String lastName, int phoneNumber) {
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
}
public Customer(int phoneNumber, String firstName, String lastName) {
this.phoneNumber = phoneNumber;
this.firstName = firstName;
this.lastName = lastName;
}
// This is not an overloaded constructor as there is already a constructor of type
// Customer(String, String)
// public Customer(String lastName, String firstName) {
// this.lastName = lastName;
// this.firstName = firstName;
// }
}
When I test my google endpoints API in the api explorer, the saveProfile method throws the 503 Service Unavailable error, but all other methods work fine.
Here is the saveProfile method in my endpoint:
#ApiMethod(name = "saveProfile")
public Profile saveProfile(final ProfileForm profileForm) {
String firstName = profileForm.getFirstName();
String lastName = profileForm.getLastName();
String email = profileForm.getEmail();
Profile profile = new Profile("124234132", email, firstName, lastName);
ofy().save().entity(profile).now();
return profile;
}
Here is the Profile entity class:
#Entity
public class Profile {
#Id
private String userId;
private String email;
private String firstName;
private String lastName;
public Profile(String userId, String email, String firstName, String lastName) {
this.userId = userId;
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
}
}
Here is the profileForm class:
public class ProfileForm {
private String firstName;
private String lastName;
private String email;
public ProfileForm() {}
public ProfileForm(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
}
I have registered the entity and have set the API_EXPLORER_CLIENT_ID as well as the web and android client IDs.
Does somebody understand how to fix this so that the method just returns the profile object as it should?
In order for Profile to be serializable you need to define getters and setters for each of its fields (ex. getUserId(), setUserId(string Id)).
An Objectify entity must also include a no-arg constructor: https://github.com/objectify/objectify/wiki/Entities
Let me know if that fixes the error.
I'm doing a project with overloaded constructors in a class and I'm a little stuck, below is what I'm supposed to be doing with the overloaded constructors:
"One that allows first, middle, and last names to be passed as Strings with an int for age
One that accepts a Name object reference, and an age as an int
Make a new Name inside Person, copying the references for the parts of the name."
I'm not quite sure what to do with my code, here is what I got:
public class Person {
int age;
Name aPersonHasAName;
Name newPerson = new Name();
public Person(String firstName, String middleName, String lastName, int age) {
newPerson.firstName = firstName;
newPerson.middleName = middleName;
newPerson.lastName = lastName;
}
public Person(Name aPersonHasAName, int age) {
}
public void details() {
System.out.println(aPersonHasAName + " age: " + age);
}
}
I'm just lost as to what I'm supposed to be typing. I believe I've done the first overloaded constructor, but I am new to this.
So what should I be doing to make this work with overloaded constructors?
I think having the code from the other two classes might help.
Here is PersonTester:
public class PersonTester {
public static void main(String[] args) {
Person person1 = new Person("a1", "b1", "c1", 11);
Person person2 = new Person(new Name("a2", "b2", "c2"), 22);
Person person3 = new Person(new Name("a3", "c3"), 33);
Person person4 = new Person(new Name("a4"), 44);
Person person5 = new Person(new Name(), 55);
System.out.println(person1.details());
System.out.println(person2.details());
System.out.println(person3.details());
System.out.println(person4.details());
System.out.println(person5.details());
}
}
Then here is the Name class:
public class Name {
String firstName;
String middleName;
String lastName;
public Name(String firstName, String middleName, String lastName) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
public Name(String firstName, String lastName) {
this(firstName, "", lastName);
}
public Name(String firstName) {
this(firstName, "", "");
}
public Name() {
this("", "", "");
}
public String getLastName() {
return lastName;
}
public String getMiddleName() {
return middleName;
}
public String getFirstName() {
return firstName;
}
public String getFullName(String nameString) {
StringBuilder build = new StringBuilder();
build.append(nameString);
build.deleteCharAt(nameString.length() - 1);
build.insert(0, build.hashCode());
return build.toString();
}
}
The problem I am having now is the error message in PersonTester which is: The method println(boolean) in the type PrintStream is not applicable for the arguments (void)
I just need to know what in which class needs to be fixed to make it work.
I am very new to Java and object oriented programming.
So far so good. But eventually you'll reach a point where you duplicate a fair bit of code.
The constructor
public Person(String firstName, String middleName, String lastName, int age) {
is the most comprehensive one in the sense that it takes in all the possible data.
With the other constructors, say one that takes a last name and an age, you can use delegating constructors:
public Person(String lastName, int age) {
this(null, null, lastName, age); /*calls the other constructor*/
}
If you can't make such an assumption then you'll need to split up the name string by hand.
Updating your code:
public Person(String firstName, String middleName, String lastName, int age) {
newPerson.firstName = firstName;
newPerson.middleName =
newPerson.lastName = lastName;
this.age = age; //<---- was missing in your code
}
And your second contructor may look like this:
public Person(Name aPersonHasAName, int age) {
this.newPerson = aPersonHasAName;
this.age = age;
}
These contructors are implemented as you needed.
Notice that you already done your overloading, if you got multiple constructors with not the same titles you contructors overloading
public class Person {
int age;
Name aPersonHasAName;
public Person(String firstName, String middleName, String lastName, int age) {
aPersonHasAName = new Name();
aPersonHasAName.firstName = firstName;
aPersonHasAName.middleName = middleName;
aPersonHasAName.lastName = lastName;
this.age = age;
}
public Person(Name aPersonHasAName, int age) {
this.aPersonHasAName = aPersonHasAName;
this.age = age;
}
public void details() {
System.out.println(aPersonHasAName + " age: " + age);
}
}
I guess it also depends on if Name has a constructor for firstName, middleName, lastName