Why can't I access this array within my constructor?

So, I’ve been looking at this code for the past couple hours, and I can’t for the life of me figure out what’s going on.

Please note: For the sake of keeping things simple, I didn’t list the contents of the array sizeindex (with a length of 95). If you think seeing its contents might be useful, just tell me.

int[] sizeindex={/*An extremely long array right here.  I've tried shortening it to see if that was the problem, but nothing changed.*/};

float getWidth(int Code, float txSize) { //this returns the width of a character given its Unicode expression (to those reading who are curious, the array only works for Unicode between 32 and 126)
  return (sizeindex[Code-32]*txSize)/80.0; //find the size index, multiply by the text size, divide by 80 (I added the divide by 80 part because I didn't want to suck up too much memory with an array of 95 floats)
}

And then, in another tab, I have a class called button. This is its constructor

button(float x1, float y1, float wdth, float hgt, float ra, color col1, color col2, color col3, String txt, float txsz, boolean texed, int spec, String inpu) { //this is our constructor
    boxx=x1; boxy=y1; wid=wdth; hig=hgt;
    txcol=col1; boxcol=col2; backcol=col3;
    rad=ra;
    text=txt; txsiz=txsz;
    txed=texed; spc=spec; inp=inpu;
    
    siz=0;
    for(int n=0;n<inpu.length();n++) {
      println(n); //this line was here to debug.  If it helps, the code returned a 0 before it gave me the error message
      siz+=getWidth(int(inpu.charAt(n)), 20.0);
    }
    
    lum=0.25;
    lum2=0.25;
    vis=true;
    
    parent=pNull;
  }

My problem is, once I introduced the getWidth function into the constructor, I received an error that looks like this:

java.lang.reflect.InvocationTargetException

I tried removing certain snippets of code selectively, until I concluded that getWidth’s reference to sizeindex is what’s causing the issue. getWidth seems to work outside of this constructor, but not inside. Not unless I remove the reference to sizeindex and instead tell it to return, say, 0. If I do that, then the code works without so much as a stutter.

My question is this: Why can I not access sizeindex inside this constructor? From what I can tell, it should be a global variable. If that’s not the case, or if classes are very picky about how global a variable can be, what do I do to fix this issue?

Help would be much appreciated. Thank you!

P.S. I don’t know if you’ll find this information useful, but I tried removing the call to getWidth in the constructor and replacing it with println(sizeindex[0]); I got the same error about reflect invocation.

1 Like

Excuse my rusty java knowledge, but you might try declaring sizeindex and getWidth() as static. IDK if this’ll do anything but I know globals/scope with processing is a little wonky.

Well, I’m even rustier when it comes to static variables, so I guess we’re both in a pickle

Hi,

Can you provide an example and more of the code? I tried to test it but I could not replicate your error.

Meanwhile, try checking this link:
https://www.baeldung.com/java-lang-reflect-invocationtargetexception

java.lang.reflect.InvocationTargetException this is the exception that is being thrown but look at the lines below this in the stack trace, it should have information about the cause . If you can please post the exception stack trace here.

1 Like

0
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at processing.core.PApplet.runSketch(PApplet.java:10852)
at processing.core.PApplet.main(PApplet.java:10620)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at processing.core.PApplet.runSketch(PApplet.java:10846)
… 1 more
Caused by: java.lang.NullPointerException
at IO_Library_1_2.getWidth(IO_Library_1_2.java:671)
at IO_Library_1_2$button.(IO_Library_1_2.java:195)
at IO_Library_1_2.(IO_Library_1_2.java:25)
… 6 more
RuntimeException: java.lang.reflect.InvocationTargetException

That’s what comes out on the console. Please note the 0 is in white, whilst everything else is in red.

1 Like

@MiguelSanches Here, go nuts. Please note I actually removed a lot of the code for the sake of isolating the problem. I made sure that, even with all those segments of code removed, the same problem persisted. With that said, I’ve attached the error outputs at the end in case anything’s different.

Declaration in main tab:

button test=new button("TEST");

entirety of button class:

class button { //this object represents a button on screen
  
  float siz;
  
  button() { } //default constructor
  
  button(String inpu) { //this is our constructor
    
    siz=0;
    for(int n=0;n<inpu.length();n++) {
      println(n);
      siz+=getWidth(int(inpu.charAt(n)), 20.0);
    }
  }
  
}

button bNull=new button(); //this will store an empty button, and will be treated as null
// 32: 1st typeable, 48-57: 0-9, 65-90: A-Z, 97-122: a-z, 126: last typeable (N=78, n=110)

//                0   1   2   3   4   5   6   7   8   9

int[] sizeindex={0 , 67, 67, 67, 67, 67, 67, 49, 80, 71, //0
                 80, 67, 67, 50, 50, 67, 70, 70, 46, 41, //1
                 50, 50, 63, 46, 46, 46, 74, 74, 63, 93, //2
                 78, 78, 25, 25, 30, 51, 50, 53, 56, 18, //3
                 26, 26, 38, 63, 25, 46, 25, 42, 50, 50, //4
                 50, 50, 50, 50, 50, 50, 50, 50, 25, 25, //5
                 63, 63, 63, 34, 69, 55, 46, 55, 60, 43, //6
                 43, 58, 59, 23, 25, 52, 43, 69, 59, 62, //7
                 44, 62, 51, 43, 51, 55, 52, 68, 50, 50, //8
                 48, 26, 42, 26, 50, 40, 49, 44, 50, 41, //9
                 50, 44, 29, 50, 50, 23, 24, 47, 23, 74, //10
                 50, 49, 50, 50, 33, 41, 30, 50, 41, 62, //11
                 49, 42, 46, 26, 30, 26, 50, 67, 55, 50, //12
                 44, 44, 44, 44, 44, 41, 44, 44, 44, 23, //13
                 23, 23, 55, 55, 43, 68, 72, 49, 49, 49, //14
                 50, 50, 42, 62, 55, 50, 50, 50, 89, 50, //15
                 44, 23, 49, 50, 50, 59, 38, 38, 34, 63, //16
                 63, 64, 64, 25, 42, 42, 80, 80, 80, 79, //17
                 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, //18
                 79, 79, 80, 80, 80, 80, 80, 80, 80, 80, //19
                 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, //20
                 80, 80, 80, 80, 80, 80, 80, 79, 80, 80, //21
                 80, 79, 80, 80, 55, 48, 41, 62, 47, 54, //22
                 50, 43, 56, 62, 64, 47, 75, 65, 42, 63, //23
                 63, 63, 63, 63, 34, 34, 63, 63, 35, 50, //24
                 25, 64, 34, 34, 65, 55, 46, 41, 56, 43, //25
                 48, 59, 62, 23, 52, 52, 69, 59, 50, 62, //26
                 59, 44, 60, 47, 51, 51, 56, 50, 58, 64, //27
                 55, 48, 45, 47, 42, 50, 50, 49, 29, 44, //28
                 47, 50, 44, 46, 49, 62, 49, 46, 54, 43, //29
                 48, 65, 44, 63, 72};                    //30

float getWidth(int Code, float txSize) { //this returns the width of a character given its Unicode representation and textSize
  return (sizeindex[Code]*txSize)/80.0; //find the alt Code, find the size index, multiply by the text size, divide by 80
  //return sizeindex[0];
}

and now for the error code:

RuntimeException: java.lang.reflect.InvocationTargetException

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

at processing.core.PApplet.runSketch(PApplet.java:10852)
at processing.core.PApplet.main(PApplet.java:10620)

Caused by: java.lang.reflect.InvocationTargetException

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at processing.core.PApplet.runSketch(PApplet.java:10846)
... 1 more

Caused by: java.lang.NullPointerException

at sketch_200605a.getWidth(sketch_200605a.java:74)
at sketch_200605a$button.<init>(sketch_200605a.java:29)
at sketch_200605a.<init>(sketch_200605a.java:17)
... 6 more

0

Of course, if you really want, I could attach the entirety of the code. Tbh, at this point, I’m honestly just considering have a loop that sets the siz for each button within the setup function.

Oh, by the way, please note, I don’t know anything about exceptions in java. I learned a little bit about the try catch block in my C++ class, but it seems to be an entirely different monster in Javascript so I decided to just leave it be.

1 Like

The red bit is the stack trace :smile:

These show that the exception was thrown by a constructor (but we new that). The nest few lines are interesting

The original cause of the exception was an NPE in the getWidth method in the inner class ($ = inner class) called button

If we look at that method there is only one line of code
return (sizeindex[Code-32]*txSize)/80.0;

It would suggest that the array sizeindex[] has not been instantiated yet.
Try modifying getWidth to -

float getWidth(int Code, float txSize) { 
  if(sizeIndex == null){
    println("++++++++++++++++++  Array not instantiated +++++++++++++++++ ");
    return 0;
  }
  return (sizeindex[Code-32]*txSize)/80.0; 
}

and see what happens.

4 Likes

@quark Well, that did the trick. :blush: I can’t tell yet if it’s a permanent solution, but it certainly seems to run like it used to now. I’ll mark your answer as the solution once I’ve determined that everything runs smoothly (or at the very least, that everything involving this one specific issue is fixed).

On that note, could you please tell me what the null equivalents of each class is? Or, better yet, link it to me? Because I didn’t know until today that you could check if an array was null. As you can see from the code I provided (under “class button {”), null object patterns are very useful to me.

@quark Okay, so it did “work”, as in it ran, but it appears all of the buttons now have a siz of 0 :disappointed:. Once I opened up the program, the output console was flooded with “array not instantiated”. Should I be declaring these buttons within the setup function? Or is there a way to do this without having them within setup? Or, would that not even work in the first place?

(Note that the reason I’m not just trying this out and seeing for myself is because A. I actually have a lot of buttons programmed in, and B. I know that somebody else might run into a similar problem involving declaring something within a class, and would probably turn here to see the solution.)

In Java all arrays are in fact objects so the statement float[] array declares an array of type float, since arrays are objects then array is an object reference so will be initialised to null.

The statement array = new float[100] instantiates an array of 100 floats and assigns the object reference, array, a non-null value;

Now we have got that out of the way back to your problem. The test proves that the array sizeIndex has been declared but not instantiated when the getWidth method is called in the constructor.

Change my code to

float getWidth(int Code, float txSize) { 
  if(sizeIndex == null){
    println("++++++++++++++++++  Array not instantiated +++++++++++++++++ ");
    return 100;
  }
  return (sizeindex[Code-32]*txSize)/80.0; 
}

and all your buttons will be 100 wide.

So you have to discover why the array is not being created before the method getWidth is executed.

I can’t really do more without seeing the whole code. I will PM you with my email address and you can send the archive sketch to me. You can archive a sketch from the tools menu , its creates a zip file you can attach to the email.

1 Like

All Java non-primitive variables are initialized w/ the value null until we assign an object reference to them.

If we make sure to initialize all our variables we shouldn’t need to check them for null.

Just initialize them at the same time they’re declared or postpone them to Processing’s setup() callback.

On the online sketch below, its 2 arrays EDGES[][] & nodes[][] are never checked for null, b/c they were properly initialized at the top of the sketch:

More about NullPointerException (NPE) troubleshooting:

1 Like

OK I have had a chance to look at your code and I have found the problem.

It is as I said before the array sizeindex is not being created before we attempt to use it by calling getWidth() in the button constructor.

In your code you

  1. declare and initialise the sizeindex array (Size_Index tab)
  2. declare and create a panel instance called examp which in turn creates a button instance (main sketch tab)

both of these are outside any method so will be done when the sketch is launched and before setup() is executed.
It is imperative that they are done in this order i.e. 1 followed by 2

Unfortunately in your code they are done in the wrong order so you get an exception in the button class constructor.

The solution is simple move the code that creates the panel into setup(). The code below shows what I mean

// Declare the panel here but instantiate it in setup
panel examp;

keyIn kCurr=new keyIn(0,0); //user's current  key inputs
keyIn kPrev=new keyIn(0,0); //user's previous key inputs

panel[] allPanels;

boolean insert=false; //this is true when insert is turned on (or rather, if it has been turned on an odd number of times since compiling)

void setup() {
  size(700,700);
  textAlign(CENTER,CENTER);
  // Create the panel here in setup
  examp=new panel(0,0, 700,700, 600,600,
                      new textbox [] {new textbox(11,310,550,30,20,#00FFFF,#00FFFF,#00FFFF,#000000), new textbox(200,100,300,20,10,#00FFFF,#00FFFF,#00FFFF,#000000), new textbox(100,600,500,50,20,#00FFFF,#00FFFF,#00FFFF,#000000)},
                      new button  [] {new button(200,400,50,50,10,#00FF00,#00FF00,#008000,"TEST",18,true,-1,"TEST",400), new button (260,400,50,50,10,#FF0000,#FF0000,#800000,"CLR",20,true,4,"",0), new button(320,400,50,50,10,#00FFFF,#00FFFF,#008080,"⌂",20,true,5,"",0), new button(380,400,50,50,10,#00FFFF,#00FFFF,#008080,"END",20,true,6,"",0), new button(440,400,50,50,10,#00FFFF,#00FFFF,#008080,"fixed",15,false,4,"",0), new button(500,400,50,50,10,#00FFFF,#00FFFF,#008080,"Move",20,false,5,"",0)},
                      new scroller[] {new scroller(575,0,25,600,#808080,true)},
                      new panel[1]);
  examp.pans[0]=new panel(50,350, 100,500, 100,200,
                          new textbox[0],
                          new button[] {new button(50,350,50,50,10,#00FF00,#00FF00,#008000,"a",20,true,-1,"a",11), new button(100,350,50,50,10,#00FF00,#00FF00,#008000,"b",20,true,-1,"b",12.75), new button(50,800,50,50,10,#00FF00,#00FF00,#008000,"Ins",15,true,10,"",0)},
                          new scroller[] {new scroller(125,350,25,200,#808080,true)},
                          new panel[0]);
  
  allPanels=new panel[] {examp.pans[0], examp};
}
3 Likes

Okay, so in order to make this work, I’m gonna have to instantiate all panels within the setup?

(For those reading, the code I sent @quark had a class called “panels” within it, whose job is to contain a bunch of text boxes, buttons, scroll bars, and sometimes other panels, then display them all within a scrollable window)