I got a null pointer exception when accessing a static array from a static member method.
The exception is thrown when i call setData(x, y, z) from a thread. When I debugged it I found out data[0] is null when i try to write to it. I just don't understand how it can be null
public class dataContainer
{
private static final short nrOfDataElements = ids.total_ids;
private static regularDataElement[] data = new regularDataElement[nrOfDataElements];
public static synchronized void getData(final short i, regularDataElement r)
{
if ( (i >= 0) && (i < nrOfDataElements) )
r.set(data[i].getTimestamp(), data[i].getValue());
}
public static synchronized void setData(short i, double ts, long val)
{
if ( (i >= 0) && (i < nrOfDataElements) )
data[i].set(ts, val); //<<-------null pointer exception, debugging showed data[i] == null, (with i = 0 and nrOfDataElements = 12)
}
}
and
public class regularDataElement
{
regularDataElement()
{
set(0, 0);
}
public void set(double _ts, long _val)
{
System.out.println(this.ts + " " + _ts + " " + this.val + " " + _val); System.out.flush();
this.ts = _ts;
this.val = _val;
}
public double getTimestamp()
{
return this.ts;
}
public long getValue()
{
return this.val;
}
private double ts;
private long val;
}
The statement private static regularDataElement[] data = new regularDataElement[nrOfDataElements]; initializes data with an array the size of nrOfDataElements. It does not initialize each element in this array. I.e., all the elements are null.
If you wish to initialize the elements, you should do so yourself. E.g., you could add a static block to handle this:
static regularDataElement[] data = new regularDataElement[nrOfDataElements];
static {
for (int i = 0; i < nrOfDataElements; ++i) {
data[i] = new regularDataElement();
}
}
Did you ever initialize the data array?
private static regularDataElement[] data =
new regularDataElement[nrOfDataElements];
will create an array full of null objects of size nrOfDataElements. It won't actually initialize any elements in the array.
You don't appear to be allocating memory for data[i], which is why you're getting the NPE.
Allocating memory for the array itself is not enough. You need to allocate memory for each element:
for (int i = 0; i < nrOfDataElements; ++i) {
data[i] = new regularDataElement(...);
}
(Replace ... with the actual arguments.)
You never actually create any objects. You must add somewhere:
for (int i = 0; i < data.length; i++) {
data[i] = new regularDataElement();
}
When you initialize an Object array in Java, like data in your code, all elements are by default set to null.
So, you need to populate the data array first, before being able to call any methods against its elements.
Assuming that the regularDataElement class has a no-args (i.e., no parameters) constructor, you could do
static regularDataElement[] data = new regularDataElement[nrOfDataElements];
static
{
for (int i=0; i<nrOfDataElements; i++)
{
data[i] = new regularDataElement();
}
}
Of course, you could have a separate method to initialize the array, e.g.
static regularDataElement[] initialize(int nrOfDataElements)
{
regularDataElement[] elements = new regularDataElement[nrOfDataElements];
for (int i=0; i<nrOfDataElements; i++)
{
elements[i] = new regularDataElement();
}
return elements;
}
and then call that method to create and initialize the data array, replacing the statement
static regularDataElement[] data = new regularDataElement[nrOfDataElements];
with
static regularDataElement[] data = initialize(nrOfDataElements);
Also, as a matter of following established coding conventions, you should name your classes starting with a capital letter, i.e. use RegularDataElement instead of regularDataElement.
Related
So I'm currently working on a project that is recreating methods for Array String Lists and Linked String Lists. There is a StringList interface, that both ArrayStringList and LinkedStringList implement. We are not allowed to see the source code for the interface - only the API documentation. For each class, we have to create a default constructor and copy constructor for both classes. I've ran tests, and the default constructors both pass but the ArrayStringList copy constructor does not work and has been throwing the error message of "null" or "-1". I am pretty new to inheritance and interfaces, and I think the object parameters vs string array data types are throwing me off a bit.
Here is the code I have so far, and the methods used in the constructor:
My Copy Constructor:
private String[] stringArray;
private int size;
public ArrayStringList(StringList sl) {
size = sl.size();
ArrayStringList asl = new ArrayStringList();
for(int i = 0; i < size-1; i++) {
if(sl.get(i) != null) {
asl.set(i,sl.get(i).toString());
} //if
} // for
} // copy constructor
Size Method:
public int size() {
return stringArray.length;
} // size
Get Method:
public String get(int index) {
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException("out of bounds");
} else {
return stringArray[index];
}
} //get
Set Method:
public String set(int index, String s) {
String old = stringArray[index];
stringArray[index] = s;
return old;
} // set
In the project, the description of the copy constructor was as follows:
The implementing class must explicitly define a copy constructor. The copy constructor should take exactly one parameter of the interface type StringList. It should make the newly constructed list object a deep copy of the list referred to by the constructor's parameter. Therefore, the initial size and string elements of the new list object will be the same as the other list. To be clear, the other list can be an object of any implementation of the StringList interface. No other assumptions about the type of the object should be made.
public class ArrayStringList implements StringList {
private static final int INITIAL_CAPACITY = 10;
private String[] stringArray;
private int size;
public ArrayStringList(StringList sl) {
stringArray = sl.toArray();
size = stringArray.length;
}
public ArrayStringList() {
stringArray = new String[INITIAL_CAPACITY];
size = 0;
}
// TODO: Extract 'if-cascade' to an validate(..) method
#Override
public String set(int index, String s) {
if (index >= size) {
throw new IndexOutOfBoundsException("")
} else if (s == null) {
throw new NullPointerException("the specified string is null");
} else if (s.isEmpty()) {
throw new IllegalArgumentException("specified string is empty");
}
String old = stringArray[index];
stringArray[index] = s;
return old;
}
// TODO: Check if posible to extend the stringArray
#Override
public boolean add(String s) {
if (s == null) {
throw new NullPointerException("the specified string is null");
} else if (s.isEmpty()) {
throw new IllegalArgumentException("specified string is empty");
}
if (size == stringArray.length) {
int newListCapacity = stringArray.length * 2;
stringArray = Arrays.copyOf(stringArray, newListCapacity);
}
stringArray[++size] = s;
return true;
}
// TODO: implement other methods ...
}
Keep in mind that this implementation is still buggy, but you can use it as a starting point
public void ArrayStringList(StringList sl) {
size = sl.size();
ArrayStringList asl = new ArrayStringList();
for(int i = 0; i < size; i++) {
if(sl.get(i) != null) {
String s = asl.set(i,sl.get(i).toString());
System.out.println(s);
} //if
} // for
}
Change set method like below. And call it by the help of class object. it will set value in global static list.
//Change set method like this
public String set(int index, String s) {
stringArray[index] = s;
return stringArray[index];
}
I would initialise the internal array to the value of size and also make use of the fact that the String class also has a copy-constructor
public ArrayStringList(StringList sl) {
this.size = sl.size();
this.stringArray = new String[size];
for(int j = 0; j < size; j++) {
this.stringArray[j] = new String(sl.get(i));
}
}
This question already has answers here:
java "void" and "non void" constructor
(5 answers)
Closed 5 years ago.
When ever I add an object to this ArrayList, my resize method, gives me a NullPointerException. The list is initialized with a size of 1, and the first element is added to possition 0 in the array.
Here is my arrayList AKA DynamicArray
//Implementation of a dynamic array
// Add remove methods
public class DynamicArray {
private Object[] data;
private int size;
public void DynamicArray(){
data = new Object[1];
size = 0;
}
public int size(){return size;}
public Object get(int index){return data[index];};
private void resizeIfFull()
{
if (size < data.length){
return;
} else {
Object[] bigger = new Object[2 * data.length];
for (int i = 0; i < data.length; i++){
bigger[i] = data[i];
data = bigger;
}
}
}
public void add(Object obj){
resizeIfFull();
data[size] = obj;
size++;
}
public void add(int index, Object obj){
resizeIfFull();
for(int i = size - 1; i >= index; i--){
data[i+1] = data[i];
}
data[index] = obj;
size++;
}
public void remove(int index){
for(int i = index; i < size; i++){
data[i] = data[i+1];
}
size--;
}
}
Here is my testing class.
public class AlgorTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
DynamicArray dynam = new DynamicArray();
System.out.println(dynam.size());
dynam.add("first");
}
}
Here is my output from the testing class.
0
Exception in thread "main" java.lang.NullPointerException
at DynamicArray.resizeIfFull(DynamicArray.java:20)
at DynamicArray.add(DynamicArray.java:38)
at AlgorTest.main(AlgorTest.java:8)
Confusingly, this isn't a constructor:
public void DynamicArray(){
data = new Object[1];
size = 0;
}
It's a function called DynamicArray (very confusing, I know).
Without the class having a constructor, data remains null and leads to an NPE when you try to access the array.
Drop the void keyword to turn the function into a constructor (which would then initialize data etc):
public DynamicArray(){
data = new Object[1];
size = 0;
}
constructor doesn't have return value , remove return type from constructor (void)
public DynamicArray(){
data = new Object[1];
size = 0;
}
in your case when you initialize object from DynamicArray class then default constructor will execute which does nothing
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'm trying to make a hash table with java. I share a long code only what I need. I use the for loop to fill the table with -1.But I am getting the error.
---Exception in thread "main" java.lang.NullPointerException
at datahashtable04.DataHashTable04.main(DataHashTable04.java:68)
Java Result: 1---
class Data {
int index, value;
public Data(int index, int value) {
this.index = index;
this.value = value;
}
}
public static void main(String[] args) {
Data a []= new Data[27];
for (int i = 0; i <a.length; i++) {
a[i].index=-1;
a[i].value=-1;
}
}
Data a []= new Data[27];
Everything in this array is null until you initialize each element. You need to call the constructor in your loop:
for (int i = 0; i <a.length; i++) {
a[i] = new Data(-1, -1);
}
I am trying to write a class that will remove a column from a 2d array, but I keep running into errors that I don't understand. I think I am misunderstanding something very basic here, any help would be appreciated
public class CollumnSwitch
{
int[][] matrix;
int temp;
public static void coldel(int[][] args,int col)
{
for(int i =0;i<args.length;i++)
{
int[][] nargs = new int[args.length][args[i].length-1];
for(int j =0;j<args[i].length;j++)
{
if(j!=col)
{
int temp = args[i][j];
}
nargs[i][j]= temp;
}
}
}
public void printArgs()
{
for(int i =0;i<nargs.length;i++)
{
for(int j =0;j<nargs[i].length;j++)
{
System.out.print(nargs[i][j]);
}
System.out.println();
}
}
}
You cannot access a non-static variable from a static context, you need to change int temp; to static int temp; or you can remove static from your method declaration.
You declare your nargs array in the coldel method, so it is not accessible from other methods. Meaning this doesn't work:
for(int i =0;i<nargs.length;i++) //You try to access nargs which is not possible.
{
for(int j =0;j<nargs[i].length;j++)
...
Maybe you want it to be the matrix array you have in your class? Like this:
in coldel:
matrix= new int[args.length][args[i].length-1];
and in printArgs
for(int i =0;i<matrix.length;i++)
{
for(int j =0;j<matrix[i].length;j++)
...
This require matrix to be static also (again, you can also remove static from coldel)
you can try like this:
static int[][] nargs;
public static void deleteColumn(int[][] args,int col)
{
if(args != null && args.length > 0 && args[0].length > col)
{
nargs = new int[args.length][args[0].length-1];
for(int i =0;i<args.length;i++)
{
int newColIdx = 0;
for(int j =0;j<args[i].length;j++)
{
if(j!=col)
{
nargs[i][newColIdx] = args[i][j];
newColIdx++;
}
}
}
}
}
public static void printArgs()
{
if(nargs != null)
{
for(int i =0;i<nargs.length;i++)
{
for(int j =0;j<nargs[i].length;j++)
{
System.out.print(nargs[i][j] + " ");
}
System.out.println();
}
}
}
Your difficulties are arising due to using variables outside of their scope. In java, variables basically only exist within the most immediate pair of braces from which they were declared. So, for example:
public class Foo {
int classVar; // classVar is visible by all code within this class
public void bar() {
classVar = classVar + 1; // you can read and modify (almost) all variables within your scope
int methodVar = 0; // methodVar is visible to all code within this method
if(methodVar == classVar) {
int ifVar = methodVar * classVar; // ifVar is visible to code within this if statement - but not inside any else or else if blocks
for(int i = 0; i < 100; i++) {
int iterationVar = 0; // iterationVar is created and set to 0 100 times during this loop.
// i is only initialized once, but is not visible outside the for loop
}
// at this point, methodVar and classVar are within scope,
// but ifVar, i, and iterationVar are not
}
public void shoo() {
classVar++; // shoo can see classVar, but no variables that were declared in foo - methodVar, ifVar, iterationVar
}
}
The problem you are having is because you are declaring a new 2-d array for each iteration of the for loop and writing one column to it, before throwing that away, creating a new array, and repeating the process.