Why If I instantiate a List as null it fails - java

Too many times I have to use a List of an Object instead of the object, If I use
MyObj a = null;
a.setParameter = 0;
It works.
But If I use
List<MyObj> a = null;
MyObj b = getObjectFromSomewhere();
a.add(b);
It fails with error : java.lang.NullPointerException?
And How I can see If my new List<MyObj> a is "null" or without any element inside?

A list is a container that you have to put elements into. The list has to exist prior to putting anything in it (so you can have an empty list, note).
So this:
List<MyObj> a = null;
declares a variable pointing to a null - not an actual container. Try:
List<MyObj> a = new ArrayList<>();
(note that lists come in different varieties, with different performance characteristics, and the above is just a commonly used variety chosen for illustration)
(to address your first point re a.setParameter, I guess that is a static method - defined for the class, not the instance of a class - and confusingly Java will let you reference that via an instance)

Eclipse allows you to initiate it to a null because Eclipse thinks that you will be pointing an object to this reference somewhere later in your code.
so its your responsibility to have it refer to an object before using any of the List methods.

doing this List<MyObj> a = null makes no initialization in memory so a point to nothing
what you should do is
List<MyObj> a = new ArrayList<>();
a.add(getObjectFromSomewhere());
How I can see If my new List a is "null" or without any element
inside?
if(a == null){...} // to check if array not initialized
if(a.size() == 0){...} // to check if array have no element
keep in mind calling a.size() when a is null will throw NullPointerException

Related

Which parameters are local in a binary tree recursion?

import java.util.*;
public static void main(String[] args) {
TreeNode root = new TreeNode(8);
root.left = new TreeNode(7);
root.right = new TreeNode(6);
root.left.left = new TreeNode(5);
root.right.right = new TreeNode(4);
List<Integer> list = postorderTraversal(root);
System.out.println(list);
}
public static List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
list = helper(root, list);
return list;
}
private static List<Integer> helper(TreeNode node, List<Integer> list){
if (node != null) {
helper(node.left, list);
helper(node.right, list);
list.add(node.val);
}
return list;
}
}
In this question, I don't understand why I don't have to do list = helper(node.left, list); Why is list global here and when I'm changing my root it's local and I have to do root.left = recurse(root.left) ?
This is because of how pointers work in java.
When you pass list in as a parameter to a function, you aren't passing in the object itself, you're passing in its memory address on your computer. This memory address is called a pointer and is useful because it lets you avoid expensively duplicating objects.
You don't normally notice this because java typically hides the fact that it's using pointers at all. For instance, when you do list.add(...), it works like you're using an ordinary object and calling add() on it because java automatically substitutes the object for the pointer.
So list is kind of like a global variable, because even though the pointer is copied every time you pass it into something, it still references the same section of memory. Changing that section of memory will affect what every other pointer to that spot sees, so you get changes that other functions can see.
The statement
List<Integer> list = new ArrayList<Integer>();
Does two things. First it allocates a new ArrayList object on the heap. Then it stores a reference to that heap object in the local variable list. When you invoke helper, you are passing only the reference, which can be thought of as a memory address referring to the actual object on the heap. This reference gets passed down to the recursive invocations of helper. Each invocation gets a local copy of list, but this is only a copy of the reference, not the heap object. All those instances of list refer to the same heap object, the one you initially allocated. This is why it "feels" like it's global, but it is most definitely not.
The same concept applies to the TreeNode references, in fact to all object references in Java.
This can be highly confusing for new Java programmers. Java is "Pass-by-value", meaning that parameters are copied when invoking a method, but when the variables are objects, the "value" is a reference and not the object itself, and only the reference is copied. The only values that are copied for parameter passing are primitive values (boolean, char, int, long, float, double).

Null pointer access: The variable b can only be null at this location

I get the above mentioned error in the last line of this following portion of my code.
String[][] b = null;
try {
br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
// use comma as separator
String[] country = line.split(cvsSplitBy);
String[] a=country[1].split(splits);
i = 0;
n = 0;
while(i<a.length) {
b[j][n]+=a[i];
}
}
} catch (...) {}
What is the reason for this error and how to solve this?
The only two uses of b are
b = null;
...
*b[j][n] ...
You need to set b to an actual array before you can try indexing it.
String[][] b is null. Look like you should not use Array here as you don't know the size up front. You can use an ArrayList with some custom object.
In the Java programming language, arrays are objects (§4.3.1),
are dynamically created, and may be assigned to variables of type
Object (§4.3.2) [...] A component of an array is accessed by an array access expression
(§15.13) that consists of an expression whose value is an array
reference followed by an indexing expression enclosed by [ and ], as
in A[i].
How do array access expression work? Like this.
Relevant bit:
Otherwise, if the value of the array reference expression is null,
then a NullPointerException is thrown.
Long story short: arrays are objects, and b is a reference to an (array) object - like basically everything in Java except primitive types.
A reference can point to something or be a null reference.
A null-reference is something entirely different from any other sort of object in the heap, including an empty array: you can't do anything with it, including trying to access its elements, except assigning a value to it (imagine it as a blank "phone" line in an address book: before calling you have to have a number to call!)
So, you have to first make your reference point to an actual array, with
b = new String[10][10].
Using this right after
String[][] b = null;
would be a good idea; or you can just String[][] b = new String[10][10]().
At this point, b points to a string array in the heap, and you can do things with it.
Note that you have to specify a size.
If you don't know it yet you might be better off with other containers, for example ArrayList, which grows dynamically.

ArrayList modifying value returned by "get" method [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
I have below two situations related to ArrayList get method, one with custom class and one with String class:
1. Below is the example of modifying Custom class ArrayList element:
ArrayList<MyClass> mTmpArray1 = new ArrayList<MyClass>();
MyClass myObj1 = new MyClass(10);
mTmpArray1.add(myObj1);
MyClass myObj2 = mTmpArray1.get(0);
myObj2.myInt = 20;
MyClass myObj3 = mTmpArray1.get(0);
Log.d(TAG, "Int Value:"+myObj3.myInt); // Prints "20"
2. And below is the example of modifying String ArrayList element:
ArrayList<String> mTmpArray2 = new ArrayList<String>();
mTmpArray2.add("Test_10");
String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";
String myStr2 = mTmpArray2.get(0);
Log.d(TAG, "Str Value:"+myStr2); // Prints "Test_10"
So in case of MyClass ArrayList, when I call get and modify the value, then I see change is reflecting when I do get again.
But same way when I modify String ArrayList, then changes are not reflecting.
What is the different in of the get method in both the scenarios?
Is it that in case of String, String class creating deep copy and returns new object, and in case of Custom class shallow copy is created?
In the first scenario applicable to "LinkedHashMap", "HashMap" and "List"?
Your are not doing the same thing in the two cases.
Here you update the state of an object, so the change affects the object stored in the list :
myObj2.myInt = 20;
Here you are assigning a new object to a local variable, so the list is not affected :
myStr1 = "Test_20";
If String was mutable, you could have modified the String by calling some method, and the change would have been reflected in the object stored in the list :
myStr1.setSomething(...);
On the other hand, if in the first case you would have changed the value of the local variable, the object stored in the list wouldn't have been affected :
myObj2 = new MyClass (...);
Strings are immutable. You're not inserting the new string into the array list.
When you do String myStr2 = mTmpArray2.get(0);, even tho you are pointing to a reference in the ArrayList, any attempt to change the value, will (because of String immutability) create a new String (myStr2) that will not reference the ArrayList anymore.
When you do myStr1 = "xxx", you're not actually changing the ArrayList reference, you're changing a new (copy) (now called myStr1) that was grabbed from the ArrayList and it has a local scope.
Read some more about Strings: Immutability of Strings in Java
Now in the first example, you are pointing to a mutable object (your custom class) so you're literally changing the direct value, through the reference. Welcome to Java. ;)
Unrelated: This code: MyClass myObj1 = new MyClass(10); is (arguably) considered bad. It's better to use a factory pattern that is a lot easier to read. In other words, public constructors with parameters are hard to read (for example, I have no idea what I am constructing when I read your code).
A (perhaps) better approach would be: MyClass myObj = MyClass.createInstanceWithCapacity(10); // i've invented the name because I don't know what your 10 is, but look at both, which one do you think is easier to understand upon first glance?
Disclaimer: The above unrelated comment is my personal opinion and not all developers will agree. ;)
Strings have very nice property called "Immutablity"
This means that String cannot be mutable (changed), when we create/
try to refer to old string, a new instance string is created. And any
changes we do are saved in new instance and it do not affect the old
string
For example,
String s = "Old String";
System.out.println("Old String : "+s); // output : Old String
String s2 = s;
s2 = s2.concat(" made New");
System.out.println("New String : "+s2); // output : Old String made New
System.out.println("Old String is not changed : "+s); // output : Old String
These is no difference between the two "get" calls. The difference is between the types that the ArrayList is holding, and what you're doing the references the "get" method returns.
In your first example, you do this:
MyClass myObj2 = mTmpArray1.get(0);
myObj2.myInt = 20;
Here, you're getting a reference to the MyClass instance in the ArrayList in position 0, and you are modifying a field within this instance.
In your second example, you do this:
String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";
Here, you're getting a reference to the String instance in the array list, and then you're giving myStr1 a reference to a different string which you create ("Test_20"). It's as if you did wrote myObj2 = new MyClass(20); in the 2nd line in the 1st example.
So, in short, in the 1st example, you access a field within the object by altering it from the reference you grabbed. In the 2nd example, you simply altered your reference to point at a different String.
I should also mention that in Java, Strings are immutable, meaning once they have been created, they cannot be changed.
String is an immutable class. A line like
myStr1 = "Test_20";
does not change the value of the String object myStr1 is pointing to. Instead a new String is created and myStr1 is modified to point to the new String. The original String is unchanged and can be retrieved from the ArrayList.
Your MyClass object is clearly mutable. Only one instance is created and its state is changed by the assignment
myObj2.myInt = 20;
Hence when this object is retrieved from the ArrayList, its new state is seen.
You simply do NOT change the list in your 2nd example.
In the first example, you are doing this:
Get the first object from the list and store it in the variable called 'myObj2'
Modify the object stored in variable 'myObj2' by setting the int value of this object
But your second example is completely different:
String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";
Let me translate that:
Get the first element from the list and store it in the variable called 'myStr1'.
Set the value of the variable 'myStr1' to "Test_20"
So, in case one you are modifying a variable of the object stored in the list. In case two you are retrieving the object stored in the list - and then re-use the variable you stored that retrieved object in and use it for something new - but that does not change the original list, of course.
To modify your list for a type like string, you would need to use set(x, "Test_20").

clear the data of type object

I using type object and I fill it with data inside loop and at the end I want to clear the data inside ,I don't see any option to clear it (with .+CTRL SPACE) and I don't want to create new instance for it because I want to create object type just once ,is there a workaround to clear it?
I want to do the following just once for specObject, i.e. create instance type list or object and than I have loop that I fill the data inside this object ,when i finish and want to create new instance in specObject I want to clear it before ,how should I do that?
List<Object> itemObject = null;
Object specObject = null;
// Check instance type whether is list or specific object instance
if (multiplicity.equals(MULTI_N)) {
itemObject = new ArrayList<Object>();
return itemObject;
} else if (multiplicity.equals(MULTI_1)) {
return specObject;
} else {
return specObject;
}
You can call the clear method on the List object. That will remove all elements without the need to create a new instance. The documentation is here.
Just to note on object references
when i finish and want to create new instance in specObject I want to clear it before ,how should I do that?
Let's say you have a list:
ArrayList<String> strings = new ArrayList<String>();
If you add some string objects to this list:
strings.add("Hello");
strings.add("There");
strings.add("StackOverflow");
Then you nullify the strings object.
strings = null;
You have effectively removed all of the elements inside the list? Why? Well when you declare ArrayList<String> strings;, you're not creating a new object. You're creating a new reference (pointer) to an object. To illustrate this:
String s = "Hello";
String s2 = s; // s2 points to the same object that s points to.
String s3 = "Another String"; // S3 points to a different object.
The one exception to this rule is if you declare:
String s = "Hello";
String s2 = "Hello"; // s2 will point to the same object as s.
When an object isn't pointed to by anything, it is removed by the Garbage Collector. So effectively, if you declare:
strings = null;
You're removing all of the String child objects that you added to.

Setting a property on an object resets the same property on similar objects in an ArrayList

In the code section below, I should have an ArrayList of Objs with different xValues. Instead, when I set the xValue of the Obj n on the fourth line, all Objs with the same name in the ArrayList get the xValue set to the same value.
Obj n = new Obj();
n = getObj(event.getX(), event.getY(), view.getHeight(), view.getWidth(), view);
n.setXValue(view.getWidth());
if (currentMode == AppMode.MODE.code && n != null) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
arraylist.add(n);
} // end if (event.getAction
}
What am I doing wrong? Is there a collection which will allow me to set properties of an object without messing up properties of other objects in the collection?
Java is a "pass-by-reference" language when it comes to Objects. When you put the same Object in two different collections, you're just passing a pointer to the same spot in memory to each collection, so any changes you make from one reference will affect the other reference.
If you don't desire this behavior, you have to use Object.clone() to make copies of the objects before putting them in new collections, or use some other similar copying technique.
I would guess that you wrote Obj and within Obj you have a static variable named something like XValue.
When you designate a variable as static you get one and only instance of that variable shared across all instances of that class, hence: this behavior.
Or, what torquestomp said (he's right)

Categories