This question already has an answer here:
Beginner Java: Variable Scope Issue
(1 answer)
Closed 7 years ago.
I'm new to programming and seem to be running into issues with when a variable, class, etc can and can't be referenced. Below is an example, hoping one of you can fix the specific issue but also help me understand it more broadly so I don't run into it again and again.
to try and avoid posting a bunch of code please note that a Question class is defined as well as a setText, setAnswer, checkAnswer, and display method are all defined elsewhere (all public).
The relevant code is below and I have two questions:
Why is the variable first not recognized in the method presentQuestion()?
At the very end there, why can't I just call the method checkAnswer() on first, i.e. why can't I just do first.checkAnswer(response);? Why do I have to define it in a new variable: boolean outcome = first.checkAnswer(response);?
Code:
/**
* This program shows a simple quiz with two questions.
*/
public class QuestionDemo {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Question first = new Question();
first.setText("Who was the inventor of Java?");
first.setAnswer("James Gosling");
Question second = new Question();
second.setText("Who was the founder of Udacity?");
second.setAnswer("Sebastian Thrun");
int score = 0;
score = score + presentQuestion(first, in);
// Present the second question
score = score + presentQuestion(second, in);
System.out.println("Your score: " + score);
}
/**
* Presents a question to the user and obtains a response.
* #param q the question to present
* #param in the scanner from which to read the user input
* #return the score (1 if correct, 0 if incorrect);
*/
public static int presentQuestion(Question q, Scanner in) {
// Display the first question
first.display();
System.out.println("Your answer:");
String response = in.nextLine();
// Check whether the response was correct
// If so, print "true" and return 1
// Otherwise, print "false" and return 0
boolean outcome = first.checkAnswer(response);
System.out.println(outcome);
if (outcome) {
return 1;
}
else {
return 0;
}
}
}
The reason you can't use the variable first inside presentQuestion is because it's defined in main, and therefore not visible outside of main. Isn't this precisely why you gave presentQuestion its Question q parameter, however?
It seems to me that this is what you want to do:
public static int presentQuestion(Question q, Scanner in)
{
// Display the first question
q.display();
System.out.println("Your answer:");
String response = in.nextLine();
// Check whether the response was correct
// If so, print "true" and return 1
// Otherwise, print "false" and return 0
boolean outcome = q.checkAnswer(response);
System.out.println(outcome);
if (outcome) {
return 1;
} else {
return 0;
}
}
Note that references to first have been replaced by references to q.
To try and clear up what I imagine your confusion may consist in, imagine if presentQuestion were called from another method than main, in which case no first variable would be declared at all. What would then happen to the references to first inside of presentQuestion, now not referring to anything at all? This is why you need to explicitly pass the data you want as parameters. Different methods are independent blocks of code, and you can't intermingle variable references between them even if they happen to call each other.
As for question 2, there should indeed be no problem with checking if(q.checkAnswer(response)) directly, without using the outcome variable. I'm guessing you were simply confused by the error emitted by the compiler when first wasn't recognized again.
first is a local variable, that means it can only be accessed inside the method in which it is defined.
You don't have to put the result of checkAnswer() into a boolean before using it. Actually, if (checkAnswer(response)) { ... } is valid.
presentQuestion takes a question as a parameter. In main, you're calling it on the first question, and then on the second question; it looks like the intent is that you use presentQuestion on the first question, and then on the second question. So far, so good.
The problem is that in presentQuestion, you're referring to the question (which could be the first or the second question) as q in the parameter list. All you need to do is use q instead of first in the rest of the method.
When I was new to programming, I had this problem as well! Then I found out it is very simple.
For your first question, first is declared in the main method and you want to use it in presentQuestion method. But presentQuestion and main are different methods! So you can't get to first in presentQuestion. As you can see, there is a Question-typed parameter in the presentQuestion method. This is like you telling first, "Come here, man! And then change your name to q." When you do pass the argument first to presentQuestion,
presentQuestion (first, in);
first comes to the pressentQuestion method with its name being as q. So you should use q instead of first in the presentQuestion method.
Now the second question, using a variable in this context is not needed. But to increase efficiency, use a boolean variable to store the result of checkAnswer. Let's imagine what happens if you don't use a boolean variable.
System.out.println(q.checkAnswer(response));
if (q.checkAnswer(response)) {
return 1;
} else {
return 0;
}
See? you called q.checkAnswer twice! This would slow down your program so you should use a boolean variable.
Related
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 4 years ago.
So I'm a scrub at java, just started learning the language at a university course.
While trying to compare values of variables linked to objects to inserted values to make sure that there are no duplicates, I ran into an issue. It appears as if the objects are "lagging behind" in the lack of a better expression. See the commenting of the code for a better explanation.
The problem only appears if you add like 2 or more separate weapons and then try to re-add a weapon with the same name, it allows you to do so. If you add just one one weapon and then try to re-add it it says nope and the code works as intended.
So yeah, when I call the method printHeroInfo I still see that I can end up with several weapons with the same name. There is also another class called superWeapon, and if you think the code in there is relevant to this issue then let me know and I'll post that in a commment or something.
Thanks in advance for helping me with the head scratching.
import java.util.ArrayList;
public class superHero{
private ArrayList<superWeapon> superWeaponList;
private String superHeroName;
private String superHeroInfo;
public superHero(String superHeroName, String superHeroInfo){
this.superHeroName=superHeroName;
this.superHeroInfo=superHeroInfo;
superWeaponList=new ArrayList<superWeapon>();
}
public void addSuperWeapon(String superWeaponName, int superWeaponCharges){
superWeapon Obj = new superWeapon(superWeaponName, superWeaponCharges); // Making an object of the superWeapon class.
int size=superWeaponList.size(); // Gets the size of the array superWeaponList.
if(size==0){ /* If the size of the arary is zero, that means there are no weapons in it currently.
For that reason we don't need the for-loop we otherwise would need to compare the name of the weapon
we are trying to add against the pre-existing names of weapons in the array. */
superWeaponList.add(Obj);
System.out.println("The Superweapon"+superWeaponName+" has been added for the superhero "+superHeroName+".");
System.out.println(superWeaponName+" has "+superWeaponCharges+" charges.");
}
else{ /* If the size of the array is NOT zero, we need to compare the name of the weapon we are trying to add
against the weapons already existing in the array. This we do with the following for loop. */
for(int i=0;i<size;i++){
superWeapon temp_obj=superWeaponList.get(i);
String temp_name = temp_obj.getName();
System.out.println(temp_name); /* Why does the name lag behind one entry?
On the second entry it also shows the first entry. On the third entry it shows the second
entry and so on... The first place in an arraylist should be index=0,
so the for-loop starting at 0 should also be correct, right?
I just added this print to see what the current value for getName()
would end up returning. This is how I found the bug/error. */
if(temp_name!=superWeaponName){ // If the name doens't match then we add a new superweapon.
superWeaponList.add(Obj);
System.out.println("The superweapon "+superWeaponName+" has been added for the superhero "+superHeroName+".");
System.out.println(superWeaponName+" has "+superWeaponCharges+" charges.");
}else{ // If the names match however, we don't add the new weapon we were trying to add.
System.out.println("There already is a superweapon with the name "+superWeaponName+
" registered for the superhero "+superHeroName);
}
}
}
}
public void printHeroInfo(){
System.out.println(superHeroName);
System.out.println(superHeroInfo);
int size=superWeaponList.size();
for(int i=0;i<size;i++){
superWeapon temp_obj=superWeaponList.get(i);
System.out.println(superHeroName+" has the superweapon "+temp_obj.getName()+" with "+temp_obj.getCharges()+" charges.");
}
}
}
Although it can be improved a lot with using Set instead of list, but I will just point out the error in assumption you are making in comparing Strings...
if(temp_name!=superWeaponName) //incorret
if(!temp_name.equals(superWeaponName)) //correct
I'm relevantly new to Java and just started my first semi serious assignment. I'm confident most of my code is working, the only problem is because I've been using classes I can't seem to call a method which uses an array into my main class. Every other method I want to call seems to work. I wonder if anyone has any explanation or easy solution to this?
Thanks in advance for taking time looking into, really appreciate it!
import java.util.Scanner;
public class GeographyQuizMain
{
public static void main(String[] args)
{
takeQuiz();
}
public static void takeQuiz(Question[][] questions)
{
int score = 0;
RandomNumber randomQuestion = new RandomNumber();
//user chooses catergory
int cat = pickCatergory();
//ask 10 questions
for(int i = 0; i < 10;)
{
Scanner answerChoice = new Scanner(System.in);
randomQuestion.dice();
int q = (randomQuestion.dice() - 1);
//checks to see if question as been asked before
if (!questions[cat][q].beenAsked)
{
questions[cat][q].beenAsked = true; //changes question status to beenAsked
System.out.println(questions[cat][q].promt);
String answer = answerChoice.nextLine();
System.out.println("\nYou picked: " + answer + "\nThe correct answer was: " + questions[cat][q].answer + "\n");
if(answer.equals(questions[cat][q].answer))
{
score++;
}
i++;
}
}
System.out.println("That is the end of the quiz!\n"
+ "You got " + score + "/10");
}
Your problem is with the call itself,
This line public static void takeQuiz(Question[][] questions) states that the method will accept a two dimensional array ([][]) of an object named Question.
On the other hand, your call - takeQuiz(); passes no array of such.
You should initialise an array of such to make this compile and pass it to the function. i.e.
Question[][] questionArray = GenerateQuestionArray(); //you should write this method
takeQuiz(questionArray);
Like you stated, it's clearly you're new to Java and I strongly suggest you to read the instructions and the information provided to you in class about that. I bet the details of Object initialisation, methods and arrays are covered there.
It seems that problem with your method call, in your method takeQuiz(); is taking 2 dimensional array for questions but at the calling time you are not providing that parameter so, compiler not able to found the method.
That's the problem.
try to use like this, this is simple an example for you. replace this with your actual values.
String[][] questions= new String[3][3];
takeQuiz(questions);
this will work.
You have called your method takeQuiz() without actually supplying its arguments Question[][] questions
The following requisites are those for the program I'm currently having an issue with:
The program must be able to open any text file specified by the user, and analyze the frequency of verbal ticks in the text. Since there are many different kinds of verbal ticks (such as "like", "uh", "um", "you know", etc) the program must ask the user what ticks to look for. A user can enter multiple ticks, separated by commas.
The program should output:
the total number of tics found in the text
the density of tics (proportion of all words in the text that are tics)
the frequency of each of the verbal tics
the percentage that each tic represents out of all the total number of tics
Here is my program:
public class TextfileHW2 {
// initiate(
public static int[] initiate(int[] values){
for (int z=0; z<keys.length; z++){
values[z] = 0;
}
return values;
processing(values);
}
// processing(values)
public static int[] processing(int[] valuez){
while (input.hasNext()){
String next = input.next();
totalwords++;
for (int x = 0; x<keys.length; x++){
if (next.toLowerCase().equals(keys[x])){
valuez[x]+=1;
}
}
return valuez;
output();
}
for (Integer u : valuez){
totalticks += u;
}
}
public static void output(){
System.out.println("Total number of tics :"+totalticks);
System.out.printf("Density of tics (in percent): %.2f \n", ((totalticks/totalwords)*100));
System.out.println(".........Tick Breakdown.......");
for (int z = 0; z<keys.length; z++){
System.out.println(keys[z] + " / "+ values[z]+" occurences /" + (values[z]*100/totalticks) + "% of all tics");
}
sc.close();
input.close();
}
public static void main(String[] args) throws FileNotFoundException {
static double totalwords = 0; // double so density (totalwords/totalticks) returned can be double
static int totalticks = 0;
System.out.println("What file would you like to open?");
static Scanner sc = new Scanner(System.in);
static String files = sc.nextLine();
static Scanner input = new Scanner(new File(files));
System.out.println("What words would you like to search for? (please separate with a comma)");
static String ticks = sc.nextLine(), tics = ticks.toLowerCase();
static String[] keys = tics.split(",");
static int[] values = new int[keys.length];
initiate(values);
}
My program should be logically right as I wrote it and successfully ran it for a while last week, but the difference with this one (which doesn't work) is that I must use separate methods for each component of the analysis, which shouldn't be too difficult a task considering the program was working before So I naturally tried to split up my program such that I can call my first method (which I called initiate) then my 2nd and 3rd methods called processing and output.
First of all, what does static really mean? I remember my teacher saying that it represents a global variable which I can use anywhere in the program. As you can see I changed every variable to static to perhaps make my task easier.
Also, do I strictly need to use public static + type returned if I'm going to change something?
Let's say I want to change the values of an array (like I do in my program and use public static void) do I need to return something to actually change the values of the array or is it ok to use public static void?
If anyone also has any general pointers for what concerns my methods I would really appreciate it.
Your problem is in your initiate method:
return values;
processing(values);
Once you call return, your method stops. If you are using Eclipse (which I highly recommend), you should have gotten an error saying "Unreachable code," because there is simply no way for the program to execute your processing method.
I also saw this flaw in your output method.
First of all, what does static really mean? I remember my teacher
saying that it represents a global variable which I can use anywhere
in the program. As you can see I changed every variable to static to
perhaps make my task easier.
It depends on the context. There is a good overall description here. The meaning is different when applied to methods, fields, and classes. To say it makes variables "global" is a bit simplified.
Also, do I strictly need to use public static + type returned if I'm going to change something?
I'm a little confused about what you mean. A method declared as public static *return_type* has three separate, independent qualities:
public: It is accessible by any other class.
static: It does not require an instance of the class to function (see above link).
*return_type*: This is, of course, the return type.
These properties aren't really related to "changing something". Unless I misunderstood your question, the answer is: No, the method specifiers and return type have no impact on its ability to change something with the exception that static methods cannot modify non-static fields or call non-static methods of this (there is no this in static methods).
Let's say I want to change the values of an array (like I do in my program and use public static void) do I need to return something to actually change the values of the array or is it ok to use public static void?
What you do in the function is entirely independent of the access specifier and static-ness of it (with the above-mentioned exception that this does not exist in static methods). If your function has any side-effects like changing the values in an array (or any values for that matter), then it does it regardless of public, or static, or its return type.
Check out the More on Classes section of the official language tutorial. It is concise and well-written and should help complete your understanding of the general concepts you're asking about. Check out some of the other tutorials there as well if you'd like.
I understand how to pass a variable to another method and I even learned how to do multiple variables to a single method. My problem is I am trying to make a switch statement, when the user inputs a symptom for digoxin(medication for heart) in the statement I want to award him 10 points store it in a variable, and when the user enters another symptom I want to store that in variable as well in a new method. My problem is that after I send the variable to my method and continue with the program it inevitably resets it to zero, and thus dooming my efforts.
Code:
switch(input5) {
case "Vomiting":
score = 0;
num = 0;
score = num + 10;
getMethod(score,0);
System.out.println(getMethod(num));
JOptionPane.showMessageDialog (null,"you're correct") ;
break;
case "Dizziness":
JOptionPane.showMessageDialog (null,"you're correct") ;
score = num + 10;
getMethod(0,score);
break;
case "Confusion":
JOptionPane.showMessageDialog (null,"you're correct");
break;
case "Vision":
JOptionPane.showMessageDialog (null,"you're correct");
break;
default :
JOptionPane.showMessageDialog (null,"you're Wrong");
break;
}
...
static int getMethod(int total) {
int amount = total;
int amount2 = total2;
int result = amount + amount2;
return result;
}
The problem with this question is that it is so poorly phrased that it is difficult to understand what you actually think is happening. Unless we understand that, it is hard to answer it properly. So I'm just going to point out some things that appear to be errors in your thinking.
Variables don't "reset" in Java. In this case that the problem is that your getMethod method doesn't update score.
If a method returns a value, and that value isn't assigned to something then it is thrown away. In your case you are not assigning the value returned by getMethod in the places that you are calling it.
In Java, arguments are passed to methods "by value". The upshot is that something like this won't work:
int test = 1;
increment(test, 2);
public void increment(int value, int by) {
// FAIL - the local copy of "value" is incremented, but the
// the original "test" variable is not touched.
value = value + by;
}
Note that this has nothing to do with the names of the variable. The issue is that the variable inside the method is not "connected" in any way to the variable used at the call site. The method updates the former ... and not the latter.
A couple things that need to be said about your code:
It is important to indent your code consistently. There are style guides that tell you what to do. (We've reindented your code in a way that would be acceptable under most style guidelines.)
It is important to use sensible and informative names for things like methods, variables and classes. This helps readers understand what the code author intended the code to do / mean. In your case "getMethod" tells the reader nothing about what the method is supposed to do.
Methods should also have javadoc comments that state what they are supposed to do, what the arguments and results mean, and so on.
i think the issue here is that every time you enter something and enter your switch statement, it resets the score to 0.
switch(input5){
case "Vomiting":
score = 0;
I think you need to set score to 0 before the first input, and not reset it every time you put in vomiting. I can't exactly follow your code, please link the full class.
Try this:
score = getMethod(score, 0);
In java, primitives are "passed by value". The value, not the variable, is passed to the method. Changing the value within the method does nothing to the variable that was used to call the method.
Create a static global variable to maintain or persist the score. This will allow you to make subsequent calls to your method and still keep track of an accurate score.
So, create a global variable public static int score = 0;. Inside of your method you can get rid of the score variable initialization to zero score = 0; since you will use the global score variable.
Ok so i am just learning recursion and i am confused on one point.
This is the code
public class RecursiveDemo {
public static void showRecursion (int num) {
System.out.println("Entering method. num = " + num);
if (num > 1) {
showRecursion(num - 1);
}
System.out.println("Leaving method. num = " + num);
}
public static void main(String[] args){
showRecursion(2);
}
}
The output i am getting is :
Entering method. num = 2
Entering method. num = 1
Leaving method. num = 1
Leaving method. num = 2
My question is why am i getting the output "Leaving method. num = 2". Shouldn't it stop at "Leaving method. num = 1" since num has already reached 1?
Once the original invocation of this method leaves the if statement, it passes to System.out.println("Leaving method. num = " + num);. Since you invoked the message originally with value 2, 2 is the value of num for this part of the code.
Your code runs like this (pseudocode):
Start First Call
if statement
Start Second call
Skips if statement
Print from Second Call
End of Second Call
End of if Statement
Print From First Call
End of First Call
It looks like you have a fundamental misunderstanding of recursion.
When you call your method with (num-1) as arguments, the parent call (the first call, in this case), retains the value num as its argument, which is 2, in this case.
So let's comment out the line below
//showRecursion(num - 1);
What would you get? It must be
Entering method. num = 2
Leaving method. num = 2
And if you uncomment the line above. You should get the one you had.
No.
main will call showRecursion(2), which in turn will call showRecursion(1) (so you get two "Entering" messages). At which point, the condition will fail, so no more recursion occurs. So now the program simply begins returning from each function call in turn, printing both of the "Leaving" messages.
It's because the initial call to showRecursion(2) hasn't finished yet.
Consider the following:
public static void showFirstRecursion (int num) {
System.out.println("Entering method. num = " + num);
if (num > 1) {
showSecondRecursion(num - 1);
}
System.out.println("Leaving method. num = " + num);
}
public static void showSecondRecursion (int num) {
System.out.println("Entering method. num = " + num);
if (num > 1) {
showThirdRecursion(num - 1);
}
System.out.println("Leaving method. num = " + num);
}
// I won't bother showing an implementation for showThirdRecursion, because it won't be called.
public static void main(String[] args){
showFirstRecursion(2);
}
No problem here, right? You'd expect to see the first method entered, second entered, (third not entered because num == 0), second left, first left.
There is really nothing special about recursion. It's just making a function call that happens to be calling the function that the call is a part of. A recursive call behaves, conceptually, in all respects like any other function call. The trick is the design of a recursive algorithm, i.e., coming up with a reason why you'd want to call the same function you're already in.
The other answers already cover the specific question, but here is some information on using a debugger. This tutorial is for Eclipse, but pretty much tells you what you need to know for any visual debugger.
The basics are pretty straightforward, and it would be well worth your time to at least learn how to step through the code. A debugger is an invaluable tool for quickly verifying the logic of your program, and is far easier than scattering print statements everywhere.
Try "showRecursion(5);".
[Answer: This is recursion. There's more than one copy of the variable "num" in memory. "num" is a parameter; it's not a field, and it's not static.]
So what I understood was
with every method call, Stack is getting populated ie. 2,1
but when i>1 doesn't matches it returns/breaks the call and control is given to the system.out.println line, that prints the value starting from the top of stack ie 1,2