I've done some looking around on here for a solution, but I can't find one. I tried these ones and many others, and I run into the same issue.
I am trying to make a simple text game, and I run into the issue where I have a main class, and a class called "gameboard" that I have as an array defined like this:
static GameBoard[] gameboard = new GameBoard[9];
Now, this works fine until I try to change the characteristics of a single one of these array objects. I will do:
gameboard[input].setState(2);
and the specific instance of gameboard that should change will not be the only one: all of them change when I do this. It's weird. Only gameboard[**input**] should change, not all 9 of the gameboard instances. EVERY variable and method I have is "static", but because of the main method (public static void main...), everything seems to have to be static. How do I get rid of all this static?
GameBoard Class
package com.name.tictactoe;
public class GameBoard {
char[] States = {'N','X','O'};
char state;
public void setState(int s){
state = States[s];
}
public char getState(){
return state;
}
}
Main class (called Game)
package com.name.tictactoe;
import java.util.Scanner;
public class Game {
static boolean turn, win;
static GameBoard[] gameboard;
static Scanner kb = new Scanner(System.in);
static int input;
public static void main(String[] args){
gameboard = new GameBoard[9];
reset();
displayStates();
askTurn();
displayStates();
askTurn();
}
public static void askTurn() {
System.out.println();
System.out.println();
System.out.println("Where do you want to go? Use the numbers shown, where the first segment is the top and the last is the bottom - left to right.");
input = kb.nextInt();
if(input > 8){
System.out.println("Input out of bounds. Game over by default.");
try {
Thread.sleep(1000000000);} catch (InterruptedException e) {e.printStackTrace();}
}
gameboard[input].setState(2);
}
public static void reset(){
for(int i = 0; i < 9; i++){
gameboard[i].setState(0);
}
}
public static void displayStates(){
for(int i = 0; i < 9; i++){
System.out.print(gameboard[i].getState() + " ");
if(i ==2 || i ==5){
System.out.print(" II ");
}
}
System.out.println();
for(int i = 0; i < 9; i++){
System.out.print(i + " ");
if(i ==2 || i ==5){
System.out.print(" II ");
}
}
System.out.println();
}
}
UPDATE: The current answers don't work. Although Eclipse doesn't realize this, making GameBoard non-static causes null pointer exceptions when any method in it is referenced.
A static variable belongs to the class, not the object, so of course all of your GameBoards are being affected!
Just because you're in a static method doesn't mean you can't manipulate instance variables. First, make everything in your GameBoard class non-static (unless you really do need some of the values shared across all instances). This includes your instance variables and your getter/setter methods.
If your program works exclusively from the main method, then keep your GameBoard[] object static. Then, when you make that method call:
gameboard[input].setState(2);
This will change only the state of the GameBoard at index input.
Edit:
To instantiate your GameBoard[] with basic GameBoard objects inside of it, you can do this at the beginning of your main method:
for(int x=0; x<gameboard.length; x++) {
gameboard[x] = new GameBoard(); //Assuming you want to use the default constructor
}
The other objects in your array should not change. Can you add some more code for more context?
As far as I can understand you, you are doing something like:
public class Main {
public static String[] strings = new String[2];
public static void main(String[] args) {
strings[0] = "test";
System.out.println(strings[1]);
}
}
In my example output is "null" as expected.
How do I get rid of all this static?
Just create instances of your objects in the main function.
GameBoard[] gameboard = new GameBoard[9];
For what you describe to happen all the elements of the gameboard array must be set to the same object (nothing to do with the array being static), check your code where you populate the gameBoard array with new instances of the GameBoard class for a bug that could cause the same instance to be written to all elements (or post that code here so people can see the problem).
Related
I get a NPE in the 2 lines I commented "NPE HERE"
import javax.swing.*;
import java.awt.*;
public class Project1{
static TextArea preSort, postSort;
static String[] Array = new String[20];
public static void main(String[] args) {
Project1GUI myFrame = new Project1GUI("Project1GUI");
readStringFromFile("filename.txt");
enterFirst(Array); // NPE HERE
selectionSort(Array);
enterSecond(Array);
}
public static void enterFirst (String[] name){ // NPE HERE
for(int i=0;i<name.length&&name[i]!=null;i++)
preSort.append(name[i]+" ");
}
public static void enterSecond (String[] name){
for(int i=0;i<name.length&&name[i]!=null;i++)
postSort.append(name[i]+" ");
}
public static void selectionSort (String[] name){
for(int i=0; i<name.length-1&&name[i]!=null;i++){
int indexLowest=i;
for (int j=i+1; j<name.length&&name[j]!=null;j++)
if(name[j]<name[indexLowest])
indexLowest=j;
if(name[indexLowest]!=name[i]){
String temp = name[indexLowest];
name[indexLowest]=name[i];
name[i]=temp;
}//if
}//for
}//method selectionSort
public static boolean isOkay (String name){
char[] chars = name.toCharArray();
for(int i=0; i<chars.length; i++){
if(!Character.isLetter(chars[i])){
return false;
}
}
return true;
} //isOkay
public static void readStringFromFile(String fileName){
TextFileInput inFile = new TextFileInput(fileName);
String line;
line = inFile.readLine();
int index = 0;
while (line!=null) {
if(isOkay(line))Array[index++]=line;
else System.out.println(line);
line = inFile.readLine();
}//while
inFile.close();
}
} //Project1
I have 2 other classes in my directory, TextFileInput and my GUI class (do you guys need to see the code there too?).
I probably have more mistakes in my code, not sure as I'm still not very familiar with Java and am trying my best to learn. Any other advice will be appreciated.
Anyways, what is causing the NPE? From my understanding, my string array has null values that cause a NPE when I try to access the array with name[i].
I've tried filling up the rest of my array with dummies (strings with value of "antinull") but that didn't solve anything and would clearly not be an elegant solution even if it was one.
I just need to have a project1 class and a GUI class. The objective is to take in a file with strings, check if a string is all letters, and send the actual words to a text area in the GUI. Then sort by size and send the ordered version to the other text area. The strings that aren't words are sent to be output to the console. Project1 should have a constructor which takes one string parameter.
When you call preSort.append(...), you're calling a method from a variable (preSort), which is not initialized and thus null, this causes a NullPointerException. If you initialize preSort in your main method for instance, things will work better.
You should also look into indenting your code properly and use proper Java naming standards. Variables should be camelCased, not starting with a capital letter.
I don't think you are getting a Null Pointer Error on calling enterFirst(Array). The loop shouldn't even execute since the first value of Array is a null. But you might get a Null Pointer Error because preSort variable doesn't refer to any object.
Try:
static TextArea preSort = new TextArea(5, 20); and
static TextArea postSort = new TextArea(5, 20);
So I'm new to coding/Java and I'm working on this project. My assignment is to create 3 different classes (which I have here) and make a them cooperate. I've successfully made my FishTankManagerApp class retrieve a new Fish object and I'm trying to figure out how to put it in a FishTank object.
My FishTank class only is only there to create an array object which can hold 5 fish (I think I've done this correctly). In my FishTankManagerApp class, I've created an array of 10 of these FishTank Objects.
My question which I cant figure out for the life of me is how do I place the Fish objects into a specfic FishTank object after they've been created (I've made a note at the end of the code where I've ran into a problem).
Essentially I know I'm trying to put an object I've created inside of and array which contains another array where fish objects can be stored... I think....
Any help would be much appreciated! Thank you!
import java.util.Scanner;
public class Fish {
private static Scanner stdin = new Scanner(System.in);
private String userInput;
private int userInput2;
public boolean mean;
public String name;
public Fish(){
System.out.println("What is your fishes name?");
userInput = stdin.next();
this.name = userInput;
System.out.println("Is this fish aggressive?\n"+
"(1)Yes\n(2)No");
userInput2 = stdin.nextInt();
if (userInput2 == 1)
this.mean = true;
else
this.mean = false;
}
}
public class FishTank {
public FishTank(){
Fish[] tank = new Fish[5];
}
}
import java.util.Scanner;
public class FishTankManager {
private static Scanner stdin = new Scanner(System.in);
private static int userInput;
private static FishTank[] tanks = new FishTank[10];
public static void main (String[] args) {
while (true){
System.out.println("Welcome to your new fish tank manager!\n"+
"What would you like to do?\n"+
"(1)Add a Fish\n(2)Move a Fish\n"+
"(3)Check a tank");
userInput = stdin.nextInt();
if (userInput == 1){
Fish fish = new Fish();
System.out.println(fish.name);
System.out.println(fish.mean);
changeTank(fish);
}
else if(userInput ==2){
}
else{
}
}
}
private static void changeTank(Fish fish){
System.out.println("Which tank would you like to put this fish in? (1-10)");
userInput = stdin.nextInt();
tanks[userInput] = fish;
// This last line is where I'm confused on how to put the fish() object into a tank which I've created.
}
}
I'd recommend adding a method to your FishTank to make adding the fish easy. Maybe something like this:
public FishTank(){
private Fish[] tank = new Fish[5];
public boolean addFish(Fish fish) {
// ... add code here to put the fish to the tank array
// return true if there was room in the tank, false otherwise
}
}
Note that the tank variable is now private. It's generally a good idea to keep member variables private in Java, and use methods to access them.
Then, where you've got the comment you mentioned, you can just call the new method:
boolean addedSuccessfully = tanks[userInput].addFish(fish);
You may not need to return the boolean as I'm showing, but it might be handy if you need to check whether the array (i.e. the tank) had room for the new fish.
Currently, what you're doing is setting the FishTank object equal to a Fish instance - not adding it to the tank variable inside of FishTank.
Right now, you have no way of accessing the tank variable inside of the FishTank class. What you need to do is make it a global variable and provide accessor/modifier methods. For example:
public class FishTank {
private Fish[] tank;
private int numFish;
public FishTank(){
this.tank = new Fish[5];
this.numFish = 0;
}
public void add(Fish f){
if(this.numFish >= 5){
//handle "tank is full" case
}
else{
numFish++;
this.tank[numFish] = f;
}
}
}
Then invoke add on the desired FishTank object:
tanks[userInput].add(fish);
This is a little adventure game I'm working on. I'm just trying to create a 3x3 matrix that the player can move around in. But, in the game loop (which doesn't loop yet, I know,) I can't reference the Player or Room objects I created with the init() method. (I have separate class files for Player and Room objects, they work fine.) When I try to run this code:
import java.util.Scanner;
public class Adventure
{
public final static int maxCol = 2;
public final static int maxRow = 2;
public static void init()
{
Scanner keyboard = new Scanner(System.in);
//instantiate rooms
final Room[][] maze = new Room[maxCol+1][maxRow+1];
final Player player = new Player("",1,1);
for(int i = 0; i <= maxCol; i++)
{
for(int j = 0; j <= maxRow; j++)
{
maze[i][j] = new Room("room");
}
}
//room names
maze[0][0].setDesc("Alleyway - West");
maze[0][1].setDesc("Alleyway - East");
maze[0][2].setDesc("Back Entrance");
maze[1][0].setDesc("Back Room");
maze[1][1].setDesc("Hallway");
maze[1][2].setDesc("Bar - North");
maze[2][0].setDesc("Bathroom");
maze[2][1].setDesc("By An Arcade Machine");
maze[2][2].setDesc("Bar - South");
//get player name
System.out.print("What is your name? ");
String nameInput = keyboard.nextLine();
//create player object
player.setName(nameInput);
player.display();
}
public static void main(String args[])
{
init();
playGame();
}
public static void playGame()
{
System.out.print(maze[player.getXPos()][player.getYPos()].getDesc());
}
}
I get these errors:
Adventure.java:54: error: cannot find symbol
System.out.print(maze[player.getXPos()][player.getYPos()].getDesc());
^ symbol: variable maze location: class Adventure Adventure.java:54: error: cannot find symbol
System.out.print(maze[player.getXPos()][player.getYPos()].getDesc());
^ symbol: variable player location: class Adventure Adventure.java:54: error: cannot find symbol
System.out.print(maze[player.getXPos()][player.getYPos()].getDesc());
^ symbol: variable player location: class Adventure 3 errors
What am I doing wrong? Thank you :)
This is an issue of scope! Java has particular rules for how something can be accessed, depending on where it is declared. If you declare something inside a method, then you can only access it inside that method.
public void doSomething() {
String str = "Hello";
// when doSomething ends, str is lost!
}
To solve this, you can declare your variable outside of the method, in the global level.
String str = "Hello";
public void doSomething() {
str = "Hello";
}
Notice, you've declared it outside of the method, but you've defined it inside the method.
Extra Reading
The big one is Java scope.
Scope of your maze variable is limited to the method init thus it can't be found in your playGame method. Update init to return the maze (Room[][]) or declare it static. In fact you need to do this for your player object too.
Basically I create a custom object in one program and instantiate with values in one program, then I create another program and want to print the instantiated object output.
import java.util.Scanner;
class example {
int value;
String name;
String city;
}
public class Yummy21 {
static example[] obj=new example[3];
static Scanner input=new Scanner(System.in);
public static void main(String args[])
{
init();
}
public static void init()
{
for(int i=0;i<3;i++)
{
obj[i]=new example();
}
for(int i=0;i<3;i++)
{
System.out.println("for the object "+i+" enter the name ");
obj[i].name=input.next();
System.out.println("for the object "+i+" enter the city ");
obj[i].city=input.next();
System.out.println("for the object "+i+" enter the name ");
obj[i].value=input.nextInt();
}
}
}
And the next program:
public class Yummy22 extends Yummy21 {
public static void main(String args[])
{
for(int j=0;j<3;j++)
{
System.out.println("the value of the object["+j+"].name is "+obj[j].name);
}
}
}
The first program works fine, meaning it takes the values and the second program shows NullPointerException.
Yummy22.main does not invoke Yummy21.init. perhaps put a
static {
init();
}
in Yummy21.
This being said, these 3 classes are abominations of Java. Please at least follow naming conventions. Class example should be Example. Also better to code all this with object level fields, constructors and non static members
serialize the data from program 1 and write it to disk and then read it from program 2.
Let me explain further. I have a String function (called stringReversal) that returns a reversed string, it has no errors in the function. But, when I try to print using System.out.println() from the main function, it gives me the error "Can not make a static reference to the non static method stringReversal (string s) from the type StringReverse".
I tried giving my stringReversal a static modifier, but after doing so, it gave me run time errors.
Here's what my code looks like:
public class StringReverse {
public String stringReversal(String s){
if(s == null){
return null;
}
else if(s.length()% 2 == 0){
int size = s.length();
for(int i =0; i<s.length(); i++){
s.replace(s.charAt(i), s.charAt(size));
size--;
if(i == (s.length()/2) || size==0)
break;
}
}
else{
for(int i =0; i<s.length(); i++){
int size = s.length();
s.replace(s.charAt(i), s.charAt(size));
size--;
if(i == ((s.length()/2) +1) || size==0 )
break;
}
}
return s;
}
public static void main(String[] args) {
String str = "Hello";
String rev = stringReversal(str);
System.out.println();
}
}
You have to instantiate your class to call object members, or you need to make your function static, indicating it's not part of object oriented paradigm
In your case you can do
StringReverse sr = new StringReverse();
String rev = sr.stringReversal("hello");
or declare your method differently
public static String stringReversal(String s)
In fact the class name StringReverse itself does not sound like some kind of object, so the second way is preferred impo
The deeper problem you have is the confusion on how Java handle OO and entrance function in general. Java is primarily an OO language so most of the time everything shall be an object or a member of a object. But when you telling the VM to run some java code, there got to be a place to start, which is the main method. There has to be one main method and it must be under some class, but it really has nothing to do with the class that contains it. Within the main method, you either start your OO life by instantiating objects and invoking their members (method 1) or stay in the spaghetti world for a bit longer, by calling other static members as procedures (method 2).
You have two options:
Keep the method non static and then create an instance of your class to call the method:
public static void main(String[] args) {
String str = "Hello";
StringReverse sr = new StringReverse(); // instance of class
String rev = sr.stringReversal(str);
System.out.println(); // just prints a blank line lol...
}
Make the method static (you should do this):
public static String stringReversal(String s) {
// ...
}
public static void main(String[] args) {
String str = "Hello";
String rev = stringReversal(str);
System.out.println(); // just prints a blank line lol...
}
Either way, you have to fix your "run time errors". You can't get around that. If your method doesn't work, keeping it not static won't make it work either.
By the way, I think you meant to do System.out.println(rev); instead of System.out.println();
For the record, here is how to easily reverse a string (both methods work):
public static String stringReversal(String s) {
StringBuffer reverseString = new StringBuffer();
// reverse the string
for (int i = s.length() - 1; i > -1; i--) {
reverseString.append(s.charAt(i));
}
return reverseString.toString();
}
/* using the reverse() method in the StringBuffer class
instead of reversing the string through iterations */
public static String stringReversal2(String s) {
return new StringBuffer(s).reverse().toString();
}
This is happening because your Main method is static, but the class that it's in is not. In order to call a non-static method, you need to create an instance of the class. Alternatively, the method can be made static, but in order to refer to it you need to include the class name in your call (as if to use the class itself like an object containing the method - see below).
There are three solutions to this problem:
Make an instance of the class and call the method from your object (recommended).
make the method static and use StringReverse.stringReversal().
Make the class AND the method static.