Design Issue: Static vs Non-static instance variables - java

I am designing an Address Book and in order to make my AddressBookApp class work (which includes my main method) I have had to create instance variables and make them static in order for each method in my class to be able to access my Name, Email, and Phone objects. I assume that there is a better way, but am struggling to know what that is. Should I create the objects in the main method? Are instance variables the right way to go? Do you guys have any ideas as to how I can improve my design? (If you have any other design suggestions not related to my question then let me know)
Here is the code for my AddressBookApp class:
import java.util.Scanner;
public class AddressBookApp {
//Instance Variables
private static Name name;
private static Email email;
private static Phone phone;
//Constructor
public AddressBookApp() {
name = new Name();
email = new Email();
phone = new Phone();
}
//Main method
public static void main(String[] args) {
new AddressBookApp();
System.out.println("Welcome to the Address Book Application\n");
Scanner sc = new Scanner(System.in);
int menuNumber;
do {
menu();
menuNumber = sc.nextInt();
System.out.println();
if (menuNumber < 1 || menuNumber > 4){
System.out.println("Please enter a valid menu number\n");
} else if (menuNumber == 1) {
printEntries();
} else if (menuNumber == 2) {
addEntry();
} else if (menuNumber == 3) {
removeEntry();
} else {
System.out.println("Thanks! Goodbye.");
sc.close();
return;
}
continue;
} while (menuNumber != 4);
sc.close();
}
/**
* Prints out Main Menu
*/
public static void menu() {
System.out.println("1 - List entries\n" +
"2 - Add entry\n" +
"3 - Remove entry\n" +
"4 - Exit\n");
System.out.print("Enter menu Number: ");
}
/**
* Prints all entries in the Address Book
*/
public static void printEntries() {
name.printNames();
System.out.println();
email.printEmails();
System.out.println();
phone.printPhoneNumbers();
System.out.println();
}
/**
* Adds an entry to the Address Book
*/
public static void addEntry() {
Scanner sc = new Scanner(System.in);
System.out.print("Enter Name: ");
name.addName(sc.nextLine());
System.out.print("Enter Email Address: ");
email.addEmail(sc.nextLine());
System.out.print("Enter Phone Number: ");
phone.addPhone(sc.nextLine());
System.out.println("\nRecord Saved.\n");
}
/**
* Removes and entry from the Address Book
*/
public static void removeEntry() {
Scanner sc = new Scanner(System.in);
System.out.print("Please Enter the record number that you would like to remove: ");
int records = sc.nextInt();
name.removeNames(records - 1);
email.removeEmail(records - 1);
phone.removePhone(records - 1);
}
}

AddressBook and AddressBookApp should be two different classes. AddressBook should look like this:
public class AddressBook {
//Instance Variables
private Name name;
private Email email;
private Phone phone;
//Constructor
public AddressBook() {
name = new Name();
email = new Email();
phone = new Phone();
}
// more Constructors
public void setName(Name name) {
this.name = name
}
public Name getName() {
return name;
}
// more getters and setters
Your app can then create an instance of this in your main() method:
AddressBook book = new AddressBook();
book.setName(new Name("Jeff"));
//more operations on book
You can pass around the object book to any methods in which you need it or keep creating new instances. You can also have it as a static reference in your app class:
private static AddressBook book = new AddressBook();
// in your app class methods
book.burnBeforeReading();

Simple, create two classes: Main and AddressBook.
Main only has
public static void main(String[] args) {
new AddressBook().execute();
...
AddressBook only has instance methods.

Related

3 subclass and 1 main class inheritance, but shows null in output in java?

I'm starting to get into coding. My formats are bad, but I wanna see first if my idea for the program works then correct it later on. This is program consists of the main class (Employee), then two subclasses that inherit from the main class (Part-Time and Full-Time employees) The code works but I encountered null in my employee's name output in this code or maybe I missed something. Any help, correction, or advice would be great! Thank you
Main Class
class Employee {
public String Name;
public void setName(String Name)
{
this.Name = Name;
}
public String getName()
{
return Name;
}
public void emp()
{
Scanner scan = new Scanner(System.in);
System.out.println("Enter Name: ");
Name = scan.nextLine();
}
}
Subclass FullTimeEmployee
class FullTimeEmployee extends Employee {
private double monthlySalary;
Scanner scan = new Scanner(System.in);
public void setMonthSalary(double monthlySalary) {
this.monthlySalary = monthlySalary;
}
public double getMonthlySalary() {
return monthlySalary;
}
#Override
public void emp() {
System.out.println("Enter monthly salary: ");
monthlySalary = scan.nextDouble();
System.out.println("Name: " + getName());
System.out.println();
System.out.println("Monthly Salary: " + monthlySalary);
}
}
subclass PartTimeEmployee
public class PartTimeEmployee extends Employee {
Scanner scan = new Scanner(System.in);
private double ratePerHour;
private int hoursWorked;
private double wage;
public void setWage(double wage) {
this.wage = wage;
}
public double getWage() {
return wage;
}
#Override
public void emp() {
System.out.println("Enter rate per hour and no of hours worked separated by space: ");
ratePerHour = scan.nextDouble();
hoursWorked = scan.nextInt();
System.out.println("Name: " + getName());
wage = ratePerHour * hoursWorked;
System.out.println("Wage: " + wage);
}
}
RunEmployee
public class RunEmployee {
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
Employee emp1 = new Employee();
FullTimeEmployee fte = new FullTimeEmployee();
PartTimeEmployee pte = new PartTimeEmployee();
emp1.emp();
System.out.println("Press F for Full Time or P for Part Time: ");
char select = scan.nextLine().charAt(0);
if(select == 'F') {
fte.emp();
} else if (select =='P') {
pte.emp();
}
}
}
OUTPUT OF BOTH
Enter monthly salary:
500
Name: null
You only set name in the Employee parent class in the emp() method here:
public void emp() {
Scanner scan = new Scanner(System.in);
System.out.println("Enter Name: ");
Name = scan.nextLine(); // here!
}
And yes, you give your child classes the same method and override and call it, but you never call the parent's version of the method, the super.emp() method, and so the name field never gets set.
A solution would be to call the super.emp() in your overrides, but this isn't good as it breaks the "single responsibility principle". And Employee should be responsible for Employee data and behaviors, but shouldn't be also responsible for handling a Scanner object and getting direct input from the user. Also, there are potential dangers from creating multiple Scanner objects based on System.in.
Much better, get all I/O, all use of Scanner, out of the Employee class and its children. The I/O should be in the main method (for this code) and instead, set name in the Employee constructor, and by calling the super constructor in the child classes, or by directly calling .setName(...) on any instances created.
e.g.,
class Employee {
public String name;
public Employee(String name) {
this.name = name;
}
public Employee() {
this(null);
}
public void setName(String Name) {
this.Name = Name;
}
public String getName() {
return Name;
}
// get rid of this
/*
public void emp() {
Scanner scan = new Scanner(System.in);
System.out.println("Enter Name: ");
Name = scan.nextLine();
}
*/
}
public class FullTimeEmployee extends Employee {
private double monthlySalary;
// Scanner scan = new Scanner(System.in); // *** get rid of this!
public FullTimeEmployee(String name) {
super(name);
}
public FullTimeEmployee() {
super();
}
public void setMonthSalary(double monthlySalary) {
this.monthlySalary = monthlySalary;
}
public double getMonthlySalary() {
return monthlySalary;
}
/* // get rid of this!
#Override
public void emp() {
System.out.println("Enter monthly salary: ");
monthlySalary = scan.nextDouble();
System.out.println("Name: " + getName());
System.out.println();
System.out.println("Monthly Salary: " + monthlySalary);
}
*/
}
and then again, put all Scanner code in the main method.
Regarding variable public String Name;
As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
Also, avoid using public fields unless absolutely necessary. Better to make this field protected, or even better yet, make it private.

Calling an object's method defined in List

I'm trying to call addContact method from main method using ArrayList called phone but its not working.
Here's the code:
import java.util.ArrayList;
import java.util.Scanner;
class A {
String name;
int num;
Scanner sc = new Scanner(System.in);
public A(String name, int num) {
this.name= name;
this.num= num;
}
public void addContact() {
sc.nextLine();
System.out.println("Enter name:");
name = sc.nextLine();
System.out.println("Enter number:");
num = sc.nextInt();
}
}
public class Main {
static void menu() {
System.out.println("1. add");
System.out.println("2. break");
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList <A> phone;
while(true) {
menu();
int c = sc.nextInt();
if(c==1) {
phone.add().addContact();
//I'm trying to call addContact()
} else if(c==2) {
break;
}
}
}
}
Why I can't just call phone.add().addContact()?
import java.util.ArrayList;
import java.util.Scanner;
class A {
String name;
int num;
Scanner sc = new Scanner(System.in);
public A(String name, int num) {
this.name= name;
this.num= num;
}
}
public class Main {
static void menu()
{
System.out.println("1. add");
System.out.println("2. break");
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList <A> phone = new Arraylist<A>();
while(true)
{
menu();
int c = sc.nextInt();
if(c==1)
{
System.out.println("Enter name:");
String name = sc.nextLine();
System.out.println("Enter number:");
int num = sc.nextInt();
phone.add(new A(name,num));
}
else if(c==2)
{
break;
}
}
}
}
Just removed you addContact and placed in in the while. Now i create a new Instance of A and add it to the list. This should work now. Please post more precise Questions in the future.
You need to create an instance of your list:
ArrayList<A> phone = new ArrayList<>();
ArrayList <A> phone;
Should be:
ArrayList phone = new ArrayList();
Also, the add() method in this line
phone.add().addContact();
should contain an A object to add to the ArrayList.
you need to return object of A
public A addContact() {
sc.nextLine();
System.out.println("Enter name:");
name = sc.nextLine();
System.out.println("Enter number:");
num = sc.nextInt();
return new A(name,num);
}
and
if(c==1)
{
phone.add(addContact);
}
Your problem starts here:
ArrayList <A> phone;
only declares that list; but doesnt define it. Thus you run into a NullPointerException when you try to run your code.
You need
ArrayList <A> contacts = new ArrayList<>();
instead. I took the freedom to give that variable a reasonable name, too. (this list is about storing contents, it is not storing phones; and it is also not a single phone ... just a list of contact information)
But there is more. You see, you are getting your abstractions wrong. Your Contact class (A is just a terrible name for that class) should not be dealing with a scanner to fetch its data.
Instead, you want to do something like:
class Contact {
private final String name;
private final int number;
Contact(String name, int number) {
this.name = name;
this.number = number;
}
and then, within your main method, you do something like:
boolean loop = true;
while (loop) {
... have user enter a name and a number
if (name.equals("STOP")) {
loop = false;
} else {
Contact contact = new Contact(name, number);
phones.add(contact);
}
}
I can't give the working code. Just check below points to make your program better.
Why you are creating constructor with arguments when you using add contact method.
Where you are created object for class A in class Main.
Try to check how to use ArrayList class. Because you are not using add() properly.

java no main classes found error when the program said build successful

Hi I'm currently doing this program for my assignment to create like a virtual shop. Currently I'm using NetBean IDE 8.1 and got an error when I tried to test the program. It's said , even though the program said build successful when I tried to build the program.
I did tried to follow the instruction in this video but came out empty image here
Here is my main program ( I haven't complete the program yet but this error keeps blocking me for testing it)
import java.util.Scanner;
public class Zarashop {
int choice;
public static void main(String[] args, int clothA){
Scanner absorb = new Scanner(System.in);
// phase 1 login
cloth cl = new cloth(); // declaring objects
payment pay = new payment();
personalinfo pi = new personalinfo();
shipping ship = new shipping();
receipt re = new receipt();
System.out.println("Welcome to Zara's cloth Shopping Center");
System.out.println("\nThis an online Shopping application will help you to buy "+ "a new cloth");
System.out.println("Please enter your detail");
System.out.println("\nPlease enter your name");
String Name = absorb.nextLine(); // user input name
System.out.println("\nAre you a student? (yes) or (no)");
String personalchoice = absorb.nextLine(); // user input status
//phase 2
System.out.println("please choose your cloth" );
System.out.println("cloth A detail : size: 170cm and red color ");
int cloathA = absorb.nextInt();
System.out.println("enter quantity ");
int quantity = absorb.nextInt();
pay.setclothA(clothA); // store value
pay.setquantity(quantity);
// phase 3 payment
System.out.println("please press 1 to calculate your payment");
int choice = absorb.nextInt();
if(choice == 1){
pay.total();
}
else {
System.err.println("error!");
}
}
}
Here is my main class for cloth ( misspelled was intended)
public class cloth {
// superclass
private int quantity; //
private int clothA=200;
//void
void setclothA(int ca){
clothA = ca;
}
void setquantity(int q){
quantity=q;
}
//get
int getclothA(){
return clothA;
}
int getquantity(){
return quantity;
}
}
my main class for personalInfo
public class personalinfo {
// superclass
public String Name;
private int Password;
private String TypeCard;
private int CardNo;
private String Address;
private int TeleNo;
//void
void setName(String n){
Name = n;
}
void setPassword(int p){
Password = p;
}
void setTypeCard(String tp){
TypeCard = tp;
}
void setCardNo ( int cn){
CardNo=cn;
}
void setAddress ( int a){
CardNo=a;
}
void setTeleNo ( int tl){
TeleNo=tl;
}
//get
String getName(){
return Name;
}
String getAddress(){
return Address;
}
int getPassword(){
return Password;
}
String getTypeCard(){
return TypeCard;
}
int getCardNo(){
return CardNo;
}
int getTeleNo (){
return TeleNo;
}
}
my sub class for payment
package zarashop;
//subclass
public class payment extends cloth {
String Status = "Initial";
public void total(){
int ca = super.getclothA(); //fetching values
int q = super. getquantity();
int total= q*ca;
}
}
public class receipt extends shipping{
}
my sub for shipping
public class shipping extends payment {
public int typeofshipping;
//void
void settypeofshipping(String ts){
String typeofshipping = ts;
}
int gettypeofshipping(){
return typeofshipping;
}
}
subclass for receipt (i'm reserving this for the program to display all the necessary user input)
public class receipt extends shipping{
}
thank you everyone and sorry for my bad program and my English.
A Java application can accept any number of arguments from the command line, and all of those are interpreted as String, that's why main only takes an array of String as parameter.
Change you code to
public static void main(String[] args)
and you'll be able to launch your application.
If you need to support a numeric command-line argument, you must convert a String argument that represents a number to an int:
int firstArg;
if (args.length > 0) {
try {
firstArg = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.err.println("Argument" + args[0] + " must be an integer.");
System.exit(1);
}
}
parseInt throws a NumberFormatException if the format of args[0] isn't valid.
The example comes from official documentation.
Here is your mistake: public static void main(String[] args**, int clothA**)
Change it to public static void main(String[] args)
You will need to change your main method to public static void main(String[] args). By adding int clothA as a second argument, you are chaging the signature, and then it becomes an invalid main method to launch your application from.
If you want to retrieve something from console, you will find your argument inside args.
You can then retrieve clothA as follows:
int clothA;
if (args.length > 0) {
try {
clothA = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.err.println("Argument" + args[0] + " must be an integer.");
System.exit(1);
}
}

Is there a way to send variables from main class to subclass using user input JAVA

So I'm working on a (supposedly) simple java application that uses console inputs from a user, to change private variables in another class. Now I can change the value of the private variables in the EmpCls class directly from the main class by manually inputting a variable into the object, e.g.
EmpCls empObject1 = new EmpCls("josh"); but how do I get something like this
EmpCls empObject1 = new EmpCls(ctName); to work? where ctName is the variable that the user inputs. here's the relevant code from the main class:
import java.util.*;
public class NewWan {
static Scanner console = new Scanner(System.in);
public static void main(String[] args) {
EmpCls empObject1 = new EmpCls(ctName);
String ctName = empObject1.getName();
System.out.println("enter name: ");
ctName = console.next();
}
}
And the subclass in question:
public class EmpCls {
private String name;
private String ext;
private int yearStarted = 0;
public EmpCls()
{
}
public EmpCls(String inName)
{
this.name = inName;
}
public void setEmpDetails(String inName) //, String inExt, int inYearStarted)
{
this.name = inName;
// this.ext = inExt;
// this.yearStarted = inYearStarted;
}
public String getName()
{
return this.name;
}
public int getYearStarted()
{
return this.yearStarted;
}
public String getExt()
{
return this.ext;
}
public void displayDetails()
{
System.out.println("Name: " + name);
System.out.println("Ext: " + ext);
System.out.println("Year Started" + yearStarted);
}
}
some parts of the code are commented just to enable easier trouble shooting, other parts are part of a different problem im working on.
You just need to reorder the statements a bit and remove the one that doesn't make sense:
public static void main(String[] args) {
System.out.println("enter name: ");
String ctName = console.next();
EmpCls empObject1 = new EmpCls(ctName);
}
Hum... just to organize your code in the good way ? You use variable before getting value, and before declare it... Strange way ^^
public static void main(String[] args) {
System.out.println("enter name: ");
String ctName = console.next();
EmpCls empObject1 = new EmpCls(ctName);
System.out.println("You just enter " + empObject1.getName());
}

method to add objects to ArrayList using user input

Can't take my head around the following: There are 2 classes - "Item", where attributes (Name, Price) and constructors are set, and main "Store". In the last one - Arraylist, which fills up with Items depending on user input. The code works.
Here is the question: Is there any way to put all from the main class, apart from "ArrayList listOfItems=new ArrayList();" line into a method "addItem()" and then just call the method? I do not know how to do it. Tried a lot.
Thank you
package store;
import java.util.ArrayList;
import java.util.Scanner;
public class Store extends Item {
public static void main(String[] args) {
ArrayList<Item> listOfItems=new ArrayList<Item>();
for(int i=0;i<2;i++){
System.out.println("ENTER NAME");
Scanner addName=new Scanner (System.in);
String name=(addName.nextLine());
System.out.println("ENTER PRICE");
Scanner addPrice=new Scanner (System.in);
double price=(addPrice.nextDouble());
listOfItems.add(new Item(name,price));
}
for(Item list:listOfItems){
System.out.println("NAME "+list.getName()+", PRICE "+list.getPrice());
}
}
}
This will work for you:
package store;
import java.util.ArrayList;
import java.util.Scanner;
public class Store {
private static class Item {
private String name;
private double price;
public Item(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
public static void main(String[] args) {
ArrayList<Item> listOfItems = new ArrayList<Item>();
addItem(listOfItems);
}
private static void addItem(ArrayList<Item> listOfItems) {
for (int i = 0; i < 2; i++) {
System.out.println("ENTER NAME");
Scanner addName = new Scanner(System.in);
String name = (addName.nextLine());
System.out.println("ENTER PRICE");
Scanner addPrice = new Scanner(System.in);
double price = (addPrice.nextDouble());
listOfItems.add(new Item(name, price));
}
for (Item list : listOfItems) {
System.out.println("NAME " + list.getName() + ", PRICE " + list.getPrice());
}
}
}
I defined the class Item separately to make it compiling. Also I removed the extends Item from the store, because it is not needed.
I don't know exactly if this is what you are looking for, but you may try the following solution:
public class Store extends Item {
public static void main(String[] args) {
ArrayList<Item> listOfItems=new ArrayList<Item>();
addItem(listOfItems);
for(Item list:listOfItems){
System.out.println("NAME "+list.getName()+", PRICE "+list.getPrice());
}
}
private static void addItem(ArrayList<Item> li) {
for(int i=0;i<2;i++){
System.out.println("ENTER NAME");
Scanner addName=new Scanner (System.in);
String name=(addName.nextLine());
System.out.println("ENTER PRICE");
Scanner addPrice=new Scanner (System.in);
double price=(addPrice.nextDouble());
li.add(new Item(name,price));
}
}
}
You maybe also try to declare the ArrayList outside the main:
public class Store extends Item {
private static ArrayList<Item> listOfItems;
public static void main(String[] args) {
listOfItems=new ArrayList<Item>();
addItem();
for(Item list:listOfItems){
System.out.println("NAME "+list.getName()+", PRICE "+list.getPrice());
}
}
private static void addItem() {
for(int i=0;i<2;i++){
System.out.println("ENTER NAME");
Scanner addName=new Scanner (System.in);
String name=(addName.nextLine());
System.out.println("ENTER PRICE");
Scanner addPrice=new Scanner (System.in);
double price=(addPrice.nextDouble());
listOfItems.add(new Item(name,price));
}
}
}
Let me know if you need further help! :)
You could use a better Oriented Object approach to solve your problem.
Store extends Items this has not sense. The store contains items, so you only need a variable like your listOfItems for save all the items of the store.
Your public class Store is a good candidate to use the Singleton Pattern.
About the construction of your listOfItems: When a List is enough, then simply you should use just a List. Also, java 7 provide the type inference for generic instance creation.
From The Java SE Documentation: You can replace the type arguments required to invoke the constructor of a generic class with an empty set of type parameters (<>) as long as the compiler can infer the type arguments from the context. This pair of angle brackets is informally called the diamond.
So, you should use List<Item> listOfItems = new ArrayList<>() instead of ArrayList<Item> listOfItems = new ArrayList<Item>()
Each time that you use a Scanner you should close it.
The Singleton:
public class Store {
private static final Store INSTANCE = new Store();
private List<Item> listOfItems = new ArrayList<>();
private Store() {
// Private Constructor
// will prevent the instantiation of this class directly
}
public static Store getInstance() {
return INSTANCE;
}
public void addItems(List<Item> newlistOfItems) {
listOfItems.addAll(newlistOfItems);
}
public String printListOfItems() {
StringBuilder sb = new StringBuilder();
for (Item item : listOfItems) {
sb.append(" [NAME : " + item.getName() + ", PRICE : " + item.getPrice() + "]");
}
return sb.toString();
}
}
The POJO Item class
public class Item {
private String name;
private double price;
public Item(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
The service interface for the management of items :
public interface ItemManagerService {
List<Item> createListOfItems();
}
The implementation:
public class ItemManagerServiceImpl implements ItemManagerService {
#Override
public List<Item> createListOfItems() {
List<Item> newListOfItems = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
try {
do {
System.out.println("ENTER NAME");
String name = scanner.nextLine();
System.out.println("ENTER PRICE");
while (!scanner.hasNextDouble()) {
System.out.print("You must enter a valid number! Try again: ");
scanner.next();
}
double price = scanner.nextDouble();
Item item = new Item(name, price);
newListOfItems.add(item);
System.out.println("Continue?[Y/N]");
scanner.nextLine();
} while (scanner.nextLine().equalsIgnoreCase("y"));
} finally {
scanner.close();
}
return newListOfItems;
}
}
A simple test :
public class MainApp {
public static void main(String[] args) {
ItemManagerService itemManagerService = new ItemManagerServiceImpl();
List<Item> newlistOfItems = itemManagerService.createListOfItems();
Store.getInstance().addItems(newlistOfItems);
System.out.println(Store.getInstance().printListOfItems());
}
}
The console output:
ENTER NAME
table
ENTER PRICE
12
Continue?[Y/N]
y
ENTER NAME
car
ENTER PRICE
50,8
Continue?[Y/N]
n
[NAME : table, PRICE : 12.0] [NAME : car, PRICE : 50.8]

Categories

Resources