Why do primitive array fields print out null pointer exceptions? - java

public class Whatever {
static double d;
static char c;
static String[] s;
static char[] b;
static double[] dd;
static Whatever w;
static Whatever[] ww;
public static void main(String[] args) {
System.out.println(Whatever.d); //prints out 0.0
System.out.println("hi"+Whatever.c+"hi"); //prints out hi hi
System.out.println(s); //prints out null
System.out.println(b); //null pointer exception!
System.out.println(Whatever.dd);
System.out.println(Whatever.w);
System.out.println(Whatever.ww);
}
}
Why do I get a null pointer exception?
Please explain in terms of memory if you can, however I have a basic understanding of memory so don't get too in depth either.

Okay, now that you've posted your full code its easier to help! This is normally what happens when you invoke PrintStream.println with a primitive array:
String s = String.valueOf(x);
Which eventually does this:
return (obj == null) ? "null" : obj.toString();
As you can see, the possibility of the supplied object being null is explicitly handled. However, there is a specific overload on the PrintStream class, just for char arrays. Here is a rough trace of the logic:
write(cbuf, 0, cbuf.length);
Where cbuf is the given char array. As you can see, it tries to reference the character arrays length, which will blow up with an NPE if the array is not initialized. It's an odd and unfortunate inconsistency in the implementation.
So now you understand why the NPE is occurring - to fix it simply initialize the char array before trying to print it out.

There's a few problems here:
1. You're not allocating any space for `int x`
2. If you want to print the contents of `x`, it should be `x.toString()`
3. What did you expect the output to be from your sample code?
I'm guessing #3 isn't what you're actually working with, I would suggest you show your real code to get a real answer :)
Hopefully this can clear it up a bit for you.
$ cat Whatever.java
public class Whatever {
static final int MAX = 5;
int[] x = new int[MAX]; // allocate array to sizeof '5'
public Whatever() {
// do stuff
}
public void addStuff() {
for(int i=0; i<MAX; i++)
x[i] = i + 2;
}
public void printX() {
for(int i=0; i<MAX; i++)
System.out.println(i + ": " + x[i]);
}
public static void main(String[] args){
Whatever w = new Whatever(); // new instance of 'Whatever'
w.addStuff(); // add some ints to the array
w.printX(); // print out the array
// print the Array 'x'
System.out.println("Array: " + w.x);
}
}
$ java Whatever
0: 2
1: 3
2: 4
3: 5
4: 6
Array: [I#870114c

The problem is basically rooted in how PrintStream.println(...) is implemented. Except for char[], a primitive array is treated as a java.lang.Object. So the println overload used is println(Object). Underneath, printing an object involves calling the object's toString(). Hence the NPE.
If you want to be defensive of nulls, you should consider using String.valueOf(Object).

Related

Scale an arrays dimensions in Java

I am wanting to make a method that can take in an array of n dimensions and then do some sorting with that info. The sorting part is out of the scope of this question though since the part I am stuck on is making a method accept an array of n dimensions. Normally you include something like int[] nums as a parameter. However, this does not allow for a scalable dimensional input. I did some research and the following code accurately calculates the dimensions of an array but I am not sure where to go from there since I cant figure out how to initialize an array of n dimensions from just an Object.
public static int dimensionOf(Object arr) {
int dimensionCount = 0;
Class<?> c = arr.getClass(); // getting the runtime class of an object
while (c.isArray()) { // check whether the object is an array
c = c.getComponentType(); // returns the class denoting the component type of the array
dimensionCount++;
}
return dimensionCount;
}
Here is something else to explain my issue lets say someone passes in a 2 dimensional array as the object. If that happened my dimensions variable would be equal to 2 since its using the above code to determine the dimension of the array. The thing I am stuck on is figuring out how to then produce a useable variable. Here you can see I tried to cast the object (which I know is an instance of array) to a 1d array which would through an error since the incoming object is a 2d array.
public static int sortNDimensionalArray(Object obj) {
int dimensions = dimensionOf(obj);
//This means we did not get an array passed in
if(dimensions == 0) return -1;
int[] array = (int[]) obj;
return 1;
}
I tried it out and got this and it works for me:
public static int dimensionOf(Object... args) {
int dim = 0;
Class<?> c = args.getClass();
while(c.isArray()) {
c = c.getComponentType();
dim++;
}
return dim;
}

How is the first line of output generated? [duplicate]

This question already has answers here:
Overloaded method selection based on the parameter's real type
(7 answers)
Closed 6 years ago.
The following code showed up in a past paper with multiple mistakes (which i have spotted and fixed easily) but what i struggle to understand is the output.
The classes:
import java.util.*;
class Count {
int i, s, o, l, c;
public Count(Object[] objects){
for(int j=0; j<objects.length; j++){
count(objects[j]);
}
}
public void count(Collection x){c++;}
public void count(List x){l++;}
public void count(Double x){i++;}
public void count(Object x){o++;}
public void count(String x){s++;}
public String toString(){
return c + ", " + l + ", " + i + ", " + o + ", " + s;
}
}
import java.util.LinkedList;
public class Test {
static Object[] objects = {new Double(10), new String("Q1"),
new Object(), new LinkedList()};
public static void main(String args[]){
System.out.println(new Count(objects));
for(Object o : objects)
System.out.println(o);
}
}
Generated output:
0, 0, 0, 4, 0
10.0
Q1
java.lang.Object#6d06d69c
[]
I'd appreciate if someone could explain the output with reference to the code.
Side note: the first line of output is what puzzles me. The other bit i understand.
Last note: This is a unique question regarding the output. It is not a duplicate of any question (to the best of my knowledge - the link to the 'possible duplicate' is regarding method overloading not "how is this output produced?" and the outcomes in both questions are unique to each other) so a precise answer would be helpful. Thanks.
for(int j=0; j<objects.length; j++){
count(objects[j]);
}
corresponds to
public void count(Object x){o++;} only
because the argument you're passing when you call count(objects[j]) is an object. You're calling a count function which has an object as parameter, and that's what Java is doing for you.
The number of objects in objects[] is 4. Hence count(Object x) gets called 4 times.
As regards the other integers, they are initialized by default to 0, and hence you see 0.
That's why you see 0 for all variables except o.
public Count(Object[] objects){
for(int j=0; j<objects.length; j++){
count(objects[j]);
}
In these lines you're creating an array of elements in which each element is of type Object itself (it's the class from which every other class inherits). So output of counting objects of type Object in array shouldn't be a surprise.
(Counting is held by overloaded methods. When you call counting function the one that is chosen must have the most suitable type. Hence, counting with Object type as a parameter is picked.)
0, 0, 0, 4, 0
Next, you're creating new array of Objects, initializing each element of the array with different type.
static Object[] objects = {new Double(10), new String("Q1"),
new Object(), new LinkedList()};
It's possible because of upcasting. As I mentioned before, every element inherits from Object class, so every object in your program is in fact Object. Using mechanism of polymorphism you're program can now "deduce" the real type of elements in your array. Namely, you can see it here
for(Object o : objects)
System.out.println(o);
where Java is printing information obtained dynamically. Hence, double is printed as double, string as string, object itself doesn't have more sensible toString() method than printing its inner "name"(by the way this is the field each object of type Object has) and of course empty link list is no more than [].
One of your problems lies here:
public void count(Collection x){c++;} // never called, init to 0
public void count(List x){l++;} // never called, init to 0
public void count(Double x){i++;} // never called, init to 0
public void count(Object x){o++;} // called 4 times, result is 4
public void count(String x){s++;} // never called, init to 0
You never initialize any of the variables (c, k, i, o, s) so I believe the int type is auto initialized to 0. Then the next time it is called it will increment. So end result is:
0, 0, 0, 4, 0 //
Now the rest:
10.0 // 10.0 because that was value specified when Double was created
Q1 // Q1 because that was the String value when it was created.
java.lang.Object#6d06d69c // memory address of where Object is
[] // initialized to empty list []
The first line outputs the number of Collections, Lists, Doubles, Objects, Strings passed to the constructor of the Count instance in the main method of the Test class, since all of the Count classes only accept one parameter and the count variables are not static four of these will always be zero.
The next four lines print the four objects in the static objects array. This is effectively just printing the results of each objects toSrting() method.

Printing all elements of an array in one println statement in Java [duplicate]

This question already has answers here:
What's the simplest way to print a Java array?
(37 answers)
Closed 2 years ago.
public class Test {
public static void main(String[] args) {
int[] a= new int[]{1,2,3};
System.out.println(a);
}
}
I expected to take a compile or run-time error.I took an output.It's "[I#1ba4806".What's the reason of it in Java?
That's the default implementation of toString() in Object you're seeing. You can use Arrays.toString for a readable result (make sure to import java.util.Arrays):
System.out.println(Arrays.toString(a));
It trys to print an Array.
If you want to get a readable result use
System.out.println(Arrays.toString(a));
expected to take a compile or run-time error.I took an output.It's
"[I#1ba4806".What's the reason of it in Java?
Because currently the toString method from Object class is getting invoked, it looks like this
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
Thats why you see [I#1ba4806
You can print array content using Arrays.toString which is overloaded method in Arrays class to print the array.
System.out.println(Arrays.toString(a));
For int[] parameters the method implementation looks like
public static String toString(int[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
I took an output.It's "[I#1ba4806".What's the reason of it in Java?
out static field in System class is instance of PrintStream and there is no println(int[]) method in PrintStream class which would iterate for you over all elements in passed array and print them, but there is println(Object o) which tries to convert passed object o into as String which will be then printed.
To do that this method uses String.valueOf(o) method which in case of o being null will return "null" String, or in case where o is not null (like in your example) it will return result of toString() method invoked from passed object. So System.out.println(a); prints result of a.toString().
Now why does array have would have toString() method? Well it was inherited from Object class (because all arrays extend Object). Also arrays do not override this method and they leave it in a way it was implemented in Object class, so its code looks like
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
which as you see returns TypeName#hexadecimalHash. One dimensional array of integers is represented as [I where number of [ determines number of dimensions, and I represents int type.
If you would like to print content of array, you would either have to iterate over all elements and print them
for (int i = 0; int < array.lenght; i++){
System.out.println(array[i]);
}
or
for (int element : array){
System.out.println(element);
}
OR you can use Arrays.toString(int[]) method, which will do this for you and will generate string in form [1, 2, 3, ....] so all you would need to do is print it like
System.out.println(Arrays.toString(a));

Immutability of string objects in java

I'm noob in programming, now learning Java.
I have read that Strings are immutable in Java. But, I have a question regarding it.
public class Immutable {
public static void main (String[ ] args)
{
new Immutable().run();
} // method main
public void run()
{
String s = "yEs";
String p = "Do";
p=p.toUpperCase();
s=s.toLowerCase();
//Here above I'm able to change the content of the string object.
//Why is it said Immutable??
p = new String("DoPe");
System.out.println(p);
// Here I'm taking it as I'm creating new object and I'm assigning it to 'p'
//rather than changing the previously assigned object. so it's immutable
//Is my understanding correct??
flip (s);
System.out.println(s);
//Why does assigning a new object using a method doesn't work
//while if I do it explicitly, it works(as I've done for 'p', see above)
} // method run
public void flip (String t)
{
System.out.println(t);
t = new String ("no");
System.out.println(t);
t = "nope";
System.out.println(t);
} // method flip
} // class Immutable
Please see questions in my comments.
Revision:
public class Immutable {
public static void main (String[] args)
{
new Immutable().run();
} // method main
public void run()
{
String s = "yEs";
String p = "Do";
int [] arr = new int[5];
for (int i = 0; i < 5; i++)
arr[i] = i;
System.out.println("Value in the calling function before the altering is done: "+Arrays.toString(arr));
alter(arr);
System.out.println("Value in the calling function after the altering is done: "+Arrays.toString(arr));
p = p.toUpperCase();
s = s.toLowerCase();
//Here above I'm able to change the content of the string object.
//Why is it said Immutable??
p = new String("DoPe");
System.out.println(p);
// Here I'm taking it as I'm creating new object and I'm assigning it to 'p'
//rather than changing the previously assigned object. so it's immutable
//Is my understanding correct??
System.out.println("Value of string in the calling function before the altering is done: "+s);
flip (s);
System.out.println("Value of string in the calling function after the altering is done: "+s);
//Why does assigning a new object using a method doesn't work
//while if I do it explicitly work(as I've done for 'p', see above)
} // method run
public void flip (String t)
{
System.out.println("Value of string in the called function, before altering: "+t);
t = new String ("no");
System.out.println("Value of string in the called function, after Altering: "+t);
t = "nope";
System.out.println(t);
} // method flip
public void alter(int[] a)
{
System.out.println("Value in the called function, before altering: "+Arrays.toString(a));
a[3] = 50;
System.out.println("Value in the called function, after Altering: "+Arrays.toString(a));
}
} // class Immutable
Modification works for arrays, but not for strings.
Is this the reason strings are called immutable??
Am I missing something?
Here above I'm able to change the content of the string object. Why is it said Immutable??
You don't change the contents of the String, you create a new String object and link it with the variable, the old object will be removed.
Here I'm taking it as I'm creating new object and I'm assigning it to 'p' rather than changing the previously assigned object. so it's immutable. Is my understanding correct??
Yes, and this is actually the same you did one question above, but the String object was created by one of its instance methods.
Why does assigning a new object using a method doesn't work while if I do it explicitly work(as I've done for 'p', see above)
This is because the immutability of String. Java is pass-by-value, but your method needs to be pass-by-pointer. Since you can't change the contents of the String (you only can create a new String object), you'll need to return the String.
You're not changing the content of the string object, you're changing which variable point to which object in memory.
Variables are just pointers to the objects in memory, not the actual objects.
You're not changing the content of the string objects. You're creating new objects and making s and p point to the new objects.
//Here above I'm able to change the content of the string object.
//Why is it said Immutable??
You did not change the content of the string, you simply created a new String and assigned its reference to your String variable. That also answers to your second comment.
//Why does assigning a new object using a method doesn't work
//while if I do it explicitly work(as I've done for 'p', see above)
Because Java methods are not pass-by-reference. See this question for further information.
I believe you are making confusion about things.
Overall, I do understand what you mean.
You believe that you "changed" p by p = new String("DoPe"); which is let's say correct but the same thing doesn't happen with s when you call flip (s);
Well, calling it won't "change" s because your function flip only takes a string and modifies it internally and that's it.
In order to "change" s using a function you have to do this modifications:
1 s= flip (s);
(s receives the returned value of the function)
2. Function flip should return a String and not a void
public String flip (String t) // String instead of void
{
System.out.println(t);
t = new String ("no");
System.out.println(t);
t = "nope";
System.out.println(t);
return t; //returns the String t
}

Modify an array passed as a method-parameter

Suppose I have an int-array and I want to modify it. I know that I cannot assign a new array to array passed as parameter:
public static void main(String[] args)
{
int[] temp_array = {1};
method(temp_array);
System.out.println(temp_array[0]); // prints 1
}
public static void method(int[] n)
{
n = new int[]{2};
}
while I can modify it:
public static void main(String[] args)
{
int[] temp_array = {1};
method(temp_array);
System.out.println(temp_array[0]); // prints 2
}
public static void method(int[] n)
{
n[0] = 2;
}
Then, I tried to assign an arbitrary array to the array passed as parameter using clone():
public static void main(String[] args)
{
int[] temp_array = {1};
method(temp_array);
System.out.println(temp_array[0]); // prints 1 ?!
}
public static void method(int[] n)
{
int[] temp = new int[]{2};
n = temp.clone();
}
Now, I wonder why it prints 1 in last example while I'm just copying the array with clone() which it's just copying the value not the reference. Could you please explain that for me?
EDIT: Is there a way to copy an array to object without changing the reference? I mean to make last example printing 2.
Your examples 1 and 3 are virtually the same in context of the question - you are trying to assign a new value to n (which is a reference to an array passed by value).
The fact that you cloned temp array doesn't matter - all it did was create a copy of temp and then assign it to n.
In order to copy values into array passed into your method method you might want to look at:System.arraycopy
It all, of course, depends on the sizes of your n array and the one you create inside method method.
Assuming they both have the same length, for example, you would do it like that:
public static void main(String[] args)
{
int[] temp_array = {1};
method(temp_array);
System.out.println(temp_array[0]);
}
public static void method(int[] n)
{
int[] temp = new int[]{2};
System.arraycopy(temp, 0, n, 0, n.length);
// or System.arraycopy(temp, 0, n, 0, temp.length) -
// since we assumed that n and temp are of the same length
}
In your method
public static void method(int[] n)
n is another name for the array that way passed in. It points to the same place in memory as the original, which is an array of ints. If you change one of the values stored in that array, all names that point to it will see the change.
However, in the actual method
public static void method(int[] n) {
int[] temp = new int[]{2};
n = temp.clone();
}
You're creating a new array and then saying "the name 'n' now points at this, other array, not the one that was passed in". In effect, the name 'n' is no longer a name for the array that was passed in.
As you correctly note, you cannot assign to the array reference passed as a parameter. (Or more precisely, the assignment won't have any effect in the caller.)
This is about the best that you can do:
public static void method(int[] n) {
int[] temp = new int[]{2};
for (int i = 0; i < temp.length; i++) {
n[i] = temp[i];
}
// ... or the equivalent using System.arraycopy(...) or some such
}
Of course, this only works properly if the size of the input array is the same as the size of the array you are copying to it. (How you should deal with this will be application specific ...)
For the record Java passes the array reference by value. It doesn't pass the array contents by value. And clone won't help to solve this problem. (At least, not with the method signature as declared.)
In your method method, nothing that you assign to n will ever change the value of the object passed in and assigned to n. At the beginning of method, n points to an array. When you assign n to equal another array, you've simply re-pointed which array n points to, and haven't changed anything about temp_array from the main method.

Categories