cant get the value passed while creating object in constructor - java

import java.util.Scanner;
Here I'm trying to throw custom exception if the lastName is empty/null, so I have created a constructor which accepts two string arguments and the value is passed while the object is created, but the problem is it's always null in the constructor. Seems like the value is not being passed. What am I doing wrong here? Any alternate solution or explain please. Thanks (Sorry for bad English).
public class Employee {
private String firstName;
private String lastName;
public Employee(String firstName,String lastName) {//here the value is always null and so throwing exception.
try {
if(this.firstName==null||this.lastName==null) {
throw new FirstnameOrLastnameNotFound("Both first and last name must not be empty");
}
}
catch(FirstnameOrLastnameNotFound e) {
System.out.println(e);
System.exit(1);
}
this.firstName=firstName;
this.lastName=lastName;
}
public void display() {
System.out.println("Name of the employee: " + this.firstName+" "+ this.lastName);
}
public static void main(String[] args) {
//Scanner sc= new Scanner(System.in);
//System.out.println("Enter the first name:");
//String firstNameAndLastName=sc.nextLine();
//String[]name=firstNameAndLastName.split(" ");
Employee obj= new Employee("dummy", "dummy");//this dummy sting is not passing in constructor.
obj.display();
}
}

Your problem is that you are testing the value of the class members firstName and lastName before you are assigning them values.
You want to test whether the constructor parameters are null, so just remove this..
Here is your corrected code.
public class Employee {
private String firstName;
private String lastName;
public Employee(String firstName, String lastName) {
try {
if (firstName == null || lastName == null) { // CHANGE HERE
throw new FirstnameOrLastnameNotFound("Both first and last name must not be empty");
}
}
catch (FirstnameOrLastnameNotFound e) {
System.out.println(e);
System.exit(1);
}
this.firstName = firstName;
this.lastName = lastName;
}
public void display() {
System.out.println("Name of the employee: " + this.firstName + " " + this.lastName);
}
public static void main(String[] args) {
Employee obj = new Employee("dummy", "dummy");
obj.display();
}
}
You also wrote in your comment that it works when you remove this.
Note though, that your fix will throw NullPointerException if you call the constructor with null argument, for example:
Employee obj = new Employee(null, "dummy");
If null or empty names are not allowed, then your check should be as follows:
if (firstName == null || firstName.isEmpty() || lastName == null || lastName.isEmpty()) {
throw new FirstnameOrLastnameNotFound("Both first and last name must not be empty");
}
The idea behind throwing an exception is to indicate to the invoking code that the invoked method failed. You usually don't throw an exception and handle it in the same method. You should declare that the constructor throws FirstnameOrLastnameNotFound and put the try-catch in method main as below:
public class Employee {
private String firstName;
private String lastName;
public Employee(String firstName, String lastName) throws FirstnameOrLastnameNotFound {
if (firstName == null || firstName.isEmpty() || lastName == null || lastName.isEmpty()) {
throw new FirstnameOrLastnameNotFound("Both first and last name must not be empty");
}
this.firstName = firstName;
this.lastName = lastName;
}
public void display() {
System.out.println("Name of the employee: " + this.firstName + " " + this.lastName);
}
public static void main(String[] args) {
try {
Employee obj = new Employee("dummy", "dummy");
obj.display();
}
catch (FirstnameOrLastnameNotFound e) {
System.out.println(e);
System.exit(1);
}
}
}

Related

Most Efficient Way to Initialize Java Fields that are Objects?

Say I have a class like so:
public class ManyFields {
public Object1 object1;
public Object2 object2;
public Object3 object3;
// etc.
}
I want to make sure these fields are not null upon trying to do anything with a ManyFieldsobject. So perhaps I'd have a validation method like so:
public Object ensureNotNull(Object o) {
if (o.object1 != null) o.object1 = new Object1();
// and so on and so forth
return o;
}
Is there a better, but also performant, approach here? Rather than checking if each field is null individually? I did explore reflection like so:
for (Field f : fields) {
try {
if (f.get(c) == null) {
f.set(c, f.getType().newInstance());
}
} catch (Exception e) {
e.printStackTrace();
}
}
However, I've read this reflection isn't the most performant-friendly approach to initializing fields. Any suggestions would help? Thanks.
Reflection is the worst and slowest way to do almost anything.
What you want is to encapsulate your fields: make them private, so your class has total control over how they get changed.
If there aren’t too many of them, you can make them all final and have the constructor set them:
public class Person {
private final String firstName;
private final String lastName;
public Person(String firstName,
String lastName) {
this.firstName = Objects.requireNonNull(firstName,
"First name cannot be null.");
this.lastName = Objects.requireNonNull(lastName,
"Last name cannot be null.");
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
With this approach, it is completely impossible for outside code to set the fields to null values.¹ If a caller passes null, the constructor never completes, so there can never be an existing instance of Person which has a field with a null value. Which means you can make a written guarantee that callers will never have to check if the values are null:
/**
* Returns this user's first name. This value will never be null.
*/
public String getFirstName() {
return firstName;
}
/**
* Returns this user's last name. This value will never be null.
*/
public String getLastName() {
return lastName;
}
You can even take it a step farther, and validate the values beyond just checking for null:
public Person(String firstName,
String lastName) {
this.firstName = Objects.requireNonNull(firstName,
"First name cannot be null.");
this.lastName = Objects.requireNonNull(lastName,
"Last name cannot be null.");
if (firstName.isBlank()) {
throw new IllegalArgumentException("First name cannot be blank.");
}
if (lastName.isBlank()) {
throw new IllegalArgumentException("Last name cannot be blank.");
}
}
If you have many fields, you can just use get-methods and set-methods instead of setting everything in the constructor. In that case, it is useful to initialize each field to a non-null value, so the class is able to make the same non-null guarantee as with the constructor approach:
public class Person {
private String firstName = "(unknown)";
private String lastName = "(unknown)";
private String socialSecurityNumber = "000-00-0000";
private LocalDate dateOfBirth = LocalDate.MAX;
public String getFirstName() {
return firstName;
}
public String setFirstName(String name) {
this.firstName = Objects.requireNonNull(name,
"Name cannot be null.");
}
public String getLastName() {
return lastName;
}
public String setLastName(String name) {
this.lastName = Objects.requireNonNull(name,
"Name cannot be null.");
}
public String getSocialSecurityNumber() {
return socialSecurityNumber;
}
public void setSocialSecuityNumber(String num) {
Objects.requireNonNull(num, "Argument cannot be null.");
if (!num.matches("\\d{3}-\\d{2}-\\d{4}")) {
throw new IllegalArgumentException(
"Argument must be in the format nnn-nn-nnnn.");
}
this.socialSecurityNumber = num;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(LocalDate date) {
Objects.requireNonNull(date, "Date cannot be null.");
int age = date.getYear() - LocalDate.now().getYear();
if (age > 150) {
throw new IllegalArgumentException(
"Invalid date: no one is more than 150 years old.");
}
if (age < 0) {
throw new IllegalArgumentException(
"Invalid date: cannot be born in the future.");
}
this.dateOfBirth = date;
}
}
1. It is technically possible for outside code to use reflection’s setAccessible method to hack the private members of a class that is not in a module, unless a SecurityManager is installed. However, people who hack into things in this manner should expect the class to break in unexpected ways, as they are essentially “voiding the warranty.” Meaning, it’s bad and no one should do it, and in fact later versions of Java won’t let them do it.

Calling superclass in main method

I've just learned about superclasses and subclasses and the homework is pretty simple: have 2 classes and a test class to call and print the attributes. Below is my code from all 3 classes. My question is, why isn't the department attributes printing in my main? Everything else prints just fine, I just can't get that last little bit to print. I think it has something to do with super...thank you in advance! Second computer course and I'm finally feeling I sort of get it, so that's improvement from the first class I took!
public class Employee {
private String firstName;
private String lastName;
private int employeeID;
private double salary;
public Employee () {
firstName = null;
lastName = null;
employeeID = 0;
salary = 0.00;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getEmployeeID() {
return employeeID;
}
public double getSalary() {
return salary;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setEmployeeID(int employeeID) {
this.employeeID = employeeID;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String employeeSummary () {
String employeeSummary = "Employee's name is: " + getFirstName() + " " + getLastName() +
". The employee's ID number is " + getEmployeeID() +
". The employee's salary is " + getSalary();
System.out.println(employeeSummary);
return employeeSummary;
}
}
public class Manager extends Employee {
private String departmentA;
public Manager() {
super();
departmentA = null;
}
public String getDepartmentA() {
return departmentA;
}
public void setDepartmentA(String departmentA) {
this.departmentA = departmentA;
}
public void EmployeeSummary() {
super.employeeSummary();
System.out.println("The employee's department is " + departmentA);
}
}
public class ManagerDerivation {
public static void main(String[] args) {
Manager person = new Manager();
person.setFirstName("Ron");
person.setLastName("Weasley");
person.setEmployeeID(2345);
person.setSalary(65000.00);
person.setDepartmentA("Department of Magical Law Enforcement");
person.employeeSummary();
return;
}
}
Method names are case sensitive. EmployeeSummary() does not override employeeSummary() because it uses a different name.
To avoid mistakes like this, always include the #Override annotation on overridden methods. If you include that annotation and make a mistake in the method signature, compilation will fail.
Note also that your return types for the two methods are different (String and void). Overridden methods must have compatible return types.
There is some spelling (employeeSummary vs. EmployeeSummary) mistakes and return types dont match, in Employee should be
public void employeeSummary () {
String employeeSummary = "Employee's name is: " + getFirstName() + " " +
getLastName() +
". The employee's ID number is " + getEmployeeID() +
". The employee's salary is " + getSalary();
System.out.println(employeeSummary);
}
then in Manager
public void employeeSummary() {
super.employeeSummary();
System.out.println("The employee's department is " + departmentA);
}

Java ~ User by user

I would like the user to provide data by scanner and add it to list. Later, I want to get the size of this list and for example user name, last name. I'm still trying to work with constructors and exceptions and now I want to try to put data from user.
It's Human Service which checks constructors, and if the name has less than 3 letters and lastname less than 5 letters will throw an exception.
import java.util.ArrayList;
import java.util.List;
public class HumanService {
List<Human> humans;
public HumanService() {
humans = new ArrayList<>();
}
public void addHuman(String name, String lastName) throws HumanNameWrongFormat, HumanLastNameWrongFormat {
if(HumanValidator.humanValidatorName(name) && HumanValidator.humanValidatorLastName(lastName)) {
Human human = new Human(sizeOfList(), name, lastName);
humans.add(human);
}
}
public int sizeOfList() {
return humans.size();
}
public Human getHumanByLastName(String lastName) throws HumanNotFoundException {
for (Human human : humans) {
if (human.getLastName().equals(lastName)) {
return human;
}
}
throw new HumanNotFoundException(lastName + " not found");
}
public Human getHumanById (Integer id) throws HumanNotFoundException {
for (Human human : humans) {
if (human.getId().equals(id)) {
return human;
}
}
throw new HumanNotFoundException(id + " not found");
}
}
I want to get data by user to list.
For example.
Please give me your name and last name.
Here is your name and last name by scanner and that will be added to list and checked.
This is also my main class.
public class main {
public static void main(String[] args) throws HumanNotFoundException {
HumanService humanService = new HumanService();
try {
humanService.addHuman("John", "Walker");
humanService.addHuman("Steve", "Williams");
humanService.addHuman("Gregor", "Wroten");
}
catch (HumanNameWrongFormat | HumanLastNameWrongFormat e) {
System.out.println(e.getMessage());
}
System.out.println(humanService.sizeOfList());
try {
humanService.getHumanByLastName("Wroten");
}
catch (HumanNotFoundException e) {
System.out.println(e.getMessage());
}
}
}
Here is the way you can use Scanner to get all the required user names and add them to the list for further processing
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<Human> humans = new ArrayList();
while (true) {
System.out.println("Please give your first name");
String firstName = scanner.nextLine();
System.out.println("Please give your last name");
String lastName = scanner.nextLine();
humans.add(new Human(firstName, lastName)); // use your humanService here
boolean breakOut = false;
String input;
do {
System.out.println("Do you want to enter more names? (Y/N)");
input = scanner.nextLine();
if (input.equalsIgnoreCase("Y") || input.equalsIgnoreCase("N")) {
breakOut = true;
} else {
System.out.println("Invalid input. try again");
}
} while (!breakOut);
if (input.equalsIgnoreCase("Y")) {
break;
}
}
System.out.println(humans);
}
}
I am assuming you have two fields firstName, lastName in Human
class Human {
private String firstName;
private String lastName;
public Human(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public String toString() {
return "first name " + firstName + " and last name " + lastName;
}
}
Input:
Please give your first name
John
Please give your last name
Smith
Do you want to enter more names? (Y/N)
y
Please give your first name
Will
Please give your last name
Smith
Do you want to enter more names? (Y/N)
n
Output:
[first name John and last name Smith, first name Will and last name Smith]
In the above code, replace the list with your humanService to add the humans

OOP parsing and adding object to list

So, I have three classes where the Class1 is used for different objects. In main class, the Class1 objects are made and names are set. Main class also makes new Household objects, the names are given to households and finally, persons are added to households as follows:
HouseholdOne.addPeopleToHousehold(person1);
The main class does not concern in present problem.
public class Class1 {
private String firstName;
private String middleName;
private String lastName;
public String setFirstName(String firstName) {
return this.firstName = firstName;
}
public String setLastName(String lastName) {
return this.lastName = lastName;
}
public String setMiddleName(String middleName) {
return this.middleName = middleName;
}
public String toString() {
if(firstName == "" && middleName == "" && lastName == "") {
return "";
} else if (firstName == null && middleName == null && lastName == null) {
return null;
} else
return firstName + " \"" + middleName + "\" " + lastName;
}
}
In the second class Household "addPeopleToHousehold" method the middle name of person should be parsed out from parameter and added to people list.
I had in mind to use .split function, but it does not work with object parameter.
How can I get given person middle name and
peopleList.add(personMiddleName)
Also in Household class, toString should print out household members like:
member1, member2, ... , memberx
public class Household {
List<Class1> peopleList = new ArrayList<>();
public String householdName;
public String setHouseholdName(String householdName) {
return this.householdName = householdName;
}
public void addPeopleToHousehold(Class1 people) {
// implementation needed //
}
public int getNumberOfPeople() {
return people.size();
}
public String toString() {
if (householdName == null || householdName == "") {
return "" + people;
}
return householdName + ": " + people;
}
}
Something like this perhaps? It was difficult to decipher your post, but the signature from the various methods says a lot. My changes simply adds people do the ArrayList peopleList. When you print the Household it will first check if a valid household name exists, after that it will loop each individual in the Household and add their full name to the list. The ((i + 1) != peopleList.size()) is only used to separate the names with a , except the last name.
Updated Class1. Fixed the setters and added a public getter for middle name.
public class Class1 {
private String firstName;
private String middleName;
private String lastName;
/*
* Setters
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
/*
* Getters
*/
public String getMiddleName() {
return middleName;
}
/*
* toString
*/
public String toString() {
if(firstName == "" && middleName == "" && lastName == "") {
return "";
} else if (firstName == null && middleName == null && lastName == null) {
return null;
} else
return firstName + " \"" + middleName + "\" " + lastName;
}
}
Updated Household class. Various fixes:
public class Household {
List<Class1> peopleList = new ArrayList<>();
public String householdName;
public String setHouseholdName(String householdName) {
this.householdName = householdName;
}
public void addPeopleToHousehold(Class1 people) {
peopleList.add(people);
}
public int getNumberOfPeople() {
return peopleList.size();
}
public String toString() {
String returnString = "";
if (householdName != null) {
returnString = householdName + ": ";
}
// Loop the members
for (int i = 0; i < peopleList.size(); i++) {
returnString += peopleList.get(i).getMiddleName();
if ((i + 1) != peopleList.size()) {
returnString += ", ";
}
}
return returnString;
}
}
In addition to the answer of OptimusCrime, you might want to use StringBuilder instead of just using returnString += to append strings.
The drawback of using += to append strings is it will create new String objects whenever you append, so you will have greater memory consumption.

Object creation across multiple files (Java)

so I have 2 files called Employee.java and Write.java (These two are within the same package). Say within Employee.java I have
public class Employee {
private String firstName = "test";
private String lastName = "ing";
public Employee(String first, String last) {
firstName = first;
lastName = last;
}
public Employee(Employee copy) {
firstName = copy.firstName;
lastName = copy.lastName;
}
}
Then within my Write.java I want to create an object of type Employee called temp. Like
public void obtainInfo(Employee temp) {
String firstName = temp.firstName;
String lastName = temp.lastName;
}
However I get an error that tells me that it cannot find the symbol in the line that is.
public void obtainInfo(Employee temp) {
I was just wondering where I went wrong that I can't create an object within different files. Despite them being in the same package I can't access them?
I want to be able to incorporate this later on to help me build a text file from reading an array list, but I figured to first start with reading a single line from an object.
It sounds to me that you are trying to set something up so that you can make a copy of an Employee and be able to write the properties to a text file. This won't write to a text file but I think it may clear some things up for you.
public class Employee {
private String firstName;
private String lastName;
public Employee(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Employee(Employee copy) {
firstName = copy.firstName;
lastName = copy.lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Employee");
sb.append("{firstName='").append(firstName).append('\'');
sb.append(", lastName='").append(lastName).append('\'');
sb.append('}');
return sb.toString();
}
}
TestClass.java
public class TestClass {
public static void main(String[] args){
//First we have to have one to copy
Employee emp = new Employee("Joe", "Dirt");
//Now we have a copy
Employee emp2 = new Employee(emp);
//Calls the Employee.toString() method and sends it to System.out
System.out.println("Employee 1 : " + emp);
System.out.println("Copy of Employee 1 : " + emp2);
}
}
Make sure that Write.java's class has the same level of access as Employee (IE: Public). If this is not the issue, I would show the code from Write.java specifically as that is most likely where the problem is coming from.

Categories