Static variable of superclass acting weird in subclass-creation - java

I'm working on a classic homework program and cannot for the life of me figure out why my static variable in the superclass reacts the way it does..
The program is a bankaccount where I have created a superclass, Account, and two subclasses, CreditAccount and SavingsAccount.
public abstract class Account {
private double balance;
private int accountId;
**private static int lastAssignedNumber = 1000;** <--- the static int
private String accountType;
public Account (double q_balance, String q_accountType)
{
balance = q_balance;
accountType = q_accountType;
**accountId = ++lastAssignedNumber; <------ counter for new accountId**
}
)
public class CreditAccount extends Account {
public CreditAccount(double balance)
{
super(balance, "Creditaccount");
}
}
public class SavingsAccount extends Account {
public SavingsAccount(double balance)
{
super(balance, "Savingsaccount");
}
}
Previously, without subclasses when Account was the only object, the counter worked beautifully. But now when I create some new objects of savingsaccount and creditaccounts the program acts really weird and returns accountnumbers as follows:
new SavingsAccount(0); // **1001**
new CreditAccount(0); // **1001**
new CreditAccount(0); // **1002**
new SavingsAccount(0); // **1003**
new CreditAccount(0); // **1002**
new CreditAccount(0); // **1004**
new SavingsAccount(0); // **1005**
What in gods name is happening?! What am I missing? Shouldn't the two subclasses provoke the same static variable 'lastAssignedNumber' and add to it accordingly??
Kindest regards // Gewra

There is nothing wrong with your code , given that you are creating accounts in single thread model.
Your following code is working absolutely fine:
abstract class Account
{
private double balance;
private int accountId;
private static int lastAssignedNumber = 1000;
private String accountType;
public Account (double q_balance, String q_accountType)
{
balance = q_balance;
accountType = q_accountType;
accountId = ++lastAssignedNumber;
}
public int getAccountID()
{
return accountId;
}
}
class CreditAccount extends Account
{
public CreditAccount(double balance)
{
super(balance, "Creditaccount");
}
}
class SavingsAccount extends Account
{
public SavingsAccount(double balance)
{
super(balance, "Savingsaccount");
}
}
public class AccountLedger
{
public static void main(String st[])
{
Account ac[] = new Account[7];
ac[0] = new SavingsAccount(0); //1001
ac[1] = new CreditAccount(0); //1002
ac[2] = new CreditAccount(0); //1003
ac[3] = new SavingsAccount(0); //1004
ac[4] = new CreditAccount(0); //1005
ac[5] = new CreditAccount(0); //1006
ac[6] = new SavingsAccount(0); //1007
for (int i = 0 ; i < ac.length ; i++)
{
System.out.println(ac[i].getAccountID());
}
}
}

The concepts of multi- and singlethreading are frankly completely new to me but I've tried making both an AtomicInteger and a volatile variable with the exactly same result. I guess it's my structure of the program that is fundamentaly wrong.
The construct is a BankLogic-class holding an ArrayList of Customer-objects. The Customer-objects hold an ArrayList of Account-objects. It doesn't matter where I put the AtomicInteger-object, even though I put it in the BankLogic-class and pass it through to the constructor, it still turns out the same results.
Guess I should just place the accounts-ArrayList in the BankLogic-class and run a method comparing personal-ids (adding a persId-variable to the account-class) instead?
It certainly doesn't feel like such an elegant solution but I see no other way.
Thanks for all the answers!

Related

Looking through class Arraylist objects without nested loops

I had this object oriented programming project last semester and it was all about simulating a simple dormitory.
1.There should have been a manager class in which the main method and like 80 percent of the other methods had to be there.
2.A dormitory class containing an arraylist of blocks.
3.A block class containing an arraylist of rooms.
4.A room class containing an arraylist of students.
5.All of these classes contained getters and setters for their private variables.
There were a few methods that we should've added to the program which has nothing to do with my question,so I will not write them in here,but the thing is,a few of theses methods needed to look through these arraylists to find a specific object.For example,a student with a specific student number.I created these methods with nested loops.But I know there is some way I could avoid heavy nesting.
Here is my reduced code.I will only let the manager class contain one nested loop method as an example:
import java.util.Scanner;
public class Manager {
private String name;
private String familyName;
private String userName;
private String passWord;
private static Scanner scan = new Scanner(System.in);
private Dormitory dorm = new Dormitory();
private static Menu menu = new Menu();
private Student tempStudent;
private Block tempBlock;
private Room room;
private boolean bool;
{
dorm.setDormManager(this);
}
public Manager(String managerName, String managerID) {
name = managerName;
userName = managerID;
}
//find student with its number
public void findStudent() {
//Taking the student number from the user.
System.out.println("Please enter the student number:");
String studentNum = scan.nextLine();
for (int i = 0; i < dorm.getBlockList().size(); i++)
for (int j = 0; j < dorm.getBlockList().get(i).getRooms().size(); j++)
for (int k = 0; k < dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().size(); k++)
if (dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().get(k).getStudentNumber().equals(studentNum)) {
tempStudent = dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().get(k);
break;
}
}
public void create() {
//Used loops for the original program.
Block block1 = new Block("1");
Block block2 = new Block("2");
dorm.getBlockList().add(block1);
dorm.getBlockList().add(block2);
Room room1 = new Room("1");
Room room2 = new Room("2");
dorm.getBlockList().get(0).getRooms().add(room1);
dorm.getBlockList().get(1).getRooms().add(room2);
Student student1 = new Student("12345678");
Student student2 = new Student("98765432");
dorm.getBlockList().get(0).getRooms().get(0).getRoomStudents().add(student1);
dorm.getBlockList().get(1).getRooms().get(0).getRoomStudents().add(student2);
}
public static void main(String[] args) {
Manager manager = new Manager("Dumbledore", "#1112");
manager.create();
}
}
public class Dormitory {
private int blocks;
private Manager dormManager;
private long allMembers;
private ArrayList<Block> blockList = new ArrayList<Block>();
}
public class Block {
private String blockNumber;
private ArrayList<Room> rooms = new ArrayList<Room>();
private Dormitory dorm = new Dormitory();
public Block(String blockNum) {
blockNumber = blockNum;
}
}
public class Room {
private String roomNumber;
private ArrayList<Student> roomStudents = new ArrayList<Student>();
private Block roomBlock;
private Student roomManager;
public Room(String roomNum) {
roomNumber = roomNum;
}
}
public class Student {
private String studentName;
private String studentFamilyName;
private String studentNumber;
private Room room;
public Student(String studentNum) { //Creates a student object using the student number.
studentNumber = studentNum;
}
}
I tried my best to reduce the code.
I searched a lot and asked a lot of people about this but I didn't get my desired answer.I'm not sure why I couldn't find anything about this,but I'd really appreciate it if you'd lend me a hand or give me the link of a related article.
Short answer: No, you should never loop through everything checking for getStudentNumber().equals(studentNum). This has linear time complexity O(N)
Long answer: You should index your data based on your queries
Eg: Indexing with HashMaps which have constant time complexity O(1). (Note: This code is not thread safe)
public class SchoolService {
private Map<String, Student> studentsById = new HashMap<>();
private Map<Long, Dorm> dormsById = new HashMap<>();
/// dormsByAreaCode is showing an example of an index which groups objects into lists
private Map<String, List<Dorm>> dormsByAreaCode = new HashMap<>();
public void addStudent(Student student) {
if (studentsById.containsKey(student.getName()) {
throw new IllegalStateException("Duplicate student " + student.getName());
}
studentsById.put(student.getId(), student);
}
public Student getStudentById(String studentId) {
Student student = studentsById.get(studentId);
if (student == null) {
throw new IllegalStateException("No such student " + studentId);
}
return student;
}
public void addDorm(Dorm dorm) {
// TODO: validation
dormsById.put(dorm.getId(), dorm);
List<Dorm> areaDorms = dormsByAreaCode.get(dorm.getAreaCode());
if (areaDorms == null) {
areaDorms = new ArrayList<>();
dormsByAreaCode.put(dorm.getAreaCode(), areaDorms);
}
areaDorms.add(dorm);
}
public Dorm getDormById(long dormId) {
Dorm dorm = dormsById.get(id);
// TODO: validation
return dorm;
}
public List<Dorm> getDormsByAreaCode(String areaCode) {
List<Dorm> areaDorms = dormsByAreaCode.get(areaCode);
// TODO: validation
return areaDorms;
}
// etc
}
The following quote is from tutorialspoint. This is the perfect use case of the forEach method from the Stream interface. The link I provided and further reading on Streams can help avoid repetitive code.
Using collections framework in Java, a developer has to use loops and make repeated checks. Another concern is efficiency; as multi-core processors are available at ease, a Java developer has to write parallel code processing that can be pretty error-prone.
dorm.getBlockList().stream().forEach((b) -> {
b.getRooms().stream().forEach((r) -> {
...
})
});
You can also read about parallelStreams from here.

Passing variables in the same class between methods?

I havent touched java in awhile. I need some help, what I am trying to do with this program is get the car class to calculate the carbonfootprint inside of the getcarbonfootprint() method. HOWEVER, like all the videos that I have been going through, I DON'T want to pass it back to the main class through a return value. Instead, I want to use the same variables in the class car through methods. I tried using the this value, however, that doesn't work either. If you can link me to the right location on this question, that will work as well.
MAIN CLASS:
package carbonfootprinttest;
public class CarbonFootprinttest {
public static void main(String[] args) {
building house = new building();
car fusion = new car();
bike trek = new bike();
double mytest = fusion.returncarbonfootprint();
System.out.print(mytest);
}
}
CAR CLASS:
public class car implements carbonfootprint {
private double mpg = 25;
public double yearly = 500;
public double carbonfootprint;
public void setmpg(){
System.out.println("The mpg of a ford fusion is " + mpg + " MPG.");
}
#Override
public void getcarbonfootprint() {
carbonfootprint = (yearly * mpg)/9;
}
public double returncarbonfootprint(){
System.out.println(carbonfootprint);
return carbonfootprint;
}
}
package carbonfootprinttest;
public class CarbonFootprinttest {
public static void main(String[] args) {
building house = new building();
car fusion = new car();
bike trek = new bike();
fusion.getcarbonfootprint();
double mytest = fusion.returncarbonfootprint();
System.out.print(mytest);
}
Need to call your method getcarbonfootprint() before returncarbonfootprint()
You should call getcarbonfootprint() first, it will generate and set value to variable carbonfootprint and then call returncarbonfootprint() to get updated value.
fusion.getcarbonfootprint();//Add this line of code in main method
double mytest = fusion.returncarbonfootprint();

Using reflection to get a specific attribute from a extended instance

I would like to make a generic method to get a List from the parameter object.
The problem is because I have a declared object with a instance of the other class that extends the declared class.
I don't want to use the instanceof solution because the number of classes that extends LimitedValue can be big.
I thought to use reflection for a solution, but I don't know how to use that with an instance of object, in this part of the code:
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
This is my full code:
public class CalculatorLimitedValue {
public static void main(String[] args) throws Exception {
StoreItem storeItem = new StoreItem(1L, "Name of StoreItem", 50L);
List listOfStoreItems = new ArrayList();
listOfStoreItems.add(storeItem);
LimitedValue limitedValue0 = new Store(listOfStoreItems);
List firstList = calculator(limitedValue0);
//do something with the list
SupermarketItem supermarketItem = new SupermarketItem(1L, "Name of SupermarketItem", 21L);
List listOfSupermarketItems = new ArrayList();
listOfSupermarketItems.add(supermarketItem);
LimitedValue limitedValue1 = new Supermarket(listOfSupermarketItems);
List secondList = calculator(limitedValue1);
//do something with the list
}
/** This is the method that I'd like to make generic to return a List */
private static List calculator(LimitedValue limitedValue) throws Exception{
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
/* I don't want to use this one way, because my classes that extends LimitedValue
can be big. I would like to made a generic way to get de list of classes. */
if (limitedValue instanceof Store) {
System.out.println("This is a store");
return ((Store) limitedValue).getStoreItems();
} else if (limitedValue instanceof Supermarket) {
System.out.println("This is a supermarket");
return ((Supermarket) limitedValue).getSupermarketItems();
}
return null;
}
}
If it help, these are my other classes:
LimitedValue.class
public class LimitedValue { }
StoreItem.class
public class StoreItem {
private Long id;
private String nameOfStoreItem;
private Long valueOfStoreItem;
public StoreItem(Long id, String nameOfStoreItem, Long valueOfStoreItem){
this.id = id;
this.nameOfStoreItem = nameOfStoreItem;
this.valueOfStoreItem = valueOfStoreItem;
}
//getters and setters...
}
SupermarketItem.class
public class SupermarketItem {
private Long id;
private String nameOfSupermarketItem;
private Long valueOfSupermarketItem;
public SupermarketItem() {
}
public SupermarketItem(Long id, String nameOfSupermarketItem, Long valueOfSupermarketItem) {
this.id = id;
this.nameOfSupermarketItem = nameOfSupermarketItem;
this.valueOfSupermarketItem = valueOfSupermarketItem;
}
//getters and setters...
}
Store.class
public class Store extends LimitedValue {
private List<StoreItem> storeItems;
public Store(List<StoreItem> storeItems) {
this.storeItems = storeItems;
}
//getters and setters
}
Supermarket.class
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
//getters and setters
}
You could try to use reflection here to try to achieve what you want, but it would be better to reconsider your overall design and try to use a better object oriented design that solves the problem at hand.
In particular, lets say we consider adding a method called getItems to the LimitedValue class that returns a List of items, which may be SupermarketItems or may be StoreItems. If it is structured correctly, you won't need to know the actual type because the code will be abstracted over it polymorphically.
public abstract class LimitedValue {
List<? extends Item> getItems();
}
We've now defined a new method on LimitedValue, but we also have to consider that we've introduced this new Item thing. I note that the SupermarketItem and StoreItem all share similiar attributes, name, id and value, so it seems that it might be possible to use a single class to represent them all.
public abstract class Item {
final Long id;
final String name;
final Long value;
public Item(final Long id, final Long name, final Long value) {
this.id = id;
this.name = name;
this.value = value;
}
String getName() {
return name;
}
// other getters and setters
}
public class SupermarketItem extends Item {
public SupermarketItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
public class StoreItem extends Item {
public StoreItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
Now we've completely abstracted away the need for any reflection when accessing these objects - you can simply call item.getValue() as you will know that every item in the list is of type Item.
Of course, you'll also need to refactor the Store and SuperMarket classes, for example:
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
public List<? extends Item> getItems() {
return supermarketItems;
}
}
and because you are only returning a List<Item> you always know what is in it, and you can change your main code to work with this.
This is a much cleaner long term solution.
To get the List value, use Method#invoke:
List list = method.invoke(limitedValue);
You don't need Object obj = cls.newInstance(); - you're not using it at all in the method.
In any case, you're making it very difficult for yourself. You could also define an interface
public interface HasList<E> {
List<E> getList();
}
and have all classes implement this.

Java scheduling causing an error

This code is supposed to fetch the variables from my class Course.
public void prettyPrint(){
Course myCourse = new Course(myCourse.n, myCourse.days, myCourse.start, myCourse.end);
for (int i=0; i>Courses.size();i++){
System.out.println("---"+ Course.dayString + ' '+ ' '+" ---");
System.out.println(myCourse.start +"-"+ myCourse.end+ ": " + myCourse.n );
}
This gets me errors that say "myCourse.n may not be initalized." How do I initialize them if they are just pulling the info from the Course class?
Course myCourse = new Course(myCourse.n, myCourse.days, myCourse.start, myCourse.end); // myCourse is just a reference, when you call new , myCourse hasn't been initialized.
Maybe you should code like this:
Course myCourse = new Course(n, days, start, end);
You cannot reference values in an object before creating it. However, you can create static class variables and reference them without creating any objects as shown:
class Course{
static int n = 1;
static int days = 180;
//..other definitions
//..
}
class Main{
public static void main(){
Course myCourse = new Course(Course.n, Course.days);
}
}
However, static variables introduce dependency between instance variables. A better design would be the factory design pattern with a sample implementation as follows:
class Course{
int n;
int days;
// other instance definitions
public course(int n, int days){
this.n = n;
this.days = days;
}
}
class History extends Course{
public History(){
super(10,200);//the values that you want this course to have
}
}
class Geography extends Course{
public Geography(){
super(20,100);//the values that you want this course to have
}
}
class Main{
public static void main(String args[]){
Course history = new History();
Course geography = new Geography();
}
}

Storing multiple object types in a List

I have following homework about computer store:
There are several class include: Monitor, Case, Mouse, Keyboard.
All the classes have common fields: id, name, price, quantity.
Each class has some unique fields.
All most features are: add, update, delete, find, show list, save, load file
-So, first I will create a class named Product have 4 common fields. Above classes will extends from Product.
-Then, I think I maybe create a ComputerStore class which have a field is items type ArrayList. items stores all objects which are instance of 4 above classes But I'm not sure.
Whether it is reasonable? I need some ideas
Before , I always use ArrayList store for only one class like
List <String> list = new ArrayList<String>();
Now they are multi type. I think it's generic in Java, right??
In case, I want to update for 1 items. I must think about how to change information for them. Ex: mouse for some code, keyboard for another code. Anyway, thank for everybody!
Your approach is 100% reasonable.
You are completely on the right track with "generics". First, check out the official enter link description here.
Next, just think about your data in real world terms, like you are already doing: Monitor, case, mouse, and keyboard are products. Your computer store's inventory is a list of products.
Hint: A list of products.
Put that together with what you learn about generics through that tutorial, and you'll be good to go.
You could use java generic.First create a java collection (ex: List) with supper class type, Product. Now you could add any sub classes (Monitor , Keyboard etc) in your collection (List) that extends of class Product.
public class Product{
}
public class Monitor extends Product{
}
public class Keyboard extends Product{
}
List<Product> products = new ArrayList<Product>();
products.add(new Monitor());
products.add(new Keyboard());
Since you have a superclass (Product), you can have the list's type as Product, i.e.
List<Product> list = new ArrayList<Product>();
list.add(new Mouse());
list.add(new Keyboard());
It will allow you to iterate them and list their name and price without caring for the class, but if you intend to take an item out of the list you'll need to check its actual type (depending on what you do with it).
You can do like below
import java.util.List;
import java.util.ArrayList;
class Test{
public static void main(String... args){
List<MultiObj> multiObjs = new ArrayList();
MultiObj ob = new MultiObj(); multiObjs.add(ob);
ResX xOb = new ResX(); multiObjs.add(xOb);
ResY yOb = new ResY(); multiObjs.add(yOb);
ResZ zOb = new ResZ(); multiObjs.add(zOb);
for (int i = 0; i < multiObjs.size(); i++ ) {
System.out.println(multiObjs.get(i).getV());
}
System.out.println("Waoo its working");
}
}
class MultiObj{
public String greet(){
return "Hello World";
}
public String getV(){
return "Hello World";
}
}
class ResX extends MultiObj{
String x = "ResX";
public String getX(){
return x;
}
public String getV(){
return x;
}
}
class ResY extends MultiObj{
String y = "ResY";
public String getY(){
return y;
}
public String getV(){
return y;
}
}
class ResZ extends MultiObj{
String z = "ResZ";
public String getZ(){
return z;
}
public String getV(){
return z;
}
}
You could do this:
public class Item {
public Item(int id, string name, float price, int amount, int ArrayID) {
if (ArrayID == 1) {
ID1 = id;
name1 = name;
price1 = price;
amount1 = amount;
}
if (ArrayID == 2) {
ID2 = id;
name2 = name;
price2 = price;
amount2 = amount;
}
if (ArrayID == 3) {
ID3 = id;
name3 = name;
price3 = price;
amount3 = amount;
}
if (ArrayID == 4) {
ID4 = id;
name4 = name;
price4 = price;
amount4 = amount;
}
}
//ArrayID #1
public static int ID1;
public static String name1;
public static float price1;
public static int amount1;
//ArrayID #2
public static int ID2;
public static String name2;
public static float price2;
public static int amount2;
//ArrayID #3
public static int ID3;
public static String name3;
public static float price3;
public static int amount3;
//ArrayID #4
public static int ID4;
public static String name4;
public static float price4;
public static int amount4;
public static int[] id = ID1, ID2 ID3, ID4;
//so forth...
}

Categories

Resources