Alright so I am doing an exercise where I have an object that contains scores for 3 tests.
I then have a set-function that takes 2 arguments, the test number and the score you set to it.
Right now my problem is that I do not know how to make the test number argument work correctly.
The code works if I do test1 = score, but when I put student1.test1 in the set argument, for some reason it does not register.
I hope you can point me in the right direction, I would be really grateful!
I have a main class and a student class:
public class Main {
public static void main(String[] args) {
Student student1 = new Student();
student1.setTestScore(student1.test1, 50);
System.out.print(student1.test1);
}
}
public class Student {
int test1;
int test2 = 0;
int test3;
Student() {
int test1 = 0;
int test2 = 0;
int test3 = 0;
}
public void setTestScore(int testNumber, int score){
testNumber = score;
}
}
Java is a pass by value language, so when you pass student1.test1 to student1.setTestScore, you are passing a copy of that member. You are not passing a reference to the member. Therefore the method can't change the member's value.
Even if the language allowed such modification, it would be a bad idea in terms of object oriented programming, since you normally make members private and don't access them directly from outside the class.
A possible alternative is to use an array :
public class Student {
int[] test = new int[3];
...
public void setTestScore(int testNumber, int score){
if (testNumber >= 0 && testNumber < test.length)
test[testNumber]=score;
}
...
}
and you'd call the method like this :
student1.setTestScore(0, 50); // note that valid test numbers would be 0,1 and 2
Related
I am practising dynamic coding so I want to create a list for class. I hereby Initialized a list for class and want to create an array with different length for each iteration in list. But It doesnt initialize it like I expected instead its length says 0.
import java.io.*;
import java.util.*;
class testcase
{
int N;
int play []= new int [N];
int villain[]=new int [N];
String status;
}
public class Main {
public static void main(String args[] ) throws Exception {
List<testcase> caseno=new ArrayList<testcase>();
Scanner sc=new Scanner(System.in);
int n1=1;
//int n1=sc.nextInt();
int i,j;
testcase t;
for(i=0;i<n1;i++)
{
int n=6;
//int n=sc.nextInt();
t=new testcase();
t.N=n;
System.out.println(t.N+" "+t.play.length);
}
}
}
The array length should print 6 instead it shows 0
You have to create a parametrized constructor in which you'll pass the value of N and then initilaze the arrays. Like
class testcase // Name should be in PASCAL
{
int N;
int [] play;
int [] villain;
String status;
public testcase (int n) { // Constructor
this.N=n;
play = new int [N];
villain=new int [N];
}
}
And in the main methos you create object like this
int n= . . .;//taking input from user
testcase t=new testcase(n);
You need to write a constructor which does these assignment based on the value passed.
// Implement your constructor something like this
public Testcase(int value) {
this.N = value;
play = new int [value];
// Some more assignment based on the need
}
And after that, you need to create the object instance
int N = 6;
Testcase newTestcase = Testcase(N);
NOTE: Clase name should always start with a capital letter.
Try declaring these variable like N, status, play e.t.c as private. After that assign and access them using getter() and setter().
For a class project I was asked to create three codes.
Student Class
First, the student class containing three Parameters.
Name(String)
TestScores( int array),
Grade(String).
An empty Constructor. sets the Name and Grade to empty Strings. The TestScores Array will be initialised with three zeros.
Another Constructor(String n, int[] tests, String g)- This will set the name, testScores, and grade.
Three methods:
getName() to return the name
getGrade() to return the grade
setGrade() to set grade
getTestAverage() to return the average of the test scores.
This is where I am having difficulty The method computeGrade(), which, if the average is greater than or equal to 65, the grade is a "Pass". Otherwise it is a "Fail".
The second class is called UnderGrad. This class is a subclass of Student.
We had to create an empty Constructor and another Constructor (String n, int[] tests, String g).
We were instructed to override the computeGrade() method so that an UnderGrad() student must get a 70 or higher to pass.
The third class is the GradStudent a subclass of Student.
We have to create 1 instance variable, int MyGradID, and an empty constructor, which calls super, and set the IDs to 0.
And another constructor (String n, int[] tests, String g, int id)- Remember to call the super constructor and set ID.
Again where I am having challenges. We had to write the method getId(), to return the ID number. Again we needed to override the computeGrade() method And, if the average is greater than or equal to 65, the grade is a "Pass". Otherwise it is a "Fail". But if the test average is higher than 90, the grade should be "Pass with distinction".
I have great difficulty with this task. I attached the GradStudent code. Can you find the errors please? I don't fully understand how to override the superclass private instance variables.
public class GradStudent extends Student {
private int MyGradID;
public void GradStudent() {
super();
MyGradID = 0;
}
public void GradStudent(String n, int[] tests, String g, int id) {
super(n, tests, g);
MyGradID = id;
}
public int getId() {
return MyGradID;
}
#Override public void computeGrade() {
if (testScores.getTestAverage() >= 65) {
super.setGrade("Pass");
} else if (testScores.getTestAverage() > 90) {
grade = "Pass with distinction";
}
}
}
This is my Student class. I'm not sure if I am referencing my super class correctly, so I am adding it. Hopefully you can explain it to me.
public class Student {
private String name;
private int[] testScores = new int[3];
private String grade;
public Student() {
name = "";
grade = "";
testScores[0] = 0;
testScores[1] = 0;
testScores[2] = 0;
}
public Student(String n, int[] tests, String g) {
name = n;
testScores = tests;
grade = g;
}
public String getName() {
return name;
}
public String getGrade() {
return grade;
}
public void setGrade(String newGrade) {
grade = newGrade;
}
public int getTestAverage() {
int average = 0;
int count = 0;
for (int testScore : testScores) {
count++;
average = average + testScore;
}
return average / testScores.length;
}
public void computeGrade() {
grade = "Fail";
if (this.getTestAverage() >= 65) {
grade = "Pass";
}
}
}
This question simply wouldn't exist if you had an IDE (or, looked at the feedback from compile). I pasted the code into Eclipse and out popped a lot of problems.
Let's look at GradStudent.
public class GradStudent extends Student {
private int MyGradID;
// Constructors do not return anything.
public GradStudent() {
super();
MyGradID = 0;
}
// Again, constructors do not return anything.
public GradStudent(String n, int[] tests, String g, int id) {
super(n, tests, g);
MyGradID = id;
}
public int getId() {
return MyGradID;
}
// Okay. Override annotation in place. Now, computeGrade() needs to get its data from someplace. Fortunately, we
// have a method in Student to do that for us. That method is called 'getTestAverage()'. You do not need to
// reference the array created in 'Student'.
#Override public void computeGrade() {
int testAverage = getTestAverage();
if (testAverage >= 65) { // Evaluate against that testAverage. There is no method (or parameter) associated
// with an array that will compute its average.
setGrade("Pass");
} else if (testAverage > 90) {
setGrade("Pass with distinction");
}
}
}
The Student class is just fine (though count in getTestAverage() is a pointless variable which doesn't do anything and an int[] is created with all values being initialised to 0).
Now I would question why the instructor would have told you to create a constructor to set the grade... when you don't actually know what the grade is... but whatever.
Where are you having trouble with the computeGrade() method in Student? It seems fine to me. The problem in GradStudent is fixed given the changes made above.
What jumps out at me is
if(testScores.getTestAverage>=65)
Try changing that to
if(testScores.getTestAverage()>=65)
Easy mistake to make. Hope this helps!
Edit - I see that twice.
Also, I don't think constructors should have a return type void (or any) though I could be wrong.
in my class SummerStats I need to create another method that locates the largest element of the array created in my method setSalaries. How can I call the array, "salaries" to another method in the same class?
class SummerStats
{
public SummerStats()
{
}
public int[][] setSalaries(int people, int years)
{
int[][] salaries = new int[people][years];
//rows respresent people and columns represent years
for (people = 0; people < salaries.length; people++)
{
for (years = 0; years < salaries[people].length; years++)
{
salaries[people][years] = (int)(1000 + Math.random()*1000);
}
}
return salaries;
}
Also, my test class is
import java.util.*;
public class testSummerStats
{
public static void main (String[] args)
{
Scanner input = new Scanner(System.in);
SummerStats one = new SummerStats();
System.out.println("Enter people, then years: ");
int x = input.nextInt();
int y = input.nextInt();
one.setSalaries(x, y);
}
}
setSalaries should not return the array. Assign the array to a field of SummerStats instead. Then add another method to SummerStats for locating the largest element.
Declare your 2D-Array as a member variable. This way it will be accessible to all the methods of the class:
class SummerStats
{
private int[][] salaries;
public SummerStats()
{
}
public void setSalaries(int people, int years)
{
salaries = new int[people][years]; // initialize the array
//rows respresent people and columns represent years
for (people = 0; people < salaries.length; people++)
{
for (years = 0; years < salaries[people].length; years++)
{
salaries[people][years] = (int)(1000 + Math.random()*1000);
}
}
}
public void locateMax() {
// Your code goes here. (You can access the salaries array)
}
}
Then create a new method (locateMax i.e) that will calculate the max number of the 2D-array.
you can assign your array to a field. and access it outside. or second option you can pass pass this array to new method and there you can do operations for finding out largest element.
Your current program:
class SummerStats
{
public SummerStats()
{
}
public int[][] setSalaries(int people, int years)
**{**
int[][] salaries = new int[people][years];
....
return salaries;
**}**
}
Solution:
class SummerStats
**{**
private int[][] salaries;
public SummerStats()
{
}
public int[][] setSalaries(int people, int years)
{
salaries = new int[people][years];
....
return salaries;
}
**}**
In your current program is the variable salaries declared as a local variable of the method setSalaries and therefore its scope is limited to the scope of the method. In the solution program is the variable salaries declared as a member variable/field of the class SummerStats and therefore its scope is limited to the scope of all member method/variable declarations of the class.
I'm in a beginning programming class, and a lot of this had made sense to me up until this point, where we've started working with methods and I'm not entirely sure I understand the "static," "void," and "return" statements.
For this assignment in particular, I thought I had it all figured out, but it says it "can not find symbol histogram" on the line in the main method, although I'm clearly returning it from another method. Anyone able to help me out?
Assignment: "You see that you may need histograms often in writing your programs so you decide for this program to use your program 310a2 Histograms. You may add to this program or use it as a class. You will also write a class (or method) that will generate random number in various ranges. You may want to have the asterisks represent different values (1, 100, or 1000 units). You may also wish to use a character other than the asterisk such as the $ to represent the units of your graph. Run the program sufficient number of times to illustrate the programs various abilities.
Statements Required: output, loop control, decision making, class (optional), methods.
Sample Output:
Sales for October
Day Daily Sales Graph
2 37081 *************************************
3 28355 ****************************
4 39158 ***************************************
5 24904 ************************
6 28879 ****************************
7 13348 *************
"
Here's what I have:
import java.util.Random;
public class prog310t
{
public static int randInt(int randomNum) //determines the random value for the day
{
Random rand = new Random();
randomNum = rand.nextInt((40000 - 1000) + 1) + 10000;
return randomNum;
}
public String histogram (int randomNum) //creates the histogram string
{
String histogram = "";
int roundedRandom = (randomNum/1000);
int ceiling = roundedRandom;
for (int k = 1; k < ceiling; k++)
{
histogram = histogram + "*";
}
return histogram;
}
public void main(String[] Args)
{
System.out.println("Sales for October\n");
System.out.println("Day Daily Sales Graph");
for (int k = 2; k < 31; k++)
{
if (k == 8 || k == 15 || k == 22 || k == 29)
{
k++;
}
System.out.print(k + " ");
int randomNum = 0;
randInt(randomNum);
System.out.print(randomNum + " ");
histogram (randomNum);
System.out.print(histogram + "\n");
}
}
}
Edit: Thanks to you guys, now I've figured out what static means. Now I have a new problem; the program runs, but histogram is returning as empty. Can someone help me understand why? New Code:
import java.util.Random;
public class prog310t
{
public static int randInt(int randomNum) //determines the random value for the day
{
Random rand = new Random();
randomNum = rand.nextInt((40000 - 1000) + 1) + 10000;
return randomNum;
}
public static String histogram (int marketValue) //creates the histogram string
{
String histogram = "";
int roundedRandom = (marketValue/1000);
int ceiling = roundedRandom;
for (int k = 1; k < ceiling; k++)
{
histogram = histogram + "*";
}
return histogram;
}
public static void main(String[] Args)
{
System.out.println("Sales for October\n");
System.out.println("Day Daily Sales Graph");
for (int k = 2; k < 31; k++)
{
if (k == 8 || k == 15 || k == 22 || k == 29)
{
k++;
}
System.out.print(k + " ");
int randomNum = 0;
int marketValue = randInt(randomNum);
System.out.print(marketValue + " ");
String newHistogram = histogram (randomNum);
System.out.print(newHistogram + "\n");
}
}
}
You're correct that your issues are rooted in not understanding static. There are many resources on this, but suffice to say here that something static belongs to a Class whereas something that isn't static belogns to a specific instance. That means that
public class A{
public static int b;
public int x;
public int doStuff(){
return x;
}
public static void main(String[] args){
System.out.println(b); //Valid. Who's b? A (the class we are in)'s b.
System.out.println(x); //Error. Who's x? no instance provided, so we don't know.
doStuff(); //Error. Who are we calling doStuff() on? Which instance?
A a = new A();
System.out.println(a.x); //Valid. Who's x? a (an instance of A)'s x.
}
}
So related to that your method histogram isn't static, so you need an instance to call it. You shouldn't need an instance though; just make the method static:
Change public String histogram(int randomNum) to public static String histogram(int randomNum).
With that done, the line histogram(randomNum); becomes valid. However, you'll still get an error on System.out.print(histogram + "\n");, because histogram as defined here is a function, not a variable. This is related to the return statement. When something says return x (for any value of x), it is saying to terminate the current method call and yield the value x to whoever called the method.
For example, consider the expression 2 + 3. If you were to say int x = 2 + 3, you would expect x to have value 5 afterwards. Now consider a method:
public static int plus(int a, int b){
return a + b;
}
And the statement: int x = plus(2, 3);. Same here, we would expect x to have value 5 afterwards. The computation is done, and whoever is waiting on that value (of type int) receives and uses the value however a single value of that type would be used in place of it. For example:
int x = plus(plus(1,2),plus(3,plus(4,1)); -> x has value 11.
Back to your example: you need to assign a variable to the String value returned from histogram(randomNum);, as such:
Change histogram(randomNum) to String s = histogram(randomNum).
This will make it all compile, but you'll hit one final roadblock: The thing won't run! This is because a runnable main method needs to be static. So change your main method to have the signature:
public static void main(String[] args){...}
Then hit the green button!
For starters your main method should be static:
public static void main(String[] Args)
Instance methods can not be called without an instance of the class they belong to where static methods can be called without an instance. So if you want to call your other methods inside the main method they must also be static unless you create an object of type prog310t then use the object to call the methods example:
public static void main(String[] Args)
{
prog310t test = new prog310t();
test.histogram(1);
}
But in your case you probably want to do:
public static String histogram (int randomNum)
public static void main(String[] Args)
{
histogram(1);
}
Also you are not catching the return of histogram() method in your main method you should do like this:
System.out.print(histogram(randomNum) + "\n");
Or
String test = histogram(randomNum);
System.out.print(test + "\n");
Static methods are part of a class and can be called without an instance but instance methods can only be called from an instance example:
public class Test
{
public static void main(String[] args)
{
getNothingStatic();// this is ok
getNothing(); // THIS IS NOT OK IT WON'T WORK NEEDS AN INSTANCE
Test test = new Test();
test.getNothing(); // this is ok
getString(); // this is ok but you are not capturing the return value
String myString = getString(); // now the return string is stored in myString for later use
}
public void getNothing()
{
}
public static void getNothingStatic()
{
}
public static String getString()
{
return "hello";
}
}
Void means the method is not returning anything it is just doing some processing. You can return primitive or Object types in place of void but in your method you must specify a return if you don't use void.
Before calling histogrom (randomNum) you need to either make histogram static or declare the object that has histogram as a method
e.g
prog310t myClass = new prog310t();
myClass.histogram()
Not to sure why the integers lowRange and highRange are not going between these classes.
package guessnumber;
public class GuessNumber
{
static public int computerGenedNumber;
static public int lowRange;
static public int highRange;
static public int playerGuess;
public static void main(String[] args)
{
Input.range(lowRange, highRange);
Rand.number(lowRange, highRange, computerGenedNumber);
Input.guess();
Give.result();
}
}
Next Class:
package guessnumber;
import javax.swing.JOptionPane;
class Input
{
public static void range(int lowRange, int highRange)
{
String rawUserInput;
rawUserInput = JOptionPane.showInputDialog("Please enter the range you wish to guess. (EX: 1-10)", "1-10");
for(int i = 0; i < rawUserInput.length(); i++)
{
if(rawUserInput.charAt(i) == '-')
{
lowRange = Integer.parseInt(rawUserInput.substring(0, i));
highRange = Integer.parseInt(rawUserInput.substring(i + 1, rawUserInput.length()));
}
}
}
static void guess()
{
}
}
And the last relevant one:
package guessnumber;
class Rand
{
static public void number(int lowRange, int highRange, int computerGenedNumber)
{
computerGenedNumber = (int)(Math.random() * (highRange - lowRange) + lowRange);
}
}
The rest of the classes are currently blank so I don't think I need to put them here too.
Here is a simplified piece of code which reproduce your problem, and make sure you understand why it is causing problem and the solution:
class Foo {
public static void square(int a, int result) {
result = a*a;
}
}
class Bar {
public static void main(String[] args) {
int a=2;
int result = 0;
Foo.square(a, result);
System.out.println("result " + result);
}
}
This should be fundamental understanding of Java. Checkout what is the meaning of "pass-by-value"
In brief, the parameter passed in the method is a copy of the argument. Therefore when you are changing the parameter in your method, you are just changing another piece of data, and your change is not reflected to caller.
One way to fix is to change the method and return your result, which looks like:
class Foo {
public static int square(int a) {
return a*a;
}
}
class Bar {
public static void main(String[] args) {
int a=2;
int result = 0;
result = Foo.square(a);
System.out.println("result " + result);
}
}
Another common solution is to pass in a "holder object" as the result. Although the object reference is passed by value, that copy of object reference is still pointing to the same object as caller. I won't go too deep into this as it is less common and you should be able to get the proper way doing so once you have better understanding on how value (including object reference) is passed around.
Parameters are passed "by value" in Java. What that means is that when you call
input.range(lowRange, highRange);
it gives the current values of those variables to input.range, but it doesn't give input.range a way to modify them. In the range method:
public static void range(int lowRange, int highRange)
the parameters lowRange and highRange (which have no connection with the variables in GuessNumber, even though the names are the same) are copies of what you pass in. When you assign lowRange = ... in the method, it changes the copy but has no effect at all on the lowRange and highRange in GuessNumber.
You need to write a range method that returns two values. This needs a little bit of work, but I'd write a Range class that has low and high members, and then change your method to
public static Range range()
That method would have to create a new Range object. I think it's OK for low and high to be public members of Range:
class Range {
public int low;
public int high;
public Range(int low, int high) {
this.low = low;
this.high = high;
}
}
Normally, public data in a class is a bad thing, but for a class whose only purpose is to let a method return multiple values, it's OK in my opinion.