In the if-else branches I declared two different PrintStream objects with the same name. However, when I use the PrintStream object later the compiler says that it "cannot find symbol". Why doesn't it see the object I created? The object works withing the if-else branch it was declared in. Here's the code:
System.out.println("Welcome. Would you like to continue a previous adventure, or begin anew?\n(type: new or old)");
status = scan.nextLine();
if(status.equals("new")) {
System.out.println("What do you call yourself?");
name = scan.nextLine();
System.out.println("And what shall be the title of your saga, after you are gone?");
game = scan.nextLine();
System.out.println("Very well. Prepare yourself, for this is the beginning of your end...\n...\n...\nAre you ready?");
status = scan.nextLine();
System.out.println("Not that it matters. Let us begin.");
status = scan.nextLine();
File file = new File(game + ".txt");
PrintStream print = new PrintStream(file);
print.println(name);
old = false;
} else {
System.out.println("So you're still alive? What was the title of your tale?");
game = scan.nextLine();
File file = new File(game + ".txt");
Scanner gscan = new Scanner(file);
String save = "";
while (gscan.hasNextLine()) {
save += gscan.nextLine();
save += "\n";
}
System.out.println(save);
PrintStream print = new PrintStream(file);
print.println(save);
old = true;
name = scan.nextLine();
}
if(old) {
}
print.println("beans");
You need to declare the variable outside the if statement, and then assign it in the two branches, like this:
PrintStream print;
if (status.equals("new")) {
...
print = new PrintStream(file);
} else {
...
print = new PrintStream(file);
}
Better yet, you can set the file inside the if, and then create PrintStream after the conditional:
if (status.equals("new")) {
...
} else {
...
}
File file = new File(game + ".txt");
PrintStream print = new PrintStream(file);
You are experiencing a scoping problem. You need to declare it outside the if-else statement if you want to use it outside the if-else statement.
There are different levels of scoping in Java programs. A scope is generally defined by a set of curly braces. However, there is also public, private, and protected types that allow for use of more global variables than just inside their braces.
Each of these scopes can have their own variables that are not available elsewhere.
Take a look at these two pieces of code:
String s;
if ( foo ) {
s = "one";
} else {
s = "two";
}
if ( foo ) {
String s = "one";
} else {
String s = "two";
}
In the first one, s is available after the if/else. In the second, s is only available within the {} (if/else blocks). Each block happens to have a variable with the same name, but it isn't the same variable. And it isn't available later.
What happens in a scope stays in the scope.
if(some condition)
{
int x = 10;
}
System.out.println(x);
This will not work because the scope of x is limited only till the if block. If you want it to live outside the if block, then declare it outside the if block.
Why define PrintStream print twice? You need to define it only once in this case outside the if.
Related
Basically, my goal is to be as efficient as possible by "deleting" variables when I'm done with them, even if still in scope. So far, I've been using if(true) to manually create a scope that defines the lifetime of variables, but I'm looking for something like, var.close(), a function that's only purpose is to cause a variable to essentially go out of scope and no longer have a memory location reserved for it.
The example I use below could obviously use for() to sidestep this particular instance(the assignment wants me not to use for()), but my concern is wider than variables used as indexes.
(ignore any other logic/syntax errors present, as I haven't proofread this yet)
package root;
import javax.swing.JOptionPane;
public class DebugEight4
{
public static void main(String[] args)
{
String array[] = new String[100];
String entry = " ";
final String STOP = "/']";
StringBuffer message = new StringBuffer(
"The words in reverse order are:\n"
);
if(true)
/*
*forces x out of scope
* after while statement ends
*/
{
int x = 0;
while(!entry.equals(STOP))
{
entry = JOptionPane.showInputDialog(null,
"Enter another word\n" +
"Enter " + STOP + " when you want to stop");
if(!entry.equals(STOP) && x != 100)//prevents fragmentation error
{
array[x] = entry;
}
else
{
JOptionPane.showMessageDialog(null, "That\'s all! Let's see the results.");
}
++x;
}
}/* end x scoping if
* If the if(true) wasn't here, x would still exist!
*/
for(int y = array.length-1; y > 0; --y)
{
message.append(array[y]);
message.append("\n");
}
JOptionPane.showMessageDialog(null, message);
}
}
Any thoughts?
This is exactly what scopes are for. You don't need to invent your own scoping system. Any variable should be declared in the smallest possible enclosing scope. But that's as far as you need to go with this. It is a visibility principle, not an efficiency principle, as all the stack needed for a method is allocated on entry to the method, and inner scopes don't correspond to bytecode instructions in any way.
To create a more-limited scope is easy enough. Just create a new block:
public static void whatever() {
int a = 5; // Exists until end of method
{
int b = 5; // Exists until end of outer block
{
int c = 5; // Exists until end of inner block
}
// c is no longer accessible
}
// b is no longer accessible
}
I'd recommend against this for a few reasons:
It's harder to read for little gain
The compiler or JIT can automatically figure out the lifetime of variables and automatically handle what you're attempting to do
You can't overlap variable lifetimes this way (nesting means that the most-nested variable must expire off the stack before less-nested ones)
public void actionPerformed(ActionEvent arg0) {
String employeeInput;
String assetInput;
String userInput = txtUserInput.getText();
userInput = userInput.toLowerCase();
if (userInput.startsWith("emp")){
//String employeeInput = null;
employeeInput = userInput.replaceAll("\\s","");
txtUserInput.setText("");
JOptionPane.showMessageDialog(frame, "The Scan was " );
}else if (userInput.startsWith("u")){
assetInput = userInput;
assetInput.replaceAll("\\s","");
txtUserInput.setText("");
System.out.println("Employee ID is " + **employeeInput**); //asks for employeeInput to be declared.
JOptionPane.showMessageDialog(frame, "The Scan was " + assetInput);
I want the employeeInput to be filled and saved, untill it is replaced by another employeeInput. The problem I'm having is when getting the item input, the employeeInput is now missing. What is the way to do this?
Thank you, for your help
employeeInput is a method variable, so everytime you exit the method you will lose the reference to it.
The obvious thing to try is turn employeeInput into a member variable. Just declare it at the top of your class.
Better yet may be to persist that value to a database.
The compiler doesn't know that the first condition has already been met. Nor, do I. But, you could change
String employeeInput; // <-- may not have been initialized
to a default value (possibly even explicitly null), here the empty String "".
String employeeInput = "";
It doesn't look like your employeeInput variable is 'missing' or could be removed after any other variable is set. So its most likely you aren't initializing your variables when they're defined.
Try initializing them like
String employeeInput = ""; // or = null
String assetInput = ""; // or = null
String userInput = txtUserInput.getText().toLowerCase();
And your problem should be solved. The compiler might also be giving you a warning about this.
You might also want to try removing this txtUserInput.setText(""); line to test for problems.
Edit:
If you are trying to access this variable after your method has finished executing then it will be wiped so instead of putting it in your method declare it in your class like public class Name{
public /*static*/ String employeeInput = ""; //or null
}
I am studying Java and using BlueJ so my question relates to part of an assignment I have been asked to do. Some of it works but I am having problems with other parts. I will include everything that I have done in the class so far but first here are the requirements:
Prompt user to select an appropriate file // done and working
Use BufferedReader and Scanner objects to read a file line by line // done and assume working!
As each line containing the name and age of a runner is read, a new Runner object should be created and its instance variable set as follows: // Class Runner already created
// Class MathatonAdmin - current class.
3a) name - can be set directly using the value from the file.
// tested with System.out.println and all values (in display panel) are shown (*).
3b) ageGroup - can be worked out from the given age: runners under 18 should be categorised as junior, 55 and older as senior, all else as standard.
// tested with System.out.println and all values (in display panel) are shown (*).
3c) The instance of Runner should be added to the list referenced by the instance variable runners.
Essentially when I run the test code provided:
MarathonAdmin ma = new MarathonAdmin();
ma.readInRunners();
I am supposed t o see a list of runners when I inspect ma; currently one the name and age of a single person is listed.
So I need help with 3a - 3c. How do I create a new instance of Runner with said variables, then add the instance Runner to the list in runners?
I have tried a for loop in while loop but since I am guessing the for loop I do not get the required list in the variable ma.
I am using System.out.println for testing that I at lest have the correct file.
Any help or advice will be appreciated.
The class MarathonAdmin:
import java.util.*;
import java.io.*;
import ou.*;
/**
* MatharthonAdmin Class
*
* #author Stephen Berry
* #version 28/03/14
*/
public class MarathonAdmin
{
// instance variables
private String runners;
private String age;
/**
* Constructor for objects of class MarathonAdmin
*/
public void MarathonAdmin()
{
List<String> runners = new ArrayList<>();
}
public void readInRunners()
{
String pathName = OUFileChooser.getFilename();
File aFile = new File(pathName);
BufferedReader bufferedFileReader = null;
try
{
String currentLine;
Scanner lineScanner;
bufferedFileReader = new BufferedReader(new FileReader(aFile));
currentLine = bufferedFileReader.readLine();
while (currentLine != null)
{
lineScanner = new Scanner(currentLine);
lineScanner.useDelimiter(",");
runners = lineScanner.next();
age = lineScanner.next();
for (String aList: runners)
{
Runner runners = new Runner();
if (Integer.parseInt(age) < 18)
{
System.out.println(currentLine + " : Junior");
}
if (Integer.parseInt(age) > 55)
{
System.out.println(currentLine + " : Senior");
}
if (Integer.parseInt(age) > 18 && Integer.parseInt(age) < 55)
{
System.out.println(currentLine + " : Standard");
}
currentLine = bufferedFileReader.readLine();
}
}
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
finally
{
try
{
bufferedFileReader.close();
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
}
}
}
There are some points in your class that lead to this missbehaviour of your program.
The Exercise says that you shall create a list of runner objects as instance variable right? Look at your instance variable runners of your marathon class and look at the type of it. ;)
Your while loop is a good approach. Now inside the while loop you interate for each line of the textfile which is equivalent to one runner right? So why you need the for loop? You can use the lineScanner to get each part of the line there is no need for a second loop i try to give you a structure with pseudocode
String runnerName;
Int runnerAge;
while (currentLine != null)
{
lineScanner = new Scanner(currentLine);
lineScanner.useDelimiter(",");
runnerName = lineScanner.next();
runnerAge = lineScanner.next();
runners = lineScanner.next();
age = lineScanner.next();
create new Runner Object
set age and name of object according to the data you ve just read
runners.add(Runnerobject) // <-- this line adds the object you ve just created to the list which is your instancevariable. Make sure that this variable really is a list :)
currentLine = bufferedFileReader.readLine();
}
}
Hope this helps you a little bit.
You create a Runner instance, but you don't set the instance variables name and age/ageGroup for class Runner. You could create a constructor in the Runner class to do that. Also you should rename your variable, since runners is already used.
Further you declared runners as an instance variable of type String. But you would need to have a List. After you created the Runner instance you can add that instance to the list.
Your instance variables are incorrect. You need a list of objects not a String runners.
Also you need a method instance for age not a class instance.
private List<Runner> runners; // instance variables for a list of runner objects
runners = new ArrayList<Runner>(); // in the constructor
I would also agree with MeiSign, you do not need a for loop within the while loop
The user enters an expression. Suppose user entered the following as input:
new y java.util.ArrayList int:5
i have successfully tokenized the string and stored it into different locations of my String array. next thing i want to do is that i should check whats on the index and do things according as mentioned in the above input for reflection. Am stuck how to do it. here is my code so far
public static void handling_input()
{
System.out.println("Welcome To Java Command Prompt: ");
aLine = null;
try
{
System.out.println("Enter The Command Line Expression: ") ;
keyboard = new BufferedReader(new InputStreamReader(System.in));
aLine = keyboard.readLine();
st = new StringTokenizer(aLine);
dt = new StringTokenizer(aLine);
}
catch (IOException ex)
{
System.out.println("Error reading input!");
}
}
public static void storing_tokens()
{
int counter =0;
while(st.hasMoreTokens())
{
counter++;
st.nextToken();
}
int i=0;
expression_keeper= new String[counter];
do
{
expression_keeper[i] = dt.nextToken().toString();
i++;
}while(dt.hasMoreTokens());
}
public static void token_classification()
{
for(int i=0; i<expression_keeper.length; i++)
{
if(expression_keeper[0].equalsIgnoreCase("new"))
{
}
else
if(expression_keeper[0].equalsIgnoreCase("call"))
{
}
else
if(expression_keeper[0].equalsIgnoreCase("print"))
{
}
else
{
System.out.println("Invalid Script!");
}
}
}
}
Inside this if condition:
if(expression_keeper[0].equalsIgnoreCase("new"))
{
}
i want to create the specified class,its object and assign values to the modifiers mentioned!
It is unclear to me what your input string tokens really mean. Is "java.util.ArrayList" the type for "y" and should it have an initial size of 5 units? Or should the first element be an integer of 5?
In the past I have found writing my own syntax tokenizer and parser a complicated thing to do. Even in simple cases I have often found that using something like JavaCC was easier in the long run.
By specifying your syntax formally you give much but structure to your code and it's debuggability. And then as said elsewhere use introspection to do the creation. The packages to do this are in java.lang.reflect.
I have this if statement and what to access axeMinDmg. How do i set it as a global variable to so that i can access it within the if statement. Also, how to i set minDmg as a global variable so that i can access outside of the if statement. thanks
// if yes ask what weapon to purchase
if (name.equals("yes")){
System.out.println("Select Your Weapon \n axe \n bat \n sword : \n ");
Scanner wc = new Scanner(System.in);
String weapon = wc.next();
if(weapon.equals("axe")){
minDmg = axeMinDmg;
} else {
System.out.println();
} // close if statement
Global variables really does not exists in Java. You can create a public static final member of a class and the member will accesible in the same scope as the class (if public everywhere)
public class MyClass {
public static final int axeMinDmg = 20;
can be used as MyClass.axeMinDmg from everywhere.
Another way could be to go with an Enum.
You can declare and initialize it outside the
if (condition) {
}
block. This will allow you to use it within if.
e.g.
String minDmg = null;
String axeMinDmg = null;
if (name.equals("yes")) {
...
}
Hope I am answering your question as intended.
You can initialize it in the beginning of your class, so the if statement would be included in its scope.