hello I have written code where it takes book details using setter method and displaying details using getter method. When user enters the input it has to enter three details.
Book NameBook PriceAuthor Name
I want to check if user has given any negative value or Zero value in Book Price.
How do I do that? Below is the code. I am practicing Encapsulation problem
//Book.java file
class Book
{
private String bookName;
private int bookPrice;
private String authorName;
public String getBookName()
{
return bookName;
}
public int getBookPrice()
{
return bookPrice;
}
public String getAuthorName()
{
return authorName;
}
public void setBookName(String a)
{
bookName=a;
}
public void setBookPrice(int b)
{
bookPrice=b;
}
public void setAuthorName(String c)
{
authorName=c;
}
}
//TestBook.java file
import java.util.*;
class TestBook
{
public static void main(String args[])
{
Book bobj = new Book();
Scanner sc = new Scanner(System.in);
try
{
System.out.println("Enter the Book name:");
bobj.setBookName(sc.nextLine());
System.out.println("Enter the price:");
bobj.setBookPrice(sc.nextInt());
sc.nextLine();
System.out.println("Enter the Author name:");
bobj.setAuthorName(sc.nextLine());
System.out.println();
System.out.println("Book Details");
System.out.println("Book Name :"+bobj.getBookName());
System.out.println("Book Price :"+bobj.getBookPrice());//should not be -ve or 0
System.out.println("Author Name :"+bobj.getAuthorName());
}
catch(Exception e)
{
System.out.println("Invalid Input");
}
}
}
You should put this check in your setter method to check if it is greater than zero. For example:
public void setBookPrice(int b)
{
if(b>0)
bookPrice=b;
else
{
throw new IllegalArgumentException("b must be positive")
}
}
Above code will prevent setting of negative and zero price. You can replace exception throwing code with your own handling.
If you are practising encapsulation I suggest creating a specific validation method for the price so this can be easily modified without changing the public interface.
public boolean isValidPrice() {
return bookPrice > 0;
}
This can now be checked with
if (!bobj.isValidPrice()) {
//error handling
}
And if the validation rules for price would change the calling code will remain unchaged
Related
I am new to programming and at the moment I am doing a task, the essence of which is the emulation of scanning a person by gender and age with a further pass to a zone defined for its parameters. I was told to supplement the program so that, for example, when you press the S button on the keyboard, the program ends.
Please tell me how can I implement this. I have 4 classes in my code:
main
public class Main {
public static void main(String[] args) {
PassportScan passportScan = new PassportScan();
Guard guard = new Guard();
while (true) {
Person person = passportScan.methodScan();
String result = guard.checkPerson(person);
System.out.println(result);
}
}
}
PassportScan
import java.util.Scanner;
public class PassportScan {
Scanner scanner = new Scanner(System.in);
public Person methodScan() {
System.out.println("Scanning gender");
String gender = scanner.next();
System.out.println("Scanning age");
int age = scanner.nextInt();
return new Person(gender, age);
}
}
Person
public class Person {
private String gender;
private Integer age;
public Person(String gender, Integer age) {
this.gender = gender;
this.age = age;
}
public String getGender() {
return gender;
}
public Integer getAge() {
return age;
}
}
Guard
public class Guard {
public String checkPerson(Person personToCheck) {
String gender = personToCheck.getGender();
int age = personToCheck.getAge();
if (age < 18 && gender.equals("M")) {
return "Zone 1";
}
if (age >= 18 && gender.equals("M")) {
return "Zone 2";
}
if (age < 18 && gender.equals("F")) {
return "Zone 3";
}
if (age >= 18 && gender.equals("F")) {
return "Zone 4";
}
return "";
}
}
Thanks in advance for the tip and your time!
Basically there will be two scenario for this.
1. Once Press S >>> You want to terminate the program
Simply its not available in normal console
but there is way to achieve refer this post for more info https://stackoverflow.com/a/1066647/8524713
2. Press S and then press Enter key >>
In this case its easy
check on each gender input if its S break the loop
try below code for reference
public static void main(String[] args) {
PassportScan passportScan = new PassportScan();
Guard guard = new Guard();
while (true) {
Person person = passportScan.methodScan();
//checking if person object is null if ts null means s is enter
// break from loop
if(person==null) {
break;
}
String result = guard.checkPerson(person);
System.out.println(result);
}
}
static class PassportScan {
Scanner scanner = new Scanner(System.in);
public Person methodScan() {
System.out.println("Scanning gender");
String gender = scanner.next();
//check if string input is S or s
// then its returning null person object
if(gender.equalsIgnoreCase("s")) return null;
System.out.println("Scanning age");
int age = scanner.nextInt();
return new Person(gender, age);
}
}
one more way is to directly terminate in PassportScan class once S is typed
class PassportScan {
Scanner scanner = new Scanner(System.in);
public Person methodScan() {
System.out.println("Scanning gender");
String gender = scanner.next();
//check if string input is S or s terminating prog
if(gender.equalsIgnoreCase("s")) System.exit(0)
System.out.println("Scanning age");
int age = scanner.nextInt();
return new Person(gender, age);
}
}
You probably have some Component in that you display something, for example a (class that extends) JFrame, lets call it c.
Now call:
c.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if (Character.toLowerCase(e.getKeyChar()) == 's') System.exit(0);
}
#Override
public void keyReleased(KeyEvent e) {
}
});
It is not possible to catch a KeyEvent without a GUI (When you think about it, how should Java know that the key was pressed in your application? If it would catch any KeyEvent on the device, you could easily build spyware that catches passwords or sth.)
I am pretty new at Java and am just learning so please be kind.
I am doing a coding Inheritance challenge and I'm trying to use user inputs to set up a car before driving.
When I call the 2 methods I am using to set the parameters with Scanner this first method testCar.drivingTest() works fine, however when testCar.carAgeType() is called, I get an exception.
Below are the requests and inputs as well as the exception.
Would you like to test a used car today? : y or n
y
great , do you have a driving licence :type: big, medium or small
big
Great you passed your 'big' exam. Lets check the MOT : type: pass or fail
pass
What type of car were you looking for :type: sports , town or 4X4
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at learning.java.Car.carAgeType(Car.java:30)
at learning.java.Main.main(Main.java:17)
Process finished with exit code 1
From what I can gather searching google most people use .hasNextLine() to check something but I don't know what to do or why this is coming back as false on testCar.carAgeType. both methods use basically the same code and when I call only one of the methods testCar.carAgeType or testCar.drivingTest they work fine when on there own but when called one after the other I get the exception. I am also unsure what to do when I use .hasNextLine and it comes back false.
Can anyone help me understand why Scanner throws an exception when it is called in multiple methods?
All help is much appreciated, thanks.
Code sample bellow has main and 2 classes, Vehicle parent and car child
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner (System.in);
System.out.println("Would you like to test a used car today? : y or n");
if ("y".equals(scanner.nextLine())){
while (true) {
Car testCar = new Car();
testCar.drivingTest();
testCar.carAgeType();
break;
}
}else{
System.out.println("dang");
}
scanner.close();
}
}
import java.util.Scanner;
public class Vehicle {
private String licence, MOT;
public Vehicle(){
this("null", "null");
}
public Vehicle(String licence, String MOT) {
this.licence = licence;
this.MOT = MOT;
}
public String getLicence() {
return licence;
}
public String getMOT() {
return MOT;
}
public void drivingTest(){
Scanner DTScan = new Scanner (System.in);
System.out.println("great , do you have a driving licence :type: big, medium or small");
String reply = DTScan.nextLine();
if ("big".equals(reply) || "medium".equals(reply) || "small".equals(reply)) {
this.licence = reply;
} else {
this.licence = "fail";
}
System.out.println("Great you passed your '" + licence + "' exam. Lets check the MOT : type: pass or fail");
reply = DTScan.nextLine();
if ("pass".equals(reply) || "fail".equals(reply)) {
this.MOT = reply;
} else {
this.MOT = "invalid";
}
DTScan.close();
}
}
import java.util.Scanner;
public class Car extends Vehicle{
private String type;
private int age;
public Car(){
}
public Car(String licence, String MOT, String type, int age) {
super(licence, MOT);
this.type = type;
this.age = age;
}
public String getType() {
return type;
}
public int getAge() {
return age;
}
public void carAgeType(){
Scanner ATScan = new Scanner (System.in);
System.out.println("What type of car were you looking for :type: sports , town or 4X4");
ATScan.nextLine();
String reply = ATScan.nextLine();
if ("sports".equals(reply) || "town".equals(reply) || "4X4".equals(reply)) {
this.type = reply;
} else {
this.type = "invalid";
}
System.out.println("And what sort of Age :type: between 1 and 10");
int years = ATScan.nextInt();
if (years > 0 && years < 10) {
this.age = years;
} else {
this.age = -1;
}
ATScan.close();
}
}
class Main34 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Would you like to test a used car today? : y or n");
String val = scanner.nextLine();
if ("y".equals(val)) {
while (true) {
Car testCar = new Car();
testCar.drivingTest(scanner);
testCar.carAgeType(scanner);
break;
}
} else {
System.out.println("dang");
}
scanner.close();
}
}
class Vehicle {
private String licence, MOT;
public Vehicle() {
this("null", "null");
}
public Vehicle(String licence, String MOT) {
this.licence = licence;
this.MOT = MOT;
}
public String getLicence() {
return licence;
}
public String getMOT() {
return MOT;
}
public void drivingTest(Scanner scanner) {
System.out.println("great , do you have a driving licence :type: big, medium or small");
String reply = scanner.nextLine();
if ("big".equals(reply) || "medium".equals(reply) || "small".equals(reply)) {
this.licence = reply;
} else {
this.licence = "fail";
}
System.out.println("Great you passed your '" + licence + "' exam. Lets check the MOT : type: pass or fail");
reply = scanner.nextLine();
if ("pass".equals(reply) || "fail".equals(reply)) {
this.MOT = reply;
} else {
this.MOT = "invalid";
}
}
}
class Car extends Vehicle {
private String type;
private int age;
public Car() {
}
public Car(String licence, String MOT, String type, int age) {
super(licence, MOT);
this.type = type;
this.age = age;
}
public String getType() {
return type;
}
public int getAge() {
return age;
}
public void carAgeType(Scanner scanner) {
System.out.println("Enter age");
System.out.println("What type of car were you looking for :type: sports , town or 4X4");
String reply = scanner.next();
if ("sports".equals(reply) || "town".equals(reply) || "4X4".equals(reply)) {
this.type = reply;
} else {
this.type = "invalid";
}
System.out.println("And what sort of Age :type: between 1 and 10");
int years = scanner.nextInt();
if (years > 0 && years < 10) {
this.age = years;
} else {
this.age = -1;
}
}
}
Instead of creating Scanner object for every call, you just need to pass your existing scanner object to method.
Also instead of directly checking if ("y".equals(scanner.nextLine())) , you need to check using some variable like this if ("y".equals(val))
Try above code, it will work fine.
The problem comes from the fact that you use Scanner with System.in (which is a static InputStream). Whenever you call close() on a Scanner, it will automatically close the underlying InputStream, in this case System.in. Once System.in is closed, no other Scanner can read from it.
The solution to that problem is to don't close the Scanner in each of the functions and only do that in the main method.
From the Oracle documentation on the Scanner class:
When a Scanner is closed, it will close its input source if the source implements the Closeable interface.
This means that when your first method closes the scanner, it closes also the input (System.in) and that's why you get the exception and also why calling only one method doesn't throw the exception.
Just close only the first scanner you have in your main and it should solve your issue.
What i want to happen is to have the user input the age and have the program use the getters and setters while also checking for exceptions and if it does catch an exception it would have to run through the method again.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
TestPatient patientZero = new TestPatient();
patientZero.setAge(in.nextInt());
System.out.println(patientZero.getAge());
}
}
//
Patient class
import java.util.InputMismatchException;
import java.util.Scanner;
public class TestPatient {
private int age;
public int getAge(){
return age;
}
public void setAge(int newAge){
Scanner in = new Scanner(System.in);
int age;
boolean success = false;
try {
System.out.print("Enter in Your age:");
age = in.nextInt();
success = true;
} catch (InputMismatchException ex) {
System.out.println("Im sorry, please enter just you age.\nTry again");
}
this.age=newAge;
}
}
Your overall program structure could be improved as you're mixing your data structural code, e.g., the Patient class, with your I/O code, e.g., the Scanner input code. These should be completely separate, something like:
public class TestPatient {
private int age;
public int getAge(){
return age;
}
public void setAge(int newAge) {
this.age = newAge;
}
}
Then I/O can go elsewhere:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// get your data here and create your new TestPatient
}
Why is this important? You don't know in advance how you will eventually use your main code, and need to keep it open and flexible to be used in any I/O situation, including GUI if need be.
Also, your code will create a new Scanner object for each setter call, and that is a dangerous thing to do, since if a Scanner based on System.in is closed, then the program no longer can get input from the user.
Note also that it is OK to throw an exception from a setter method if the data being passed in is not allowed.
e.g.,
public void setAge(int newAge) {
if (newAge <= 0) {
String text = "for newAge is less than or equal to 0: " + newAge;
throw new IllegalArgumentException(text);
}
this.age = newAge;
}
Use a while loop. You also don't need the newAge parameter, as you are reading user input.
public void setAge(){
int age;
Scanner in = new Scanner(System.in);
boolean success = false;
while (!success) {
try {
System.out.print("Enter in Your age:");
age = in.nextInt();
success = true;
} catch (InputMismatchException ex) {
success = false;
System.out.println("Im sorry, please enter just you age.\nTry again");
}
}
this.age=age;
}
I have two methods 1st method has a object as a return type and 2nd method has integer as a return type.
I have some values in 1st method and some values in 2nd method
All i want to do is pass all these values to a single object.
But the problem is only values of 1st method is passing and the values from second method is not passing.I am practicing Encapsulation
Below is the code of two files and OUTPUT.
//Employee.java file
import java.util.*;
class Employee
{
private int employeeId;
private String employeeName;
private double salary;
private double netSalary;
/*public Employee()
{
}*/
public void setEmployeeId(int a)
{
employeeId = a;
}
public void setEmployeeName(String b)
{
employeeName = b;
}
public void setSalary(double c)
{
salary=c;
}
public int getEmployeeId()
{
return employeeId;
}
public String getEmployeeName()
{
return employeeName;
}
public double getSalary()
{
return salary;
}
public void calculateNetSalary(int pfpercentage)
{
netSalary = salary-((salary*pfpercentage)/100);
}
public double getNetSalary()
{
return netSalary;
}
}
import java.util.*;
class Main
{
public static Employee getEmployeeDetails(Employee e)//1st Method
{
Scanner sc=new Scanner (System.in);
try
{
System.out.println("Enter Id:");
e.setEmployeeId(sc.nextInt());
sc.nextLine();
System.out.println("Enter Name:");
e.setEmployeeName(sc.nextLine());
System.out.println("Enter salary:");
e.setSalary(sc.nextDouble());
sc.nextLine();
}catch(Exception e1){System.out.println("Invalid Input");}
return e;
}
public static int getPFPercentage()//2nd Method
{
Employee e = new Employee();
int pf=0;
Scanner sc1=new Scanner(System.in);
try
{
System.out.println("Enter PF percentage:");
pf=sc1.nextInt();
e.calculateNetSalary(pf);
}catch(Exception e1){System.out.println("Invalid Input");}
return pf;
}
public static void main(String args[])
{
Employee e = new Employee();
getEmployeeDetails(e);
getPFPercentage();
System.out.println();
System.out.println("Id : "+e.getEmployeeId());
System.out.println("Name : "+e.getEmployeeName());
System.out.println("Salary : "+e.getSalary());
System.out.println("Net Salary : "+e.getNetSalary());
}
}
OUTPUT
Enter Id:
101
Enter Name:
Harry
Enter salary:
20000
-------------1st method is used to take above input
Enter PF percentage:
7
-------------2nd method is used to take only PF percentage input
Id : 101
Name : Harry
Salary : 20000.0
Net Salary : 0.0
Calculation of Net salary is in file Employee.java function name "calculateNetSalary"
You have not calculated netSalary before calling method getNetSalary();
public void calculateNetSalary(int pfpercentage) //This function should be called first.
{
netSalary = salary-((salary*pfpercentage)/100);
}
public double getNetSalary()
{
return netSalary;
}
Look below code for better understanding:
System.out.println("Salary : "+e.getSalary());
e.calculateNetSalary(5); //Add this line and you will get the required output.
System.out.println("Net Salary : "+e.getNetSalary());
The problem is inside getPFPercentage() method you are creating a new Employee object. You should use the same object created in the main method.
public static int getPFPercentage(Employee e)//2nd Method
{
int pf=0;
Scanner sc1=new Scanner(System.in);
try
{
System.out.println("Enter PF percentage:");
pf=sc1.nextInt();
e.calculateNetSalary(pf);
}catch(Exception e1){System.out.println("Invalid Input");}
return pf;
}
public static void main(String args[])
{
Employee e = new Employee();
getEmployeeDetails(e);
getPFPercentage(e);
System.out.println();
System.out.println("Id : "+e.getEmployeeId());
System.out.println("Name : "+e.getEmployeeName());
System.out.println("Salary : "+e.getSalary());
System.out.println("Net Salary : "+e.getNetSalary());
}
In the 'getPFPercentage' method you are creating a new object but in the main method you are using a different object.
Pass the object that you have created in the main method to the getPFPercentage method
Change you getPFPercentage signature to
'public static int getPFPercentage(Employee e)'
Remove the object creation line in the getPFPercentage method
and call this method from the main method
- getPFPercentage(e)
List<Student> studentInfo = new LinkedList<Student>();
int choice;
boolean flag = true;
Student student = new Student();
while(flag)
{
System.out.println();
System.out.println("Press 1 to Add Student details");
System.out.println("Press 2 to Display Student details");
System.out.println("Press 3 to Sort");
System.out.println("Press 4 to Search");
System.out.println("Press 5 to Exit");
System.out.println("Enter your choice: ");
choice = sc1.nextInt();
switch(choice)
{
case 1: studentInfo.add(student.addDetails());
break;
case 2: System.out.println("Details of Students are as follows: ");
for(Student s : studentInfo){
System.out.println(s);
}
break;
//More code
The addDetails() method in the Student class is:
public Student addDetails()
{
System.out.println("Enter the name: ");
name = sc2.nextLine();
this.setName(name);
return this;
}
I'm using the case 1 block to take the student details and then adding them into the studentInfo collection. But, when i display the last entered details overwrites all the previous ones and when i print them out only that is displayed as many number of students that I've added. Can somebody tell me what is that I've done incorrectly? Thanks!
OUTPUT:
Details of Students are as follows:
name=Amar, age=0, semester=0, sub_1_marks=0, sub_2_marks=0, sub_3_marks=0, percentage=0, totalMarks=0
name=Amar, age=0, semester=0, sub_1_marks=0, sub_2_marks=0, sub_3_marks=0, percentage=0, totalMarks=0
The fact that you are unsure of the answer to this question implies that it's answer may change as your code develops. If you focus on the fact that your code develops as time goes on you will often see the right path.
To me, this code already has an issue. The fact that if you wanted to add a new menu option you would have to add code in two different places (the print list and the case statement).
I would start by pulling those two areas back together into a single list of actions. Something like this:
static boolean exit = false;
enum Action {
AddDetails("Add student details") {
#Override
public void doIt() {
// How to add details.
}
},
DisplayDetails("Display student details") {
#Override
public void doIt() {
// How to display details.
}
},
SortDetails("Sort") {
#Override
public void doIt() {
// How to sort details.
}
},
SearchDetails("Search") {
#Override
public void doIt() {
// How to search details.
}
},
Exit("Exit") {
#Override
public void doIt() {
// How to exit.
exit = true;
}
};
private final String description;
Action(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public abstract void doIt();
}
public static void main(String args[]) {
try {
Scanner sc1 = new Scanner(System.in);
do {
// Show my menu.
for (Action a : Action.values()) {
System.out.println("Press " + a.ordinal() + " to " + a.getDescription());
}
System.out.println("Enter your choice: ");
int choice = sc1.nextInt();
// Should really do some range checks here.
Action action = Action.values()[choice];
// Perform the chosen function.
action.doIt();
} while (!exit);
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
So - in answer to your question - use the static methods mechanism but only the concept. Enums are a good substitute if you have a number of distinct actions.