So, adding stuff to my custom linked list is causing a NullPointerException, and I cannot, for the life of me, figure out why. The purpose of the program is to simulate a chest of drawers, with a list that has the drawers as nodes. The drawers each have a list that includes household objects as nodes.
Here's the relevant bits of code. The error happens when I create a: new ChestOfDrawers(3); in my UI class:
public class ChestOfDrawers{
private static OwnList chest;
private static int[] parametres;
public ChestOfDrawers (int drawers){
chest = new OwnList();
create();
}
public static void create(){
for (int i = 0; i < parametres.length; i++) {
Object drawer = new Drawer(i, parametres[i]);
chest.add(i, drawer); //This is causing the error
}
}
}
The Drawer class being referred to here is the class for the drawers. It requires int i as an ID and int parametres as drawer capacity. The parametres[] array gets filled before the additions to the list are made and it includes info for drawer capacity. The linked list in the question (OwnList) is functioning 100% correctly as it is part of a provided course material, it's near identical to Java's own. I tested the class in another test class and it worked fine, I've just made a mistake here somewhere. Please help!
The problem is that you are not initializing the parametres array. This field will be null by default. You need to either initialize it where it is declared, or in a static initializer block. Additionally, why are the two fields and the create method static? Those certainly seem like instance state...
Here's a better version:
public final class ChestOfDrawers{
private final OwnList chest = new OwnList();
private final int[] parametres;
public ChestOfDrawers (int drawers){
if (drawers < 0) throw new IllegalArgumentException("Drawers may not be negative");
chest = new OwnList();
parametres = new int[drawers]; // <-- I'm assuming that's the intended meaning
initialize();
}
private void initialize(){
for(int i = 0; i < parametres.length; i++){
Object drawer = new Drawer(i, parametres[i]); // <-- parametres[i] will always be 0
chest.add(i, drawer);
}
}
}
I'm not sure what you need the parametres array to actually contain (a new array of int will be filled with zero values) - but I'll leave that as an exercise to the reader :-)
Related
How do I add a card to my hand when it says "addCardToHand" I tried card++; and hand++; neither worked. Is there a problem with my code, or did I just left something out? I feel like I need to add something but, I don't know what.
private AbstractCard[] hand;
private int winCount;
public AbstractPlayer() {
hand = new AbstractCard[0];
}
public AbstractPlayer(int score) {
}
public void addCardToHand( AbstractCard card ) {
AbstractCard[] NewHand = new AbstractCard[hand.length+1];
for ( int i = 0; i < NewHand.length; i++) {
NewHand[i] = hand[i];
}
}
public void resetHand() {
hand = new AbstractCard[0];
}
I think it's probably because hand[] has nothing in it. It gets created as an array with size 0, (no elements), and then when you add a card, you pull from the hand[] at index 0, but since the hand[] has no elements, it's not pulling from anywhere.
Basically, nowhere in your code does hand[] ever get to be an array with any elements in it, so when you take from hand[0] there's nothing there, because in hand = new AbstractCard[0];, [0] is the size of the array.
EDIT:
You might want to look into using an ArrayList (Oracle documentation) (Stack Overflow post), because they don't have a pre-defined size. In your case, you're adding elements as you go, so an ArrayList be very helpful. With an ArrayList, you won't have to constantly create new arrays.
You probably want to keep track of the next insert position for cards with some state like private int insertCursor = 0;
Your addCardToHand(AbstractCard) method can then simply be
public void addCardToHand(AbstractCard card) {
hand[insertCursor++] = card;
}
I've done the searching and it seems to be a case by case basis as to what's causing this. Though, someone who truly understands it will quite possibly disagree.
My buttons going from my main screen into other activities work just fine, the only difference with the one that doesn't work is that it's actually pulling a class/variable from another .java file and so I'm sure I haven't implemented it correctly.
It's a Singleton class:
GLOBAL.JAVA
//Constructor
//
protected Global() {
getInstance();
}
//Singleton Method
//
public static Global getInstance() {
if(instance == null) {
initialize();
instance = new Global();
}
return instance;
}
I have a few (static)class structures(I use the term structures because I program primarily in C++, and to me, that's what they are) that are placed inside the Global file/class, along with this array that holds all the data for the program static questionStruct[] questions = new questionStruct[TOTAL_QUESTIONS];
The initialize(); function called from the getInstance()(Singleton Method) simply fills in the data into the questionStruct[] array.
I have a method to return a string
public static String getQ(int q){
return questions[q].q;
}
In the .java file that gets called from the button pressed, I have placeData(); just to test things out, and in that function:
public void placeData() {
String testString = ("Testing Text: " + Global.getQ(3));
TextView Q = (TextView) findViewById(R.id.testingText);
Q.setText(testString);
}
and lastly... hopefully... the TextView where it's supposed to show up in the XML file:
<TextView
android:id="#+id/testingText"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
And here's my official error I believe is the indicator to the crash, that only occurs when I press the button to initialize this activity.
java.lang.RuntimeException: Unable to start activity ComponentInfo{godwin.com.study/godwin.com.study.practice}: java.lang.NullPointerException: Attempt to read from field 'java.lang.String godwin.com.study.Global$questionStruct.q' on a null object reference
Thoughts???
EDIT:
Classes (like a structure in C++) inside of Global.Java
class answerStruct
{
String a;
boolean status;
}
//Structure for Questions
//
class questionStruct
{
String q;
answerStruct[] answer = new answerStruct[TOTAL_ANSWERS];
}
The "initialize()" function:
public static void initialize() {
questions[0].q = "Question # 1";
questions[0].answer[0].a = "Q1A1";
questions[0].answer[0].status = true;
questions[0].answer[1].a = "Q1A2";
questions[0].answer[1].status = false;
...And so on...Forever
}
When you allocate an array of objects in Java like this:
static questionStruct[] questions = new questionStruct[TOTAL_QUESTIONS];
You are only allocating an array of object references, you aren't actually allocating the objects themselves. It's kind of like you allocated an array of pointers in C++, but they don't point to anything yet.
At the top of your initialize() function, you can allocate all the questionStruct objects, and also the answers for each in a nested for loop, like this:
for(int i = 0; i < TOTAL_QUESTIONS; i++)
{
questions[i] = new questionStruct();
for(int j = 0; j < TOTAL_QUESTIONS; j++)
questions[i].answer[j] = new answerStruct();
}
Then you can go through and initialize all the fields in the structs as you are doing.
I recently came across a very stupid (at least from my point of view) implementation inside Androids Parcel class.
Suppose I have a simple class like this
class Foo implements Parcelable{
private String[] bars;
//other members
public in describeContents(){
return 0;
}
public void writeToParcel(Parcel dest, int flags){
dest.writeStringArray(bars);
//parcel others
}
private Foo(Parcel source){
source.readStringArray(bars);
//unparcel other members
}
public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>(){
public Foo createFromParcel(Parcel source){
return new Foo(source);
}
public Foo[] newArray(int size){
return new Foo[size];
}
};
}
Now, if I want to Parcel a Foo Object and bars is null I see no way to recover from this situation (exept of catching Exceptions of course). Here is the implementation of these two methods from Parcel:
public final void writeStringArray(String[] val) {
if (val != null) {
int N = val.length;
writeInt(N);
for (int i=0; i<N; i++) {
writeString(val[i]);
}
} else {
writeInt(-1);
}
}
public final void readStringArray(String[] val) {
int N = readInt();
if (N == val.length) {
for (int i=0; i<N; i++) {
val[i] = readString();
}
} else {
throw new RuntimeException("bad array lengths");
}
}
So writeStringArray is fine if I pass bars which are null. It just writes -1 to the Parcel. But How is the method readStringArray supposed to get used? If I pass bars inside (which of course is null) I will get a NullPointerException from val.length. If I create bars before like say bars = new String[???] I don't get any clue how big it should be. If the size doesn't match what was written inside I recieve a RuntimeException.
Why is readStringArray not aware of a result of -1 which gets written on null objects from writeStringArray and just returns?
The only way I see is to save the size of bars before I call writeStringArray(String[]) which makes this method kind of useless. It will also redundatly save the size of the Array twice (one time for me to remember, the second time from writeStringArray).
Does anyone know how these two methods are supposed to be used, as there is NO java-doc for them on top?
You should use Parcel.createStringArray() in your case.
I can't imagine a proper use-case for Parcel.readStringArray(String[] val) but in order to use it you have to know the exact size of array and manually allocate it.
It's not really clear from the (lack of) documentation but readStringArray() is to be used when the object already knows how to create the string array before calling this function; for example when it's statistically instanciated or it's size is known from another previously read value.
What you need here is to call the function createStringArray() instead.
So I'm creating a class called dicegame. Here's the constructor.
public class dicegame {
private static int a, b, winner;
public dicegame()
{
a = 0;
b = 0;
winner = 2;
}
And now in the main, I'm creating an array of this object (I called it spaghetti for fun).
public static void main(String[] args)
{
dicegame[] spaghetti = new dicegame[10];
spaghetti[1].roll();
}
But when I try to do anything to an element in the array, I'm getting the NullPointerException. When I tried to print one of the elements, I got a null.
You created an array, but you have to assign something (e.g. new dicegame()) to each element of the array.
My Java is slightly rusty, but this should be close:
for (int i=0; i<10; i++)
{
spaghetti[i] = new dicegame();
}
new dicegame[10]
just creates an array with 10 empty elements. You still have to put a dicegame in each element:
spaghetti[0] = new dicegame();
spaghetti[1] = new dicegame();
spaghetti[2] = new dicegame();
...
You need spaghetti[1]=new dicegame() before you call roll() on it.
Right now you are allocating an array,but don't. Place any objects in this array, so by default java makes them null.
1.you have just declared the array variable but not created the object yet. try this
2.you should start index with zero not with one.
dicegame[] spaghetti = new dicegame[10]; // created array variable of dicegame
for (int i = 0; i < spaghetti.length; i++) {
spaghetti[i] = new dicegame(); // creating object an assgning to element of spaghetti
spaghetti[i].roll(); // calling roll method.
}
Firstly,you should create object for every spaghetti input of yours.
You can start with whatever value you want. Just be sure that the size of array is matched accordingly so that you won't get ArrayIndexOutOfBounds Exception.
So,if you wanted to start with 1 and have 10 objects of the class dicegame,you will have to assign the size of the array as 11(since it starts from zero).
your main function should be like :
public static void main(String[] args)
{
dicegame[] spaghetti = new dicegame[11];
//the below two lines create object for every spaghetti item
for(int i=1;i<=11;i++)
spaghetti[i]=new dicegame();
//and now if you want to call the function roll for the first element,just call it
spaghetti[1].roll;
}
Ok, here is the code and then the discussion follows:
public class FlatArrayList {
private static ArrayList<TestWrapperObject> probModel = new ArrayList<TestWrapperObject>();
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] currentRow = new int[10];
int counter = 0;
while (true) {
for (int i = 0; i < 10; i++) {
currentRow[i] = probModel.size();
}
TestWrapperObject currentWO = new TestWrapperObject(currentRow);
probModel.add(counter, currentWO);
TestWrapperObject testWO = probModel.get(counter);
// System.out.println(testWO);
counter++;
if (probModel.size() == 10) break;
}
// Output the whole ArrayList
for (TestWrapperObject wo:probModel) {
int [] currentTestRow = wo.getCurrentRow();
}
}
}
public class TestWrapperObject {
private int [] currentRow;
public void setCurrentRow(int [] currentRow) {
this.currentRow = currentRow;
}
public int [] getCurrentRow() {
return this.currentRow;
}
public TestWrapperObject(int [] currentRow) {
this.currentRow = currentRow;
}
}
What is the above code supposed to do? What I am trying to do is load an array as a member of some wrapper object (TestWrapperObject in our case). When I get out of the loop,
the probModel ArrayList has the number of elements it is supposed to have but all have the same value of the last element (an array of size 10 with each item equal to 9). This is not the case inside the loop. If you perform the same "experiment" with a primitive int value everything works fine. Am I missing something myself regarding arrays as object members? Or did I just encounter a Java bug? I am using Java 6.
You are only creating one instance of the currentRow array. Move that inside the row loop and it should behave more like you expect.
Specifically, the assignment in setCurrentRow does not create a copy of the object, but only assigns the reference. So each copy of your wrapper object will hold a reference to the same int[] array. Changing the values in that array will make the values appear to change for all other wrapper objects that hold a reference to the same instance of the array.
i don' t want to sound condescending, but always try to remember tip #26 from the excellent pragmatic programmer book
select isn't broken
it is very rare to find a java bug. keeping this in mind often helps me to look over my code again, turn it around, and shake out the loose bits until i finally discover where i was wrong. of course asking for help early enough is very encouraged, too :)