java: Confusing instructions on programming exam - java

Okay so don't get turned off by the fact that I want homework help.
Anyways, I don't want to explain the entire project for this little bit of help, but I'll just list some rules, and what I did with them. They're in weird order and they don't make complete sense. And there are many ways to do this probably, and I simply don't know what is what.
So here's the rules I'm confused about:
Three fields, a String for name of the purchase, int for units purchased, and a double for cost per unit.
So I made this:
private String purchase = "";
private int unitsPurchased = 0;
private double costPerUnit = 0;
Then, next rule:
Standard accessors and modifier methods for each field, so I made this:
//Accessors
public String purchase(){
return purchase;
}
public int unitsPurchased(){
return unitsPurchased;
}
public double costPerUnit(){
return costPerUnit;
}
//Modifiers
public void setPurchase(String purchase){
this.purchase = purchase;
}
public void setunitsPurchased(int unitsPurchased){
this.unitsPurchased = unitsPurchased;
}
public void setCostPerUnit(double costPerUnit){
this.costPerUnit = costPerUnit;
}
Then this: Negative values are not allowed, so change those to zero in all cases.
Wasn't sure if that meant to do anything, so I continued on.
Then this: Constructor to initialize these three fields (String, int, double) in that order.
So I did this:
public Purchase(String initialPurchase, int initialUnitsPurchased, double initialCostPerUnit){
purchase = initialPurchase;
unitsPurchased = initialUnitsPurchased;
costPerUnit = initialCostPerUnit;
}
Then this rule: Constructor overload, (String, double) assumes the int quantity is zero.
I didn't know if that meant anything, so once again I skipped it
Then this rule: Default constructor that assumes name is “” and numbers are zero, must call the three argument constructor.'
Now I'm just confused. So first of all, I would like to know if my code seems right. I don't think I need to explain the backstory of the program to do that. Then, I would love to know what to do about that last rule, because it says "must call the three argument constructor" am I supposed to use "this"? I didn't know where to go and I've tried a couple ideas but I don't think it works. I can't test to see if it's right either, given there's not really anything to test. Thanks so much to anyone who helps.
Here's just everything I've written:
public class Purchase {
private String purchase = "";
private int unitsPurchased = 0;
private double costPerUnit = 0;
//Accessors
public String purchase(){
return purchase;
}
public int unitsPurchased(){
return unitsPurchased;
}
public double costPerUnit(){
return costPerUnit;
}
//Modifiers
public void setPurchase(String purchase){
this.purchase = purchase;
}
public void setunitsPurchased(int unitsPurchased){
this.unitsPurchased = unitsPurchased;
}
public void setCostPerUnit(double costPerUnit){
this.costPerUnit = costPerUnit;
}
//Default constructor
public Purchase(){
purchase = "";
unitsPurchased = 0;
costPerUnit = 0;
}
//first constructor
public Purchase(String initialPurchase, int initialUnitsPurchased, double initialCostPerUnit){
purchase = initialPurchase;
unitsPurchased = initialUnitsPurchased;
costPerUnit = initialCostPerUnit;
}
//constructor overload
//Default constructor
}
You don't really need that but just in case. That's all a mess, not sure what I'm writing. But thanks to anyone that helps.

Starting with the first rule you didn't understand:
Negative values are not allowed, so change those to zero in all cases.
This is referring to the setter methods you wrote, and it means that if someone calls setUnitsPurchased with a negative number as a parameter, you only set unitsPurchased = 0.
You'll probably want to add an if statement (or ternary, if you're familiar with those) to setUnitsPurchased and setCostPerUnit checking for values below zero.
Wasn't sure if that meant to do anything, so I continued on. Then this: Constructor to initialize these three fields (String, int, double) in that order.
Instead of directly setting the values (like you did):
purchase = initialPurchase;
unitsPurchased = initialUnitsPurchased;
costPerUnit = initialCostPerUnit;
You should probably call your setters, so you don't have to repeat your checks:
this.setUnitsPurchased(initialUnitsPurchased);
// etc.
Constructor overload, (String, double) assumes the int quantity is zero.
If a class has an overloaded constructor, it means that you can initialize it with different amounts and/or types of parameters. You've already overloaded the constructor with an empty constructor and one that takes three arguments.
Simply make another constructor, but with this signature:
public Purchase(String initialPurchase, double initialCostPerUnit)
Default constructor that assumes name is "" and numbers are zero, must call the three argument constructor.
Instead of the default constructor you implemented, you must call the three argument constructor. To call another constructor, use the this keyword, and invoke it like a method, passing in the correct parameters:
this("", 0, 0);
Happy Coding!

Couldn't be more self-explanatory. It writes itself if you can read:
public class Purchase {
private String purchase;
private int numUnits;
private double costPerUnit;
public Purchase() {
this("", 0, 0.0);
}
public Purchase(String purchase, double costPerUnit) {
this(purchase, 0, costPerUnit);
}
public Purchase(String purchase, int numUnits, double costPerUnit) {
this.purchase = purchase;
this.numUnits = (numUnits < 0) ? 0 : numUnits;
this.costPerUnit = (costPerUnit < 0.0) ? 0.0 : costPerUnit;
}
// Leave the rest for you.
}

Three fields, a String for name of the purchase, int for units purchased, and a double for cost per unit.
You got it correct, though there is no need for assigning any values to the data members.
private String purchase;
private int unitsPurchased;
private double costPerUnit;
Standard accessors and modifier methods for each field
You got this correct too.
Negative values are not allowed, so change those to zero in all cases.
You need to change your code to convert neg values to zero. e.g.
public void setunitsPurchased(int unitsPurchased){
if(unitsPurchased < 0)
unitsPurchased = 0;
this.unitsPurchased = unitsPurchased;
}
Constructor to initialize these three fields (String, int, double) in that order.
You got this correct. Though you might want to have this keyword for data members. It just makes it more readable.
public Purchase(String initialPurchase, int initialUnitsPurchased, double initialCostPerUnit){
this.purchase = initialPurchase;
this.unitsPurchased = initialUnitsPurchased;
this.costPerUnit = initialCostPerUnit;
}
Constructor overload, (String, double) assumes the int quantity is zero.
This is simple. you want a constructor with just 2 arguments. It also specifies to have unitsPurchased set to 0.
public Purchase(String initialPurchase, double initialCostPerUnit){
this.purchase = initialPurchase;
this.unitsPurchased = 0;
this.costPerUnit = initialCostPerUnit;
}
Default constructor that assumes name is “” and numbers are zero, must call the three argument constructor.'
Now you know a default constructor does not take any arguments. but the question asks to call the three argument constructor from within this constructor. that can be done using the this() as follows:
public Purchase(){
this("", 0, 0.0);
}

Related

Why am I getting the error "cannot resolve method "x" in "x""?

The purpose of this program is to create a class and tester class for a select object(in my case a monitor), with at least one overloaded method. And in the client class, I have to instantiate at least three instances of the object. So far I believe I've finished the first class with the declaration of methods, getters and setters, and constructors. The problem occurs in my tester class, where I get the error "Cannot resolve method 'MonitorV82' in 'Monitor V82'. I don't know for sure why I'm getting this error, any advice?
My first class is:
public class MonitorV82
{
private double l;
private double h;
//one parameter constructor, all private instance variables initialized
public MonitorV82(double monitor1Height) {
//2.When this gets name1(jupiter), it designates "jupiter" to the variable "n"
h = monitor1Height;
l = (monitor1Height * 1.77);
}
//two parameter constructor
public MonitorV82(double monitor1Height, double monitor1Length){
//3.When this gets name1(jupiter), and a double, it sets jupiter to "n" and the diameter to "d"
h = monitor1Height;
l = monitor1Length;
}
public double getMon1height() { return h; }
public double getMon1Length() {
return l;
}
public void setMon1height(double name) { h = name; }
public void setMon1Length(double diam) {
l = diam;
}
public String monType(int resolution)
{
String monitType = "";
if (resolution == 1080) {
monitType = "lenovo";
} else if (resolution == 4000) {
monitType = "samsung";
}
return monitType;
}
//overloaded method
public String monType(int pixLength,int pixHeight)
{
String monitType = "";
if (pixHeight == 1080) {
monitType = "lenovo";
} else if (pixHeight == 4000) {
monitType = "samsung";
}
return monitType;
}
}
My tester class(where the error is) is:
public class V8Tester {
public static void main(String[] args) {
double length1 = 32.2;
double height1 = 51.8;
double length2 = 31.8;
double height2 = 50.6;
int resolution = 0;
MonitorV82 monit1 = new MonitorV82(length1);
resolution = monit1.MonitorV82(height1);
}
}
I am still learning Java in school so please don't roast me if something seems obvious or simple. Thank you for your help.
You are getting this error because there is no method MonitorV82, only a constructor. Also you are trying to instantiate the int variable resolution with a MonitorV82 object, which is not possible, because the compiler expects an int value.
If you want the resolution that refers to the pixel count of the MonitorV82 object with known pixel height, you first need to find out it's pixel length. You can do this by using your getMon1length() method and the calculate the resolution by length * height. Ultimately what I think you are trying to do is:
int heightMonit1 = monit1.getMon1height();
int resolution = (int)length1 * (int)heightMonit1;
You need to type cast, because you want to instantiate the int variable resolution with a calculation of double values.
You could however also use your second constructor and do:
MonitorV82 monit1 = new MonitorV82(length1, height1);
int resolution = (int)monit1.getMon1height() * (int)monit1.getMon1length();
Before answering the question in the title, you need the answer to this question:
What is a constructor in Java?
A constructor in Java is a special method used to "construct" (build, instantiate, etc.) objects. A constructor follows these basic rules:
The name of the constructor should match exactly the class name. In your case, MonitorV82 is this name.
A constructor doesn't have a return type. The new operator is responsible for returning a new object matching the type of the class in which the constructor is being invoked.
Knowing this, let's address the original question: Why the error? Because in MonitorV82 there is only a constructor a with matching name, but not a regular method with the same name. Consider my example below
public class Test {
private String name = "default";
// constructor #1
public Test() {}
// constructor #2
public Test(String name) {
this.name = name;
}
// method #1
public void Test() {
System.out.println(name);
}
// method #2
public void Test(String name) {
System.out.println(name);
}
}
Notice that in the code above, I have two constructors and two methods with the same name (matching case) and same parameters. This is allowed in Java although this is STRONGLY discouraged due to how confusing it can get.
What does this mean for you?
To create monit1, you need to invoke a CONSTRUCTOR. Once you construct the object, you cannot use it to invoke a constructor. You use objects to invoke non-static, accessible methods. Based on this, the line
MonitorV82 monit1 = new MonitorV82(length1);
is totally fine. However, the set resolution line is not resolution = monit1.MonitorV82(height1); because you have no METHOD named MonitorV82 (you just have a constructor with a matching name). You fix this by creating a method in your class that does exactly that. Since method names should be descriptive of their function, creating a method named setResolution or calculateResolution should be fine. What you should not do is used an ambiguous name; especially using the same name as the constructor.
Lastly, I will leave you with this small piece of advice: Just because the language allows you to do something, that does not mean that it is correct or OK to do so. My code example (along with this lengthy explanation) should've illustrated this point.
tl;dr
You asked:
Why am I getting the error "cannot resolve method "x" in "x""?
Because your last line tries to call a method named MethodV82 which does not exist on an instance of the class named MethodV82.
Details
Firstly, you should have indicated which line of code is causing that error.
You have at least one offending line, that last line. The code monit1.MonitorV82(height1) makes no sense. That code is trying to call a method named MonitorV82 on the instance named monit1. But of course there is no such method. Thus the error « Cannot resolve method ».
I cannot follow your logic, so I cannot give a fixed replacement code snippet.
I think you are misunderstanding the use of constructors.
I guess that what you want to do with your monit1.MonitorV82(height1) is to set the height of your monit1 instance to height1.
You need to call the setter to do so, not a constructor. The constructor is not known as a class method, that is why your error occurs. Use
monit1.setMon1height(height1);
Next, I think that you are trying to retrieve a resolution from your monitor, but you have no method inside of your MonitorV82 with this aim so I suggest that you create a method for this such as
public int computeResolution() {
return this.h * this.l;
}
In your test class you end up with:
public class V8Tester {
public static void main(String[] args) {
double length1 = 32.2;
double height1 = 51.8;
double length2 = 31.8;
double height2 = 50.6;
int resolution = 0;
MonitorV82 monit1 = new MonitorV82(length1);
monit1.setMon1height(height1);
resolution = monit1.computeResolution();
}
}
Edit: Even the instantiation of your monit1 does not seem correct. The only one parameter constructor you have is based on height and you are calling it with length1
Edit2: My example of computeResolution() will probably end up with an exception as I am returning an int from a compute action on doubles. But I think that it is not the main issue here

Am I using methods, constructors & getters right?

I have a class that calculates the mean of an ArrayList, and I'm wondering whether I have it set up correctly? I am still very new to Java, so what I want to end up with is just to take an ArrayList as a parameter, and return it within the main method using:
StatCalc stats = new StatCalc(someArrayList);
System.out.printf("Mean of someArrayList is: %.3f\n", stats.getAverage());
Here is the StatCalc class
public class StatCalc {
//declare inst variables & method
private double average = 0;
private double meanCalc(ArrayList<Double> myList) {
double sum = 0;
if (!myList.isEmpty()) {
for (Double element : myList) {
sum += element;
}
}
return sum / myList.size();
}
//Constructor
public StatCalc(ArrayList<Double> myList) {
double average = meanCalc(myList);
this.average = average;
}
//getter
public double getAverage() {
return average;
}
}
I am just wondering is this is how it's 'supposed' to be done in Java, as before I had the meanCalc method inside the constructor, which worked but I thought was bad practice?
In your constructor, you are declaring average as constructor-scoped.
Just remove double from: double average = meanCalc(myList);
That will assign your instance field, instead of a variable with the same name inside your constructor.
In turn, the getAverage() method will return instance field average after it's been assigned, instead of its default value as unassigned, which is 0.0.
In short:
//Constructor
public StatCalc(ArrayList<Double> myList) {
average = meanCalc(myList);
}
Final note
If you are delivering a functionality that only depends on the parameters given, you can probably do without creating an instance of your class.
You could simply have a static method returning double and taking a List<Double> as parameter.
FYI, under java 8+, all your code can be replaced by only one line :
List<Double> list = new ArrayList<>();
[...]
OptionalDouble average = list.stream().mapToDouble(Double::doubleValue).average();

Error With Big Decimal in Java

I keep getting the
The method add(BigDecimal) in the type BigDecimal is not applicable for the arguments (pay)"
error with the code below.
For reference I have saved the pay class in a separate file, where I import BigDecimal as well.
Would one of you like to point out where I'm lacking/misunderstanding? I've tried to find a solution, but I couldn't find something.
import java.util.Scanner;
import java.math.BigDecimal;
class SalesPreInt {
public static void main(String[] args) {
Pay pay = new Pay();
pay.basePay();
BigDecimal intCalc = new BigDecimal("0.15");
Scanner userInput = new Scanner(System.in);
System.out.println("What were your total sales?");
BigDecimal salesPre = userInput.nextBigDecimal();
System.out.println("You're Total Sales were "+salesPre);
userInput.close();
BigDecimal postIntCalc = salesPre.multiply(intCalc);
BigDecimal salesCom = postIntCalc.add(salesPre);
int finalCalc = salesCom.add(pay);
System.out.println("Your total sales including commission is "+salesCom);
System.out.println("Your total pay is"+finalCalc);
}
}
pay.java file below:
import java.math.BigDecimal;
public class Pay {
public void basePay() {
int basePay = 50000;
BigDecimal bd = new BigDecimal(String.valueOf(basePay));
}
}
Like the error message tells you, the add method of BigDecimal with one argument expects a BigDecimal instance: [javaDoc]
public BigDecimal add(BigDecimal augend)
Returns a BigDecimal whose value is (this + augend), and whose scale
is max(this.scale(), augend.scale()).
Parameters:
augend - value to be added to this BigDecimal.
Returns:
this + augend
You've passed a variable of type Pay to this method and since Pay is not a subtype of BigDecimal it is not related to it. The method add can't know how to add a Pay instance, the compiler complains about that argument type.
You can do the following fix, to bypass that problem:
Your basePay method creates a BigDecimal and I guess this is the one you like to add to salesCom, so change that method a bit:
public BigDecimal basePay() {
int basePay = 50000;
return new BigDecimal(String.valueOf(basePay));
}
This method now creates a BigDecimal and returns it to the calling method. Now change the add method call to use the basePay method:
int finalCalc = salesCom.add(pay.basePay());
Now there is only one problem left. As you can see in the JavaDoc posted above, add returns a new BigDecimal instance, but you're assigning the returned value to the variable finalCalc, which is of type int. So we need to change it to BigDecimal:
BigDecimal finalCalc = salesCom.add(pay.basePay());
Now your code compiles and it should work as expected.
If you want the Pay class to return a basePay value, you need a proper method for that, ie a method that actually returns the value, ie not a void method.
public class Pay {
private int basePay = 50000;
public BigDecimal getBasepay() {
// no need to pass via strings, BigDecimal has a constructor that takes an int value
BigDecimal bd = new BigDecimal(basePay);
return bd;
}
}
which will be called like
int finalCalc = salesCom.add(pay.getBasepay()).intValue();
as you want to store the result as an integer, or
BigDecimal finalCalc = salesCom.add(pay.getBasepay());
Notice that I declared basePay - the value - as a private member of the Pay class, and renamed the method to start with get (called a getter in Java, and by convention their names are prefixed with get). If some day you need a way to modify that value, just add a setter
public void setBasepay(int bp) {
basePay = bp;
}
And maybe you also want to be able to set the value directly as a BigDecimal although it's stored as an int? Just add
public void setBasepay(BigDecimal bp) {
basePay = bp.intValue();
}
Two methods with the same name but other arguments is called overloading, and that's an often-used mechanism to introduce flexibility and versatility in your programs.
I would also suggest you have a look at a good tutorial, the official one by Oracle is pretty good (and free :))

How to pass objects that are not of a primitive type (string, int, double, etc) in Java with private access modifier

I am trying to build a complete program from the partial code of a book. The difficulty is when a variable's modifier is set to private, I can't access it from the main method of my BankTest class after instantiating an object. Am confused on how to pass the Dollar Object as I can't set it to a primitive type like double or float.
Is there a way to set the Dollar object with amount = 100, so that when I run the BankTest class, I could get it to print the getAmount = 100 ? I want to maintain the Dollar object as the parameter of a method if possible ?
final class BankTest {
public static void main(String args[]) {
BankAccount ba = new BankAccount();
Dollar d = new Dollar(100);
//d.setAmount(100.00); "IF class Dollar method is PUBLIC"
//ba.deposit(d); "How to set the value of Dollar Object ??
System.out.println("Balance available: " + d.getAmount());
}
}
final class BankAccount {
private Dollar balance;
private boolean receipt;
public void deposit(Dollar amount, boolean receipt) {
balance.add(amount);
// if receipt == true, print receipt
}
public void deposit(Dollar amount) {
// validate and chain to base method
deposit(amount, true);
}
}
final class Dollar {
private double amount = 0;
public Dollar(double _amount) {
setAmount(_amount);
}
private void setAmount(double amt) { //can only be called by within Dollar class
// make sure amt is a valid currency amount
amount= amt;
}
double getAmount() {
return amount;
}
public void add(Dollar amt) {
// validate amt
amount+= amt.getAmount();
}
}
It seems Dollar was created to not be modified, but I wonder why the attribute is not final and why it can be modified by adding another Dollar object...
The idea is you have to create a new instance of Dollar every time you need a new value. Something similar happens with String and any primitive wrapper class (Integer, Float...).
As you are taking the code from a book you can decide how to deal with it: you can make the setter public or you can live with the current status and create a new object when needed.
You can already add an amount, so I think I'd modify the setter to public
Simply make setAmount public.
And also add a getter. eg getAmout() that returns the current dollar value.
Setters and getters are meant to be public, else they are pointless.
You could also pass the dollar value in the constructor.

Constructor and different data types are confusing

I am passing a string through the constructor and assigning its value to a Grade type object class variable. I know it's very simple but I can't figure out to make this work. I cannot modify the variables or the constructor arguments, only implement the constructor.
I looked through the methods from string but couldn't figure out after an hour what to do. casting/converting/ idk
public class Course
{
private String courseNumber;
private int numberOfCredits;
private Grade gradeReceived;
private String termWhenTaken;
/**
* The value for the courseNumber instance variable is converted to uppercase.
* The numberOfCredits instance variable is set to the credits passed as a parameter if it's 0 or more.
* Otherwise, it gets set to 0.
*/
public Course(String course, int credits, String grade, String term)
{ courseNumber = course.toUpperCase();
numberOfCredits = credits;
termWhenTaken = term;
gradeReceived = grade; <-----problem here mismatched data types obviously
}
You can't assign an object of type A to a reference variable of type B (unless A is a subclass of B). You can't assign a String to a Grade.
You will need to create a Grade using the String:
gradeReceived = new Grade(grade);
The new operator calls the constructor public Grade(String grade) and returns a new Grade object.
You're going to need some sort of converter or mapping to convert a String value (say, "6th") to a Grade object. Something like this could get you started:
public Course(String course, int credits, String grade, String term) {
...
gradeReceived = convertGradeStringToGrade(grade);
...
}
private Grade convertGradeStringToGrade(String gradeStr) {
if ("A".equals(gradeStr)) {
return new Grade("A");
} else if ("B".equals(gradeStr)) {
return new Grade("B");
} else if ... etc
} else {
// do something (throw an exception? return null?) if the string doesn't match a known grade
}
}
Or you could just do something like
public Course(String course, int credits, String grade, String term) {
...
gradeReceived = new Grade(grade);
...
}
if there isn't any conversion to be done.
You could also use an enum for your Grade object, but that might be beyond the scope of what you're trying to do currently.

Categories