Strange behavior of Java code with static attribute - java

I do not have much to ask really. Heck I don't even know what the question should say. Basically, this Java code works fine without any compilation errors.
public class Application {
static String[][] tiles;
public Application() {
tiles = new String[9][9];
}
public static void main(String[] args) {
Application app = new Application();
Grid mines = new Grid();
mines.fillTiles(tiles, 9, 9, 10);
}
}
class Grid {
Random rand;
public void fillTiles(String[][] tiles, int rowSize, int colSize,
int numMines) {
rand = new Random();
int rowIndex;
int columnIndex;
while (numMines > 0) {
rowIndex = rand.nextInt(rowSize);
columnIndex = rand.nextInt(colSize);
tiles[rowIndex][columnIndex] = "M";
numMines--;
}
}
}
But, when I remove the line
Application app = new Application();
from the main method in the first class, it is throwing a NullPointerException at
tiles[rowIndex][columnIndex] = new String("M");
Any reason why?

Application app = new Application();
If you don't instantiate Application, tiles will be pointing to null. Operation on null reference results in NullPointerException.
Your Array initialization logic is in constructor.
public Application() {
tiles = new String[9][9];
}
Constructor will be executed only on Object creation (new Application())
If you don't want to do Application app = new Application();
Just change static String[][] tiles=new String[9][9];
Defining static array variable doesn't mean that instantiation will happen on load. It just means that that variable is class variable.

You notice that you have instantiated your array in your constructor?
static String[][] tiles;
public Application() {
tiles = new String[9][9]; <--- Here
}
So, if you don't instantiate your Application using new Application(), your array would not be initialized, and your reference will be pointing to null.
Also, it is not a good idea to initialize your static variables in constructor. Ideally, you should initialize your static array in a static initializer block or at the place of declaration itself: -
static {
tiles = new String[9][9];
}
or
static String[][] tiles = new String[9][9];
If you initialize your array in your constructor, it will be re-initialized for every instance, every time you create one. As static variables are common to all the instances. So, the change you make to your static variable, will be reflected in all your instances.

I think I might know the reason why:
public class Application {
static String[][] tiles;
public Application() {
tiles = new String[9][9];
}
public static void main(String[] args) {
Application app = new Application();
Grid mines = new Grid();
mines.fillTiles(tiles, 9, 9, 10);
}
}
In this you have a static 2d array that holds strings called tiles. However, you only initialize it in the constructor of Application. Thus when calling "mines.fillTiles(tiles", tiles is still null and
tiles[rowIndex][columnIndex] = new String("M");
will throw a NullPointerException.

Because you are initializing tiles = new String[9][9]; in your constructor. You constructor is only called when you use new to create the object instance as new Application().
If you don't want to use the constructor, declare your static variable with initialization as:
static String[][] tiles = new String[9][9];
That should work fine without constructor call.

You are initializing the array in the constructor of an instance. If you create another instance after the first, it will re-initialize the static member.

Related

Java - Custom type nested in class

I am once again asking for technical support.
I need to define a custom type inside a class, I've done it like this:
public class MainClass {
private class CustomType {
public byte[] varA;
public int varB;
public CustomType() {
varA = new byte[3];
varB = 13;
}
}
private CustomType[] myArray;
public MainClass() {
myArray = new CustomType[1024]
System.out.println(this.CustomType[0].varB);
}
}
When I run it throws a NullPointerException at System.out.println(this.CustomType[0].varB);
I've tested if myArray gets properly initialized with 1024 elements and it does, however I can't seem to access them.
I just moved from C++ to Java so I'm still getting used to it, am I missing something blatant?.
You only create an array without any objects, so this.CustomType[0] is null.
You should add the objects to the array:
public MainClass() {
myArray = new CustomType[1024]
for (int i =0; i<myArray.length;i++ {
myArray[i] = new CustomType();
}
System.out.println(this.myArray[0].varB);
}
Also you should make the member of CustomType private and access it via getter and setter.
Two things,
You must instantiate CustomType.
CustomType does not need access to MainClass.this so you can make it static.
So
public class MainClass {
private static class CustomType {
public byte[] varA;
public int varB;
public CustomType() {
varA = new byte[3];
varB = 13;
}
}
private CustomType[] myArray;
public MainClass() {
myArray = new CustomType[1024];
for (int i = 0; i < myArray.length; ++i) {
this.CustomType[i] = new CustomType();
}
// Or
Arrays.setAll(myArray, CustomType::new);
System.out.println(this.CustomType[0].varB);
}
}
Not making it static stores a MainClass.this in every CustomType instance which is unnecessary overhead.
Arrays in java are objects. The following line of the code you posted creates an array of 1024 elements where each and every element is null.
myArray = new CustomType[1024];
If you want to place actual objects in the array, named myArray, you need to create instances of class CustomType and assign them to elements of the array, for example:
CustomType instance = new CustomType();
myArray[0] = instance;
Then you can execute the following line of code and it will not throw NullPointerException.
System.out.println(myArray[0].varB);
Here is the full code to get the value of varB. In which you can avoid declaring CustomType[] myArray
public class Test
{
private static class CustomType
{
public byte[] varA;
public int varB;
public CustomType() {
varA = new byte[3];
varB = 13;
}
}
public static void main(String... args)
{
System.out.println(new CustomType().varB);
}
}
The solution is to add some elements to that array. See the below steps for more information.
constructor will be invoked, when you create the object of that class
And then you created an empty array of CustomType with size 1024 and trying to access the first element which does not exist(default is null) and trying to perform operations on that null reference. So you are getting the NullPointerException.

How can I assign instance of a class from an array to a class initializer in java?

In a Android application I am making I have an array of instances of a certain class I made, and later in the program I need to use the getter and setter methods from that class on an instance of the class from the array. Do I need to assign the instance of the class from the array to a new class initializer? Here is some code to clear this up:
Class
public class ProfileInformation {
private String console;
private String gamertag;
public String getConsole() {
return console;
}
public void setConsole(String console) {
this.console = console;
}
public String getGamertag() {
return gamertag;
}
public void setGamertag(String gamertag) {
this.gamertag = gamertag;
}
}
Array
ArrayList<ProfileInformation> ProfTags = new ArrayList<>();
Some instances of ProfileInformation are then added to arraylist, and then I get one of the instances from the arraylist and try to use getGamertag() to set it to a string:
ProfileInformation profNew = ProfTags.get(ProfTags.size()-1);
String example = profNew.getGamertag();
The problem is example will equal null. Why is this?
First, an Arraylist is a List, try not to confuse that with actual arrays.
Do I need to assign the instance of the class from the array to a new class initializer?
You don't need to get an element out of the Arraylist, no. You can chain many methods together
String example = ProfTags.get(ProfTags.size()-1).getGamertag();
example will equal null. Why is this?
For the same reason any object is null... You never set it equal to anything else
This code runs on my laptop:
public static void main(String[] args) {
ArrayList<ProfileInformation> ProfTags = new ArrayList<>();
element = new ProfileInformation();
element.setGamertag("Actual Gamer tag value");
ProfTags.add(element);
ProfileInformation profNew = ProfTags.get(ProfTags.size()-1);
String example = profNew.getGamertag();
}
Output is:
Actual Gamer tag value
I guess you didn't call setGamertag(String).

Java NullPointerException in constructor

I defined a class with public attributes.
However, when initializing the values in the constructor, I get a NullPointerException.
Here is my code:
class CacheBlock
{
public byte[] data;
public int frame;
public boolean ref;
}
public class Cache
{
private CacheBlock[] blocks;
public Cache(int blockSize, int cacheBlocks)
{
blocks = new CacheBlock[10];
blocks[0].data = new byte[blockSize]; //line that causes exception
}
}
This is the issue:
blocks = new CacheBlock[10];
Here the block array has been initialized but there is no CacheBlock object at index 0 therefore when it accessed in the next line, there is a NPE.
You would need to create CacheBlock instances and add it to the block array.
For instance:
blocks[0] = new CacheBlock();
and so on.
blocks = new CacheBlock[10];
This line, you only allocate the memory, but not initialize it.
You should add
blocks[0]=new CacheBlock();
above the suspect line.

Accessing an instance of a class in an arraylist loop

So I have a class LayerCopper that holds a few textboxes and a few methods to set values in those textboxes:
public class LayerCopper extends javax.swing.JPanel {
public LayerCopper() {
initComponents();
}
private static javax.swing.JFormattedTextField CuWeightTextField;
private static javax.swing.JFormattedTextField LayerNumJFormattedTextField;
...
...
...
public void setLayerNumberText(int layerNumber) {
LayerNumJFormattedTextField.setText("" + layerNumber);
}
public void setLayerCuThickness(double CuThickness) {
CuWeightTextField.setValue(CuThickness);
}
}
I also have another class StackupCalculator with multiple instances of the LayerCopper panels in it. I have an arraylist that holds each instance of the LayerCopper panel:
static ArrayList<LayerCopper> layerSet_Copper = new ArrayList<>();
...
...
...
public void createLayerSetArray() {
layerSet_Copper.add(layerCopper1);
layerSet_Copper.add(layerCopper2);
layerSet_Copper.add(layerCopper3);
layerSet_Copper.add(layerCopper4);
layerSet_Copper.add(layerCopper5);
initializeLayerArrayValues();
}
When my initializeLayerArrayValues runs, It's supposed to populate a couple textfields with text:
private void initializeLayerArrayValues() {
for (int i = 0; i < layerSet_Copper.size(); i++) {
layerSet_Copper.get(i).setLayerNumberText(i + 1);
layerSet_Copper.get(i).setLayerCuThickness(0.750);
}
}
When I run the program though it doesn't update the fields. I'm guessing I am calling the main class LayerCopper and not the instanced version of it? How would I call the instanced version of the layer?
According to you, you haven't instantiated LayerCopper. You need to make a new instance of it, and make layerCopper1, layerCopper2, etc. Then use createLayerSetArray().
Like so:
LayerCopper lc = new LayerCopper();
// create values different layerCoppers to go in layerSet_Copper
lc.createLayerSetArray();
I don't quite understand the inner workings of your class, so I could be wrong.
Changing the textfields from static to non-static fixed it for me. /cheers

Why 2D array return 'null'?

i make a 2D String array in main activity but i make NEW in another activity :
public class MainActivity extends Activity
{
public String[][] arr;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestpayment requestpayment=new requestpayment(getApplicationContext(), 1, 8, "boy");
TextView textView=(TextView)findViewById(R.id.text);
textView.setText(arr[1][1].toString());
}
}
In second Activity i use 2d array in this form :
int i=1;
MainActivity mainActivity=new MainActivity();
mainActivity.arr= new String[5][5];
mainActivity.arr[i][0] = FLName;
mainActivity.arr[i][1] = Old;
mainActivity.arr[i][2] = Image;
mainActivity.arr[i][3] = Gender;
mainActivity.arr[i][4] = Description
to here و Everything work good and i can use array amount in second activity.
but when use 2d-array in mainactivity in this form :
textView.setText(arr[1][1].toString());
return null :
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.../....main.MainActivity}: java.lang.NullPointerException
before , i make a ArrayList and New in another activity then i use in main activity and that work right , but for 2d array not work;
Now , how i can use this array that maked new in another activity
public String[][] arr was never initialized.
You need to do something like,
private String[][] arr = null;
public String[][] getArr()
{
if(arr == null)
{
arr = new String[5][6];
}
return arr;
}
Although I personally think you probably wanted to make an array list, or maybe a List of String arrays.
List<String[]> list = new ArrayList<String[]>();
If you wanted to send the array between activities, you should rather make a holder class that holds the array, make it parcellable, and send the holder between activities using Intent Extras. The http://www.parcelabler.com/ helps with making a class Parcelable.
You haven't shown enough code for me to say for sure, but that new call makes it look like your second class is setting up the array on a different instance of your main class; you never show any communication between them.
Okay… To answer your question. MainActivity mainActivity = new MainActivity(); Only creates an object: Instantiates the object. In the second class where you declare the String[][] you are assigning values and that is fine (although not a good design, unless a parent/child class relationship exists). If you were to call textView.setText(arr[1][1].toString()); in the second class you would have the values. But the thing is there is no call back. In other words your main class has no idea what the second class is doing.
I would look at other ways to persist your data. But if your do. You need a way for the first class to know your added values to your array. Which with out some sort of data persistence will be hard.
Why you are doing this in the first place is not clear. The problem is your design. Why are you going back and forth? There is no rhyme or reason. Create your array in the class it will be used and if it will not be used in that class use a data store to persist that data (or pass the data to the next class via an intent; but only primitive types). There are a few ways to data persist in Android. Read the multiple tutorials out there.
Think of OOP principles. Only pass info if it is necessary.. Deal with the info in the class it is created (substantiated). Hope this helps.
As others have said, the NullPointerException should be related to the fact that you are referencing different instances of the MainActivity. Please have a look at the code below, which is working only when arr is declared static AND the array creation is happening before using it in the class where it is actually declared (and not created):
public class Main {
public static void main(String[] args) {
SecondClass sc = new SecondClass();
sc.printArray(1, 1);
FirstClass fc = new FirstClass();
fc.printArray(1, 1);
}
}
class FirstClass {
public static String[][] arr;
public void printArray(int i, int j) {
System.out.println(arr[i][j]);
}
}
class SecondClass {
SecondClass(){}
public void printArray(int i, int j) {
FirstClass fc = new FirstClass();
fc.arr = new String[5][5];
for (int x=0; x<5; x++)
for (int y=0; y<5; y++)
fc.arr[x][y] = Integer.toString(x*y);
System.out.println(fc.arr[i][j]);
}
}
// okay to return empty 2d array..
//simply create one function like below
public static int[][] subsets(int input[],int index) {
if(index==input.length)
{
int arr[][]= {};
return arr;
}

Categories