I've been searching a lot for this problem and I can't find a solution. I'm trying to build a mini-game and I have a method for creating platforms. I have a class with every platform parameters, and I made a class array so i can have multiple platforms at the same time.
Problem: When I try to call the method for constructing the platform by sending the parameters I want, it gives me a NullPointerException. The method was working before, but with everything static and so i couldnt have multiple instances of that class, and now I removed the static fields from the platform class and it gives me the NullPointerException every time I call the method.
I copied the part of the code that gives me the error, the error goes the following way:
public static void main(String[] args) {
Game ex = new Game();
new Thread(ex).start();
}
In Game class:
public Load_Stage load = new Load_Stage();
public Game() {
-other variables initializatin-
Initialize_Items();
load.Stage_1(); // <--- problem this way
In Load_Stage class:
public class Load_Stage {
public Platforms plat = new Platforms();
public void Stage_1(){
Stage_Builder.Build_Platform(200, 500, 300, plat.platform1);
Stage_Builder.Build_Platform(100, 200, 100, plat.platform1);
}
}
And inside the Stage_Builder class:
public class Stage_Builder {
public static final int max_platforms = 10;
public static Platform_1[] p1 = new Platform_1[max_platforms];
public static boolean[] platform_on = new boolean[max_platforms];
public Stage_Builder() {
for (int c = 0; c < platform_on.length; c++) {
platform_on[c] = false;
}
}
public static void Build_Platform(int x, int y, int width, ImageIcon[] type) { // BUILDS A PLATFORM
for (int b = 0; b < max_platforms; b++) {
if (platform_on[b] == false) {
p1[b].Construct(x, y, width, type); // <-- NullPointerException here
platform_on[b] = true;
break;
}
}
}
}
Thanks beforehand.
EDIT: Here's the Platform_1 class (sorry for forgetting about it):
public class Platform_1 {
private int platform_begin_width = 30;
private int platform_middle_width = 20;
public int blocks_number = 0;
public ImageIcon[] platform_floors = new ImageIcon[500];
private int current_width = 0;
public int [] platform_x = new int [500];
public int platform_y = 0;
public int platform_width = 0;
public void Construct(int x, int y, int width, ImageIcon [] type) {
platform_width = width;
platform_y = y;
for (int c = 0; current_width <= platform_width; c++) {
if (c == 0) {
platform_x[c] = x;
platform_floors[c] = type[0];
current_width += platform_begin_width;
} else if ((current_width + platform_middle_width) > platform_width) {
platform_floors[c] = type[2];
blocks_number = c + 1;
platform_x[c] = current_width + x;
current_width += platform_middle_width;
} else {
platform_floors[c] = type[1];
platform_x[c] = current_width + x;
current_width += platform_middle_width;
}
}
}
}
And the Platforms class:
public class Platforms {
public ImageIcon[] platform1 = {new ImageIcon("Resources/Sprites/Stage_Objects/Platform1/begin.png"),
new ImageIcon("Resources/Sprites/Stage_Objects/Platform1/middle.png"),
new ImageIcon("Resources/Sprites/Stage_Objects/Platform1/end.png")};
}
The problem and solution are both obvious.
public static Platform_1[] p1 = new Platform_1[max_platforms];
After this line of code executes, p1 is an array of references of type Platform_1 that are all null.
Executing this line of code tells you so right away:
p1[b].Construct(x, y, width, type); // <-- NullPointerException here
The solution is to intialize the p1 array to point to non-null instances of Platform_1.
Something like this would work:
for (int i = 0; < p1.length; ++i) {
p1[i] = new Platform1();
}
I'm not seeing where you put things in the p1 array in the Stage_Builder class.
Another possibility (unlikely, but possible if you haven't shown everything) is that something in the Platform class, which you didn't show, is not initialized, and is breaking when you call Construct.
Also, the following seems problematic
public static Platform_1[] p1 = new Platform_1[max_platforms];
public static boolean[] platform_on = new boolean[max_platforms];
public Stage_Builder() {
for (int c = 0; c < platform_on.length; c++) {
platform_on[c] = false;
}
}
it appears you declare static variables p1 and platform_on, but you only populate platform_on in a constructor. So the first time you create a Stage_Builder instance, you populate one static array with all false, and don't put anything in the other static array...
Populate those static variables in a static block
// static var declarations
static {
// populate static arrays here.
}
The array you are calling a message on was never filled.
You have
public static Platform_1[] p1 = new Platform_1[max_platforms];
so p1 is
p1[0] = null
p1[1] = null
.
.
.
p1[max_platforms] = null
You try to call
p1[b].Construct(x, y, width, type);
which is
null.Construct(...);
You need to initialize that index on the array first.
p1[b] = new Platform_1();
p1[b].Construct(...);
First of all, your problem is that p1[b] is most likely null, as duffymo pointed out.
Secondly, you are using arrays in a really weird way. What about
a) delete Stage_Builder
b) Instead, have an ArrayList somewhere
c) The equivalent of Build_Platform1() look like this, then:
p1.add(new Platform1(x, y, width, type);
d) no if on[i], no max_platforms, no for loop to add a platform (the latter is a bad performance problem if you actually have a few hundret platforms)
Related
While coding I was trying to declare a class that can create an arraylist of arraylists, but soon enough I found it hard to define a proper constructor for my class. I wanted to define some methods for me to handle the huge outer arraylist(1000*1000), but I might be affected by C and always tried to use something like structdef.
How should I define my class? I guess declaring every lines seperatedly is not a wise choice, and I don't want to use 2D arraylist directly. Besides, how should I define a constructor to get an object that is an 2D arraylist?
//Update here
Below is my code example:
class farbicMap {
//attribute
ArrayList<Integer> farbicUnit = new ArrayList<Integer>();
//constructor
farbicMap () {
for (int i=0;i<1000;++i) {
farbicUnit.add(0);
}//this gives an arraylist with size of 100
//I want to use the above arraylist to construct another list here
}
//method
setUnitValue(int v) {
...
}
}
Seems that I didn't really understand the concept of class... I wanted to use the class to represent a map with some nodes. Now that's much clearer to me.
This is how I understood your consern:
class Test {
public static void main(String[] args) {
Board board = new Board(1000, 1000);
board.put(1, 2, "X");
Object x = board.get(1, 2);
System.out.println("x = " + x);
}
}
class Board {
private final int xSize;
private final int ySize;
private ArrayList<ArrayList<Object>> board = new ArrayList<>();
public Board(int xSize, int ySize) {
this.xSize = xSize;
this.ySize = ySize;
for (int i = 0; i < xSize; i++) {
board.add(getListOfNulls());
}
}
public Object get(int x, int y) {
return board.get(x).get(y);
}
public void put(int x, int y, Object toAdd) {
List<Object> xs = board.get(x);
if (xs == null) {
xs = getListOfNulls();
}
xs.add(y, toAdd);
}
private ArrayList<Object> getListOfNulls() {
ArrayList<Object> ys = new ArrayList<>();
for (int j = 0; j < ySize; j++) {
ys.add(null);
}
return ys;
}
}
You should use Array if size is fixed.
Note: This is a troubling problem, possibly a bug, although I might be incorrect and missing something small
Problem:
Issue is the separately instantiated objects are referring to the same data structure.
Calling a.add() adds an object to data[NEXT], where is instantiated to NEXT = 0, followed by NEXT++ for increment purposes.
Thereafter, b.add() is called, and following the logic of the add() method, the array is extended,
BUT no initial value has been inserted into b i.e. b.data[0] = null
TL;DR
a.add() adds value to a.
b.add() extends a's array. This should not happen as a and b are 2 separate objects of the same type
main class code:
//...
SimpleSet<Integer> a = new SimpleSet<>();
SimpleSet<Integer> b = new SimpleSet<>();
// add a maximum of 20 unique random numbers from 0..99
Random rand = new Random();
for (int i = 0; i < 20; i++) {
a.add(rand.nextInt(100)); //i=0 - adds to data[0] with no issue
b.add(rand.nextInt(100)); //i=0 - extends a's array? why?
}
//...
class SimpleSet
public class SimpleSet<E> {
private static int MIN_SIZE = 1;
private static int NEXT = 0;
private Object[] data;
/**
* constructor of SimpleSet
*/
public SimpleSet() {
data = new Object[MIN_SIZE];
}
public void add(E e) {
if(NEXT > 0.75*MIN_SIZE){
extendArray();
}
if (data != null) {
data[NEXT] = e;
NEXT++;
}
}
private void extendArray() {
MIN_SIZE = MIN_SIZE*2;
Object[] newData = new Object[MIN_SIZE];
for (int i = 0; i < data.length; i++) {
newData[i] = data[i];
}
data = newData;
return;
}
//...
}
Am I missing something small or is this a bug?
IDE = IntelliJ 2016.3
I want to create a game and I need to read file from the notepad
when I use my loadfile.java alone, it work very well. Then, I would like to copy my data into datafile.java as it will be easier for me to do the fighting scene. However, I can't copy the array in my loadfile.java to the datafile.java and I don't understand why.
import javax.swing.*;
import java.io.*;
import java.util.Scanner;
public class loadfile
{
static String filename = "Save.txt";
static int size = 4;
static int s;
static int[] number;
static String[] line;
private static void load() throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
while (reader.readLine()!= null)
{
size++;
}
size -= 4;
reader.close();
line = new String[size];
number = new int[size];
BufferedReader reader2 = new BufferedReader(new FileReader(filename));
for (int i = 0; i < size; i++)
{
line[i] = reader2.readLine();
}
reader2.close();
for (int i = 4; i < size; i++)
{
number[i] = Integer.parseInt(line[i]);
}
}
public static String[] getData()
{
return line;
}
public static int[] getNumber()
{
s = size - 4;
int[] num = new int[s];
for (int i = 0; i < s; i++)
{
num[i] = number[i+4];
}
return num;
}
public static int getDataSize()
{
return size;
}
public static int getNumberSize()
{
return size - 4;
}
This is my loadfile.java
I use the file with 4 names and 9 * n int in the notepad as I want to check whether I have the character first before I read the file. However, before I can handle this problem, I got another problem that I can't copy the array into my datafile.java
The datafile.java is separate with two constructor. One is for Starting the game and one is for loading the data. The constructor with the (int num) is the problem I have. First, I would like to show the java first:
import java.util.Arrays;
import java.io.*;
public class datafile
{
private static String[] data;
private static int[] number;
private static String[] name;
private static int[] a, d, s;
private static int[] hp, maxhp;
private static int[] mp, maxmp;
private static int[] lv, exp;
public datafile()
{
initialization();
name[0] = "Pet";
a[0] = 100;
d[0] = 100;
s[0] = 100;
hp[0] = 500;
mp[0] = 500;
maxhp[0] = 500;
maxmp[0] = 500;
exp[0] = 100;
lv[0] = 1;
}
public datafile(int num) throws IOException
{
initialization();
loadfile l = new loadfile();
for (int i = 0; i < l.getNumberSize(); i++)
{
number[i] = l.getNumber()[i];
}
for (int i = 0; i < l.getDataSize(); i++)
{
data[i] = l.getData()[i];
}
for(int i = 0; i < 4; i++)
{
name[i] = data[i];
}
for(int i = 0; i < 4; i++)
{
a[i] = number[1+(i*9)];
d[i] = number[2+(i*9)];
s[i] = number[3+(i*9)];
hp[i] = number[4+(i*9)];
mp[i] = number[5+(i*9)];
maxhp[i] = number[6+(i*9)];
maxmp[i] = number[7+(i*9)];
lv[i] = number[8+(i*9)];
exp[i] = number[9+(i*9)];
}
}
public static String getName(int n)
{
return name[n];
}
public static int getAttack(int n)
{
return a[n];
}
public static int getDefense(int n)
{
return d[n];
}
public void initialization()
{
name = new String[3];
a = new int[3];
d = new int[3];
s = new int[3];
hp = new int[3];
mp = new int[3];
maxhp = new int[3];
maxmp = new int[3];
lv = new int[3];
exp = new int[3];
}
public static void main (String[] args) throws IOException
{
new datafile(1);
}
}
When I run the program, the debugging state this line
data[i] = l.getData()[i];
as an error
I don't know what wrong with this line and I tried so many different ways to change the way the copy the method. However, it didn't work
The error says this:
Exception in thread "main" java.lang.NullPointerException
at datafile.<init>(datafile.java:38)
at datafile.main(datafile.java:92)
I hope you guys can help me with this problem because I don't want to fail with my first work
in your datafile(int num)
you call
loadfile l = new loadfile();
but you never call the load() method on you loadfile
l.load();
Edit: my bad, I didn't see your initialization method, but regardless, I'm going to stick with my recommendation that you radically change your program design. Your code consists of a kludge -- you've got many strangely named static array variables as some kind of data repository, and this suggests that injecting a little object-oriented design could go a long way towards creating classes that are much easier to debug, maintain and enhance:
First I recommend that you get rid of all of the parallel arrays and instead create a class, or likely classes, to hold the fields that need to be bound together and create an ArrayList of items of this class.
For example
public class Creature {
private String name;
private int attack;
private int defense;
// constructors here
// getters and setters...
}
And elsewhere:
private List<Creature> creatureList = new ArrayList<>();
Note that the Creature class, the repository for some of your data, should not be calling or even have knowledge of the code that loads the data, but rather it should be the other way around. The class that loads data should create MyData objects that can then be placed within the myDataList ArrayList via its add(...) method.
As a side recommendation, to help us now and to help yourself in the future, please edit your code and change your variable names to conform with Java naming conventions: class names all start with an upper-case letter and method/variable names with a lower-case letter.
I'm trying to get a radix sort going with an array of queues to avoid long rambling switch statements but I'm having some trouble getting the array properly initialized. The constructor and an example of an implementation are given below.
I'm just getting a cannot find symbol error when I try to compile though.
public static radixj(){
IntQueue[] buckets = new IntQueue[10];
for (int i = 0; i < 10; i++)
buckets[i] = new IntQueue();
}
public static void place(int temp, int marker)
{
int pos = temp % marker;
buckets[pos].put(temp);
}
I'm pretty sure it is a really simple mistake that I'm making but I can't find it. Any help would be greatly appreciated.
In your code
IntQueue[] buckets = new IntQueue[10];
is a local variable to the function
public static radixj()
which must have a return type
public static void radixj()
So then you can't use it in another function
buckets[pos].put(temp);
You should declare a static class variable
class Foo {
static IntQueue[] buckets = new IntQueue[10];
...
and access it using: Foo.buckets
class Foo {
public static IntQueue[] buckets = new IntQueue[10];
public static void radixj() {
for (int i = 0; i < 10; i++) {
Foo.buckets[i] = new IntQueue();
}
}
public static void place(int temp, int marker) {
int pos = temp % marker;
Foo.buckets[pos].put(temp);
}
}
the return type in radixj() is missing and buckets cannot be resolved to a variable
I've been trying to code a simple screenshot application using rococoa (java to osx cocoa api library), and managed to get as far as actually taking the screenshot, and then saving it to a file. Unfortunately, once in a while, the application fails with an 'Invalid memory access of location...' error. I'm assuming this is due to something being garbage collected, because I'm failing to keep a reference alive. The line that is causing the crash is:
int[] data = pointer.getIntArray(0, bytesPerPlane / 4);
I really haven't coded anything with Objective C, and just starting up with rococoa, so I'm finding myself just confused with this. I've copied the relevant code below, and would really appreciate any help with this!
public interface QuartzLibrary extends Library {
QuartzLibrary INSTANCE = (QuartzLibrary) Native.loadLibrary("Quartz", QuartzLibrary.class);
class CGPoint extends Structure {
public double x;
public double y;
}
class CGSize extends Structure {
public double width;
public double height;
}
class CGRect extends Structure implements Structure.ByValue {
public static class CGRectByValue extends CGRect { }
public CGPoint origin;
public CGSize size;
}
int kCGWindowListOptionIncludingWindow = (1 << 3);
int kCGWindowImageBoundsIgnoreFraming = (1 << 0);
ID CGWindowListCreateImage(CGRect screenBounds, int windowOption, int windowId, int imageOption);
}
public interface NSBitmapImageRep extends NSObject {
public static final _Class CLASS = Rococoa.createClass("NSBitmapImageRep", _Class.class);
public interface _Class extends NSClass {
NSBitmapImageRep alloc();
}
NSBitmapImageRep initWithCGImage(ID imageRef);
com.sun.jna.Pointer bitmapData();
NSSize size();
}
public class Screenshot {
public static void getScreenshot(int windowId) throws IOException {
QuartzLibrary.CGRect bounds = new QuartzLibrary.CGRect.CGRectByValue();
bounds.origin = new QuartzLibrary.CGPoint();
bounds.origin.x = 0;
bounds.origin.y = 0;
bounds.size = new QuartzLibrary.CGSize();
bounds.size.width = 0;
bounds.size.height = 0;
ID imageRef = QuartzLibrary.INSTANCE.CGWindowListCreateImage(bounds, QuartzLibrary.kCGWindowListOptionIncludingWindow, windowId, QuartzLibrary.kCGWindowImageBoundsIgnoreFraming);
NSBitmapImageRep imageRep = NSBitmapImageRep.CLASS.alloc();
imageRep = imageRep.initWithCGImage(imageRef);
NSSize size = imageRep.size();
com.sun.jna.Pointer pointer = imageRep.bitmapData();
int width = size.width.intValue();
int height = size.height.intValue();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// The crash always happens when calling 'getIntArray' in the next line.
int[] data = pointer.getIntArray(0, bytesPerPlane / 4);
int idx = 0;
for(int y = 0; y < height; y++)
for(int x = 0; x < width; x++)
image.setRGB(x, y, data[idx++]);
ImageIO.write(image, "png", new File("foo.png"));
}
}
Found the problem.
The last use of 'imageRep' is on the line
"com.sun.jna.Pointer pointer = imageRep.bitmapData();".
After this, imageRep is fair game for the Java garbage collector. And if it hits in
before we are done using 'pointer', the backing buffer it's pointing to may/will get
freed, causing bad things to happen.
To fix it, adding an extra set of retain/release for imageRep does the job, or alternatively
adding any reference to it to the end of the method.
Possibly related, possibly not: NSBitmapImageRep descends from NSImageRep, not directly from NSObject.