Java ArrayList StackOverFlowError - java

This is my first time asking a question so please be patient. I am working on a school assignment and have been battling a stackoverflow error that I do not know enough about to get to the bottom of. The errors are indicated by ~~~:
The sections of code from the stack trace are as follows:
public class Employee extends StaffMember {
public static final int DEFAULT_SIN = 123456789;
public static final double MINIMUM_WAGE = 400.00;
protected int socialInsuranceNumber = DEFAULT_SIN;;
protected double payRate = MINIMUM_WAGE;
/**
*
*/
public Employee() {
super();
}
/**
* #param name
* #param streetAddress
* #param phone
* #param socialInsuranceNumber
* #param payRate
*/
public Employee(String name, String address, String phone, int socialInsuranceNumber, double payRate) {
~~~ super(name, address, phone);
this.socialInsuranceNumber = socialInsuranceNumber;
this.payRate = payRate;
}
public abstract class StaffMember extends Staff {
public static final String DEFAULT_NAME = "Default Name";
public static final String DEFAULT_ADDRESS = "Default Address";
public static final String DEFAULT_PHONE = "Default Phone";
protected String name;
protected String address;
protected String phone;
/**
* default constructor
*/
public StaffMember() {
super();
}
/**
*
* #param name
* #param address
* #param phone
* abstract class can not be instantiated therefore should not
* have constructors
*/
~~~ public StaffMember(String name, String address, String phone) {
super();
this.name = name;
this.address = address;
this.phone = phone;
}
public class Staff {
public ArrayList<StaffMember> staffList;
/**
* Constructor for objects of type Staff.
*/
public Staff() {
staffList = new ArrayList<StaffMember>(6);
~~~ staffList.add(new Executive("Hilary", "203 Whitewater Line", "871-0469", 123456789, 5000, 0));
staffList.add(new Employee("Thomas", "1000 Robson Street", "604-0000", 010203040, 1500));
staffList.add(new Hourly("Condoleeza", "678 Fifth Ave.", "905-0690", 958473625, 18.50, 0));
staffList.add(new Volunteer("Kimberly", "1200 West Point Grey Road", "514-8374"));
staffList.add(new Volunteer("Jean", "321 Shawinigate Lane", "613-7282"));
}
public class Executive extends Employee {
private double bonus;
/**
* Default Constructor
*/
public Executive() {
super();
}
/**
* #param name
* #param address
* #param phone
* #param socialInsuranceNumber
* #param payRate
*/
public Executive(String name, String address, String phone, int socialInsuranceNumber, double payRate, double bonus) {
super(name, address, phone, socialInsuranceNumber, payRate);
this.awardBonus(bonus);
}

There is a Circular chain of constructor invocations.
Your base class constructor Staff() is instantiating child classes which in turn invoke self constructor leading to infinite chain causing stackOverFlow error.
Also, it doesn't seem correct for StaffMember to extend Staff . As staff is the entire staff consisting of all the employees and StaffMember represents a single employee. There is no is A relationship between the two.
You should remove the extends Staff from StaffMember and the code should also work fine then.

The constructor of your class A calls the constructor of class B. The constructor of class B calls the constructor of class A. You have an infinite recursion call, that's why you end up having a StackOverflowError. You are going into an circular call of constructors.
Java supports having circular dependencies between classes, the problem here is only related to constructors calling each others.

You are having a circular instantiation of objects which is causing your stack to overflow.
In your Staff constructor you are instantiating many classes, such as Executive and Employee. Your Executive class extends the Employee class and your Employee class extends your StaffMember class.
When you do that, the constructor of Staff will be called again implicitly (by calling super() from Executive, then Employee and then StaffMember) and repeat the entire process, thus consuming all your memory.
Getting rid of your class that extends Staff would probably solve your problem (probably the problematic one is the extends from StaffMember which is the last on the chain of invocations).

Related

How do I multiply by a method in a different class java

I want to know how to call an income method that is located in a different method. Currently, my income method is located in a TaxPayer class. I want to call on this method however, and use it in the equation below income * corporate rate = tax. How do I do this?
Tax calculator:
`public class TaxCalculator {
double tax;
/**
* Creates a TaxCalculator using 2021-2022 tax rates;
*/
public TaxCalculator() {
}
/**
* Calculates a tax payer's tax assuming they are a corporation.
*
* #precondition payer != null AND payer.isCorporation()==true
* #postcondition none
*
* #param payer the tax payer
*/
public double corporaterate = 0.21;
public double taxcalc(TaxPayer income) {
tax = income.getIncome() * corporaterate;
return tax;
}
public double calculateCorporateIncomeTax(TaxPayer payer) {
if (tax < 0) {
tax = 0;
}
return tax;
}`
I am trying to call upon my method located in a different class called Tax Payer:
public class TaxPayer {
private String name;
private int age;
private boolean isCorporation;
private double income;
/**
* Creates a new taxpayer.
*
* #precondition name != null AND !name.isEmpty() AND age >= 0
* #postcondition getName()==name AND getAge()==age AND getIsBusiness()=isBusiness
*
* #param name the person or business' name
* #param age the person's age (ignored if it is a business)
* #param income the annual income
* #param isCorporation true if the taxpayer is a business, false otherwise
*/
public TaxPayer(String name, int age, double income, boolean isCorporation) {
super();
this.name = name;
this.age = age;
this.isCorporation = isCorporation;
this.income = income;
}
/**
* Gets the name
* #return the name
*/
public String getName() {
return this.name;
}
/**
* Gets the age
* #return the age
*/
public int getAge() {
return this.age;
}
/**
* Gets the taxpayer's annual income.
* #return the taxpayer's annual income.
*/
public double getIncome() {
return this.income;
}
/**
* Gets whether or not this is a corporation (and not a person)
* #return true if a corporation, false otherwise
*/
public boolean isCorporation() {
return this.isCorporation;
}
}
I want to know how to call this getIncome method.
To call method getIncome() that is a method of class TaxPayer, there are two possibilities, depending upon whether the method is a static method or an instance method.
For a static method, from the other class (such as from TaxCalculator):
tax = TaxPayer.getIncome() * corporateRate; // TaxPayer is a class; getIncome() is a static method
For instance methods, you need an instance of a TaxPayer object:
tax = taxPayer.getIncome() * corporateRate; // taxPayer is an object of type TaxPayer; getIncome is an instance method
From what you posted, it appears that you're working with an instance method, and the calculate method that calls the getIncome() method gets an instance of TaxPayer as it's parameter. If this is all true, the code seems correct. Before you call calculateCorporateIncomeTax(payer), you should verify that TaxPayer object payer is initialized correctly.
As others have stated, it would be easier to answer with full code posted.

Class constructors not initializing values correctly [duplicate]

This question already has answers here:
What are java object fields initialized with?
(6 answers)
Closed 7 years ago.
I have a main java file and an employee class. For the employee class I have 3 methods - a getName method which returns an employee name, a getSalary method which returns a salary, and a raiseSalary which raises the salary by a certain percent.
In my Main.java file, I made a constructor to initialize the values of the employee class, and when I attempt to printout these values, I get null and 0
/**
* This class tests the Employee object.
*
*/
public class Main {
/**
* Create an employee and test that the proper name has been created. Test
* the initial salary amount and then give the employee a raise. Then check
* to make sure the salary matches the raised salary.
*
public static void main(String[] args) {
Employee harry = new Employee("Hi", 1000.00);
System.out.println("Employee name:" + harry.getName());
System.out.println("Salaray: "+ harry.getSalary());
harry.raiseSalary(10); // Harry gets a 10% raise.
}
}
/*** This class implements an employee which is a person with a name and a salary.
*
*/
public class Employee {
private String employeeName;
private double currentSalary;
public Employee(String employeeName, double currentSalary) {
}
// Accessors that are obvious and have no side effects don't have to have
// any documentation unless you are creating a library to be used by other
// people.
public String getName() {
return employeeName;
}
public double getSalary() {
return currentSalary;
}
/**
* Raise the salary by the amount specified by the explicit argument.
*
*/
public void raiseSalary(double byPercent) {
currentSalary = getSalary() * byPercent;
}
}
The parameters in your constructor do not point to the same objects created outsides it's scope... to fix simply
public Employee(String employeeName, double currentSalary) {
this.employeeName = employeeName;
this.currentSalary = currentSalary;
}
Adding a "this" before a variable name simply tell the code to point at the variable outside the scope

Eclipse- Source Not Found

I am doing Stanford Java Class (the art and science of java), working on the exciese of implemetation of class. When I try to run the code below, Eclipse gave the error: Source not found - the souce attachment does not contain the source for the file Program.class. You can change the source attachemnt by clicking Change Attached Source below.
My current location is /ACMStarterProject/acm.jar
If you know how to resolve this, please let me know. Thanks.
public class Employee extends ConsoleProgram {
public void run() {
Employee emp = new Employee("John Smith", "Robert Cook", 78000);
println(emp.getName() + ", " + emp.getSupervisor() + ", " + emp.getSalary());
}
/**
* Creates a new employee object, which has name, supervisor’s name,
* and salary as its state.
* #param empName The name of the employee
* #param supName The name of the supervisor
* #param sal The salary of the employee
*/
public Employee(String empName, String supName, double sal) {
name = empName;
supervisor = supName;
salary = sal;
}
/**
* Returns the name of the employee.
* #return The name of the employee
*/
public String getName() {
return this.name;
}
/**
* Returns the name of the supervisor of the employee.
* #return The name of the supervisor of the employee
*/
public String getSupervisor() {
return this.supervisor;
}
/**
* Returns the salary of the employee.
* #return The salary of the employee
*/
public double getSalary() {
return this.salary;
}
/**
* Set the salary of the employee.
* #param sal The new salary of the employee
*/
public void setSalary(double sal) {
this.salary = sal;
}
/**
* Set the supervisor of the employee.
* #param supName The new salary of the employee
*/
public void setSupervisor(String supName) {
this.supervisor = supName;
}
/* Private instance variables */
private String name;
private String supervisor;
private double salary;
}
Usually you need a zip or jar file as well which contains java source code files. For example , if you want to see the source code of jre, you need something like src.zip and you need point your class to that zip file.
In your case , I guess you need something like acm.src.zip or acm.src.jar. if you find it you need point your class to this zip or jar file by selecting the right position of the corresponding file.
The jar file is similar as a zip file which bundles all the java source files(not class) together.

Questions about calling a constructor and defining the variables in Java (Homework)

To be clear, this is an active homework assignment. I just need some guidance.
I am creating a bookstore program in Java that, in revision 1, only has to return information about one specific book when it runs. I must use two classes, and call the info in the secondary class inside the main method to output.
I think I created the constructor correctly inside the Book class, but what's the best way to A) define those variables and B) call the info inside the Bookstore class to output? I just need some guidance here, as I'm kinda stuck. Eclipse is asking me to re-define the int and double variables as a String, but they are going to be numbers...is there something in my syntax that is causing it to do that?
Here's what I have so far:
import java.util.Scanner; // Import Scanner
/** Main Class */
public class Bookstore {
/** Secondary Class */
private class Book {
/** Declare Variables */
private int isbn;
private String bookTitle;
private String authorName;
private int yearPublished;
private String publisherName;
private double bookPrice;
/** Constructor */
Book (int isbn, String bookTitle, String authorName, int yearPublished, String publisherName, double bookPrice) {
setIsbn(isbn);
setBookTitle(bookTitle);
setAuthorName(authorName);
setYearPublished(yearPublished);
setPublisherName(publisherName);
setBookPrice(bookPrice);
}
/**
* #return the isbn
*/
public void getIsbn(int isbn) {
return isbn;
}
/**
* #param isbn the isbn to set
*/
public void setIsbn(int isbn) {
this.isbn = isbn;
}
/**
* #return the bookTitle
*/
public void getBookTitle(String bookTitle) {
return bookTitle;
}
/**
* #param bookTitle the bookTitle to set
*/
public void setBookTitle(String bookTitle) {
this.bookTitle = bookTitle;
}
/**
* #return the authorName
*/
public String getAuthorName() {
return authorName;
}
/**
* #param authorName the authorName to set
*/
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
/**
* #return the yearPublished
*/
public int getYearPublished() {
return yearPublished;
}
/**
* #param yearPublished the yearPublished to set
*/
public void setYearPublished(int yearPublished) {
this.yearPublished = yearPublished;
}
/**
* #return the publisherName
*/
public String getPublisherName() {
return publisherName;
}
/**
* #param publisherName the publisherName to set
*/
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
/**
* #return the bookPrice
*/
public double getBookPrice() {
return bookPrice;
}
/**
* #param bookPrice the bookPrice to set
*/
public void setBookPrice(double bookPrice) {
this.bookPrice = bookPrice;
}
} // End Book Class
/** Main Method */
public static void main(String[] args) {
} // End Main Method
} // End Bookstore Class
That's where I'm at. Again, I'm stuck on how to define the variables properly, and then call the data for output in the Bookstore method. I know how to print it to the screen, it's just getting it there that is perplexing me. Do I create another Book object inside the Bookstore class?
I appreciate any help that's available.
Let's start with...
private class Book {
I would say declaring an inner class as private might not be the best choice, as you not be able to use beyond the scope of BookStore, but that's a choice you need to make...
This...
/**
* #return the isbn
*/
public void getIsbn(int isbn) {
return isbn;
}
is wrong on a number of accounts. First, it is declared as void, meaning that the method won't return anything, but then you use return isbn within the method. It should be declared as returning an int.
Next, you pass isbn as a parameter to the method, but immediately return the same value, this isn't really what you want to do, you want to return the value of isbn defined by Book, for example...
/**
* #return the isbn
*/
public int getIsbn() {
return isbn;
}
The same thing goes for getBookTitle.
In some languages they pass parameters by reference, meaning you can actually alter the value in the method/function and that will be reflected in the callers context. Java doesn't do this (more accurately, you can't reassign the value within the method and have it reflected in the caller). This is tripping point for many developers.
Basically, this means you can't do something like...
public void getBookTitle(String bookTitle) {
bookTitle = this.bookTitle;
}
As the value of the parameter will the same in the callers context after the method call as it was before it. You have to "get" the value from the class.
An interesting side effect though, is you can change the properties of objects passed to a method, if they supply mutable functionality...

Java enum in practice, bad code to improve

I want to improve my use of JDK 1.5 and stop using private static final String instead of enum. This is what seems to be recommended.
But now my constant class looks like this :
public class CEnum{
/**
* #author JJA
* date : 20/10/2010
*/
public enum ListTypeAffichage {
DEP("DEPOT_TVA"), PAD("PAS_DEPOT_TVA"), NORM("CAT_NORMALE"), CAP("CAT_PARTICULIERE"), CAA("CAT_AUTRE_CAS");
private final String sName;
/**
* #param name String
*/
ListTypeAffichage(String name) {
this.sName = name;
}
/**
* #return String
*/
public String getType() {
return sName;
}
}
/**
* #author JJA
* date : 20/10/2010
*/
public enum ListTypeCategorie {
DEDUIRE("SOMME_A_DEDUIRE"), AJOUTER("SOMME_A_AJOUTER");
private final String sName;
/**
* #param name String
*/
ListTypeCategorie(String name) {
this.sName = name;
}
/**
* #return String
*/
public String getType() {
return sName;
}
}
/**
* #author JJA
* date : 26/10/2010
*/
public enum ListInterval {
POS("POSITIF"), NS("NON_SIGNE");
private final String sName;
/**
* #param name String
*/
ListInterval(String name) {
this.sName = name;
}
/**
* #return String
*/
public String getInterval() {
return sName;
}
}
}
instead of
public class ConstantesADMD {
public static final List<String> typeAffich = new ArrayList<String>();
...
ConstantesADMD(){
typeAffich.add("DEPOT_TVA");
typeAffich.add("PAS_DEPOT_TVA");
typeAffich.add("CAT_NORMALE");
...
}
}
My code seems to be really bad, but at least works. For each enum I have to add the redundant code :
private final String sName;
/**
* #param name String
*/
ListTypeAffichage(String name) {
this.sName = name;
}
/**
* #return String
*/
public String getType() {
return sName;
}
What improvment do you advise me?
Note : forget the last sentences of my first question, I need the index. Tell me if I have to post another question, editing my fisrt seems easier.
I would name my enum-constants as you have named your strings. You can then access the name using the Enum.toString() method. For example:
public enum ListTypeAffichage {
DEPOT_TVA, PAS_DEPOT_TVA, CAT_NORMALE, CAT_PARTICULIERE, CAT_AUTRE_CAS;
/**
* #return String
*/
public String getType() {
return toString();
}
}
You could of course also skip the getType() all together, and access the "type" using toString() instead:
ListTypeAffichage myEnum = ListTypeAffichage.CAT_PARTICULIRE;
System.out.println("Type: " + myEnum.toString()); // like this...
System.out.println("Type: " + myEnum); // ...or like this
According to the API, this is better than using the Enum.name() directly:
public final String name()
[...] Most programmers should use the toString() method in preference to this one [...]
Each enum has a name() method which return the exact string represantation of the constant. So you may do this:
public enum ListTypeAffichage {
DEPOT_TVA, PAS_DEPOT_TVA, CAT_NORMALE, CAT_PARTICULIERE, CAT_AUTRE_CAS
}
and then
ListTypeAffichage.DEPOT_TVA.name();
By using the abbreviations (DEP, PAD, NORM) etc. you have created aliases to (DEPOT_TVA, PAS_DEPOT_TVA, CAT_NORMALE) etc.
If you want to keep the abbreviations, then you'll have to maintain the enum as you have it.
If you are willing to do away with the abbreviations, then you can change you enum as below, I have included a main method in the enum to demonstrate its use.
public enum ListTypeAffichageNames {
DEPOT_TVA,
PAS_DEPOT_TVA,
CAT_NORMALE,
CAT_PARTICULIERE,
CAT_AUTRE_CAS;
public static void main(String[] args) {
System.out.println(DEPOT_TVA.toString());
ListTypeAffichageNames affichage = ListTypeAffichageNames.valueOf("DEPOT_TVA");
System.out.println(affichage.toString());
}
}
In addition to this, your current structure of constants does not give you compile time type checking, and does not prevent something like the following happening during runtime:
ConstantesADMD.typeAffich.clear();
// or
ConstantesADMD.typeAffich.remove("DEPOT_TVA");
ConstantesADMD.typeAffich.add("dEpOt-tVa");

Categories