Initialize an ArrayList. When necessary? - java

I had the impression growing out of the applications by my work that when I define an ArrayList attribute in a class in Java 7, it is not necessary to initialize it (with new as a new Object) when I want to access it in a method for the first time. Nevertheless I receive always a nullPointerException error (on my personal home Computer), despite of having installed JDK1.7.0. Is there a newer version which I should install to overcome this annoying occurrence?
public class AdditionNode {
private VectorOperationCodeGen nodeCodeGen;
protected ArrayList<VectorInTree> connectedVectors;
...
...
...
public void inputVector(VectorInTree inputVector){
if(inputFlag==2||inputFlag==0){
if(this.connectedVectors.isEmpty()){
The last line evokes a nullPointerException. Should be so?

I define an ArrayList attribute in a class in Java 7, it is not
necessary to initialize it (with new as a new Object) when I want to
access it in a method for the first time.
This is false. What gave you that impression ?

I had the impression growing out of the applications by my work that when I define an ArrayList attribute in a class in Java 7, it is not necessary to initialize it
If you are to use the ArrayList, then you better initialize it.
By simply doing
ArrayList<SomeType> list;
you have just declared a reference to an ArrayList, and not actually created an ArrayList.
If you want to be "lazy" with the initialization, then whenever you need to access the list referred to by list, you'll have to do
ArrayList<SomeType> list;
// ...
if (list == null)
list = new ArrayList<SomeType>();
list.add(someElement);

Since the very beginning of Java the default value for references (which you call "ArrayList attribute") has been null. This will also not change in the future. Therefore someone must initialize them before using the list.
So this one simple declares a list reference and initializes it with null:
class MyClass {
private ArrayList<String> list;
}
To declare and initialize it with an actual instance just do:
class MyClass {
private ArrayList<String> list = new ArrayList<String>();
}
At Work you might use some frameworks, which can do nearly magical things for you. Better check out what framework are used and learn how they do their magic and, most importantly, when they do and when they don't do this magic.

If I can say my opinion, yours it's a very strange impression. How can you use an object(such as an array list) without initialization and declaring a reference? Only referencing an object and initializing it, you can use that object.
If it would be possible what you're saying, it isn't necessary to have a reference of something on the memory and you have solved the problems of memory allocation. :-)
You should be clearer in your question.
EDIT
Now you have updated the question.
Yes, it should be like you are saying. You are receiving NullPointerException from the compiler on the line if(this.connectedVectors.isEmpty()){, because you haven't initialized before with new operator the connectedVectors object.
If you are at the beginning with java programming, this is considered a typical error, and for now you are forgived :-)
Even if the forgotten initialization of an object is considered a typical error of beginner programmer, this is an important and serious error, that you must not repeat.

As far as i know, you can't avoid to initialize an object before using it.
Even if this is true, you should initialize it anyway because if your user does not use the java version you're referring, he's gonna meet a lot of errors.
Still, I don't think that you can do what you're saying.

This 'annoying occurrence' is part of the design of the Java Programming Language, and hasn't changed since the beginning. Your expectations/impressions are mistaken.

Related

Java List/Array List clarification

If someone can explain the difference between these two type of Array Initializations that would be great:
There is a static method getList() in class ListReturn, which returns an ArrayList<Some_Custom_Object> upon calling.
In the invoking class, I can call the function in two ways as follows:
List<Some_Custom_Object> listFromCall = new ArrayList<Some_Custom_Object>();
listFromCall=ListReturn.getList();//works completely fine
List<Some_Custom_Object> listFromCall = ListReturn.getList();//Works completely fine
My question here is, in the second scenario, don't we have to initialize or instantiate the listFromCall object?, can we directly assign return values from method to un-initialized List/ArrayList object?
Can someone please explain what is going on beneath the hood here?.
Thanks
You only have to initialize a variable if you read from it before you write to it.
If you write to an uninitialized variable, the computer doesn't care because you're initializing it with the return value from ListReturn.getList().
In fact, you shouldn't needlessly initialize object variables to anything but null if they're going to be overwritten before use. Otherwise, you create and garbage collect an extra object for no reason.
Let's discuss both way one by one,
First Way :
List<Some_Custom_Object> listFromCall = new ArrayList<Some_Custom_Object>();
means, something likewise,
listFromCall=ListReturn.getList();//works completely fine
it will reflect on listFromCall's value assignment, see below image for
deeper understanding,
Here, completion of both statement, total either 2-object created(1
will eligible for garbage collection after second created and assign)
or 1-object created (which will become eligible for garbage collection
and assign null to reference variable)
Your Second Way :
Now if you do something likewise,
2. List<Some_Custom_Object> listFromCall = ListReturn.getList();//Works completely fine
Then it will appear something likewise,
So, here either 1-object(of ArrayList) will created on heap or not.

Java - Remove "Variable", keep assignments with side effects

I am starting to develop for Android (And I am starting to think, does it worth it!). Eclipse keeps giving me a lot of strange warnings and errors too! Here is one that kept me frustrated for the last two hours with no luck on Google:
private String alertTitle= null;
There is an ! mark beside it saying Remove "alertTitle", keep assignments with side effects. What is this?! I am defining a variable exactly as Java states. I am using the variable later:
public ASAlertDialog setTitle(String title) {
this.alertTitle = title;
return this;
}
Another one that's a little bit similar is defining enum"
public enum MyStyles {
aStyle;
}
public MyStyles myStyle = aStyle;
This made Eclipse angry!
You may be using the variable name by assigning a value to it, but you are not using the value stored in the variable. To do that, you must use the variable name to retrieve the stored value, and do something with this retrieved value somewhere in your code.
Eclipse tags the variable as unused when the value is never retrieved (or more generally, it's never possible to retrieve it*). It means you're merely assigning values to it, but never making use of them anywhere. This makes the variable an unnecessary memory hog, hence the warning.
* public and protected variables won't get the warning because they can be retrieved in other classes even if they aren't retrieved within the class they are declared in, and even if they are currently never retrieved in any class (it may happen in the future due to library use).
For the enum, it should be:
public MyStyles myStyle = MyStyles.aStyle;
This is because an enum is something like a class, with the constants acting similar to static variables in the class. (This is just an analogy, not exact an language definition.) You would retrieve enum constants the same way you retrieve variables from an external class that are defined as static.
Your variable is not used, so eclipse informs you about that and therefore you get message Remove "alertTitle", keep assignments with side effects
For enums, you need to declare it as
public enum MODE
{
NO_ASYNC_TASK,
NO_DOWNLOADED_DRAWABLE,
CORRECT
};
Check my this answer for more information
And the warning is because you might not be using alertTitle variable after declaring it.
To your first question:
It just means that your variable isn't being used, so you can safely remove it. The warning will disappear once you start using the variable in your code. Side-effects are explained here:
http://www.cs.umd.edu/~clin/MoreJava/Intro/assign.html
Check under "Is Assignment an Expression?"
To your second question:
There is no ';' in defining an enum. Check this:
http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
Try
public enum MyStyles {
aStyle;
}
public MyStyles myStyle = aStyle;
Regarding to your String, maybe Eclipse informs you that your variable is never used.
By the way,
private String alertTitle;
is null by default, so why do you set "= null"?

very specific java constructors and Object class problem

I have an array at actionTable.get(state).
When I go to add an onject to the array, namely the Reduce, the properties of the reduce don't seem to go with it.
The array is of type Action[] where Action is the superclass of Reduce, could this be the reason?
Adding the reduce to the array:
actionTable.get(state)[t] = new Reduce(st.items.get(item).prod);
Checking to see if the field head is defined before adding it:
System.out.println(Prod.prods.get(st.items.get(item).prod).head);
Checking to see if the newly added reduce has the correct head field:
System.out.println(actionTable.get(state)[t].prod.head);
A NullPointerException occurs on the last print statement. The .prod part is defined but the .prod.head is null, even though the original prod object had a defined head.
This is the constructor for Reduce:
Reduce(int pr) {
p = pr;
length = Prod.prods.get(pr).length;
prod = Prod.prods.get(pr);
}
All of the RHS of the assignments in the constructor are defined. So, I don't understand why the head field, within the prod object that the new Reduce has access to is not defined when you access it through the actionTable.
Trust inheritance and all. Most likely with arrays is, that different array instances are involved (if you enlarge/copy array references). Some more System.out.println's will help there.
The first thing you always should do is this: got to your break points view in your IDE, check "stop on Exception thrown" and perhaps give the name NullPointerException.
Then run your code in the debugger and it will stop exactly at the point where the NullPointerException is thrown.

Why does javac complain about not initialized variable?

For this Java code:
String var;
clazz.doSomething(var);
Why does the compiler report this error:
Variable 'var' might not have been initialized
I thought all variables or references were initialized to null. Why do you need to do:
String var = null;
??
Instance and class variables are initialized to null (or 0), but local variables are not.
See ยง4.12.5 of the JLS for a very detailed explanation which says basically the same thing:
Every variable in a program must have a value before its value is used:
Each class variable, instance variable, or array component is initialized with a default value when it is created:
[snipped out list of all default values]
Each method parameter is initialized to the corresponding argument value provided by the invoker of the method.
Each constructor parameter is initialized to the corresponding argument value provided by a class instance creation expression or explicit constructor invocation.
An exception-handler parameter is initialized to the thrown object representing the exception.
A local variable must be explicitly given a value before it is used, by either initialization or assignment, in a way that can be verified by the compiler using the rules for definite assignment.
It's because Java is being very helpful (as much as possible).
It will use this same logic to catch some very interesting edge-cases that you might have missed. For instance:
int x;
if(cond2)
x=2;
else if(cond3)
x=3;
System.out.println("X was:"+x);
This will fail because there was an else case that wasn't specified. The fact is, an else case here should absolutely be specified, even if it's just an error (The same is true of a default: condition in a switch statement).
What you should take away from this, interestingly enough, is don't ever initialize your local variables until you figure out that you actually have to do so. If you are in the habit of always saying "int x=0;" you will prevent this fantastic "bad logic" detector from functioning. This error has saved me time more than once.
Ditto on Bill K. I add:
The Java compiler can protect you from hurting yourself by failing to set a variable before using it within a function. Thus it explicitly does NOT set a default value, as Bill K describes.
But when it comes to class variables, it would be very difficult for the compiler to do this for you. A class variable could be set by any function in the class. It would be very difficult for the compiler to determine all possible orders in which functions might be called. At the very least it would have to analyze all the classes in the system that call any function in this class. It might well have to examine the contents of any data files or database and somehow predict what inputs users will make. At best the task would be extremely complex, at worst impossible. So for class variables, it makes sense to provide a reliable default. That default is, basically, to fill the field with bits of zero, so you get null for references, zero for integers, false for booleans, etc.
As Bill says, you should definitely NOT get in the habit of automatically initializing variables when you declare them. Only initialize variables at declaration time if this really make sense in the context of your program. Like, if 99% of the time you want x to be 42, but inside some IF condition you might discover that this is a special case and x should be 666, then fine, start out with "int x=42;" and inside the IF override this. But in the more normal case, where you figure out the value based on whatever conditions, don't initialize to an arbitrary number. Just fill it with the calculated value. Then if you make a logic error and fail to set a value under some combination of conditions, the compiler can tell you that you screwed up rather than the user.
PS I've seen a lot of lame programs that say things like:
HashMap myMap=new HashMap();
myMap=getBunchOfData();
Why create an object to initialize the variable when you know you are promptly going to throw this object away a millisecond later? That's just a waste of time.
Edit
To take a trivial example, suppose you wrote this:
int foo;
if (bar<0)
foo=1;
else if (bar>0)
foo=2;
processSomething(foo);
This will throw an error at compile time, because the compiler will notice that when bar==0, you never set foo, but then you try to use it.
But if you initialize foo to a dummy value, like
int foo=0;
if (bar<0)
foo=1;
else if (bar>0)
foo=2;
processSomething(foo);
Then the compiler will see that no matter what the value of bar, foo gets set to something, so it will not produce an error. If what you really want is for foo to be 0 when bar is 0, then this is fine. But if what really happened is that you meant one of the tests to be <= or >= or you meant to include a final else for when bar==0, then you've tricked the compiler into failing to detect your error. And by the way, that's way I think such a construct is poor coding style: Not only can the compiler not be sure what you intended, but neither can a future maintenance programmer.
I like Bill K's point about letting the compiler work for you- I had fallen into initializing every automatic variable because it 'seemed like the Java thing to do'. I'd failed to understand that class variables (ie persistent things that constructors worry about) and automatic variables (some counter, etc) are different, even though EVERYTHING is a class in Java.
So I went back and removed the initialization I'd be using, for example
List <Thing> somethings = new List<Thing>();
somethings.add(somethingElse); // <--- this is completely unnecessary
Nice. I'd been getting a compiler warning for
List<Thing> somethings = new List();
and I'd thought the problem was lack of initialization. WRONG. The problem was I hadn't understood the rules and I needed the <Thing> identified in the "new", not any actual items of type <Thing> created.
(Next I need to learn how to put literal less-than and greater-than signs into HTML!)
I don't know the logic behind it, but local variables are not initialized to null. I guess to make your life easy. They could have done it with class variables if it were possible. It doesn't mean you have to have it initialized in the beginning. This is fine :
MyClass cls;
if (condition) {
cls = something;
else
cls = something_else;
Sure, if you've really got two lines on top of each other as you show- declare it, fill it, no need for a default constructor. But, for example, if you want to declare something once and use it several or many times, the default constructor or null declaration is relevant. Or is the pointer to an object so lightweight that its better to allocate it over and over inside a loop, because the allocation of the pointer is so much less than the instantiation of the object? (Presumably there's a valid reason for a new object at each step of the loop).
Bill IV

In Java, Prevent a field from being changed after being returned by instance method

In a software development class at my university, the teacher kept mentioning that on a quiz we needed to make sure that a field returned by a getter needed to be "protected." I guess she meant that nothing outside the class should be able to change it. She didn't give much more of an explanation than that.
For instance:
class Foo {
string[] bar = <some array contents>;
public string[] getBar() {
return bar;
}
}
Any code calling getBar would be able to modify the elements in that array. How do you prevent that from happening? I'm assuming that the object itself should be able to modify the array, just not anything outside the object.
This isn't homework help since the quiz is a couple of weeks old. I simply want to understand Java better since my teacher didn't explain very well.
Update: The teacher wouldn't merely allow us to use protected as the access modifier on the field.
You either use a collection and wrap it in Collections.unmodifiable*() or you defensively copy your array, collection or object if its mutable (which arrays always are).
For example:
class Foo {
private String[] bar = <some array contents>;
public String[] getBar() {
return bar == null ? bar : Arrays.copyOf(bar);
}
}
What you have to watch out for is that this is a shallow copy (so is clone). Not sure what your teacher's problem with clone was.
Just to add to one of the previous answers, you want to make sure that with a collection you aren't using the clone() method to achieve what you are trying to achieve here. This creates a shallow copy of the collection only, all object references contained in the collection copy still point to the same objects as in the original, e.g. the objects in the collection copy can still be modified, even though the original collection cannot. Be sure you are making a deep copy of a returned collection if this is what you are trying to do.
I suspect what she meant was that the visibility of the field itself should be protected (or private) so that access only occurs through the getter. In the case of a collection, you may also want to do as #cletus suggests and return a copy of the collection if you don't want it to be modified outside the class. EDIT Based on your edit, she probably meant both.
class Foo {
protected string[] bar = <some array contents>;
public string[] getBar() {
return bar;
}
}
To protect that field from being changed you need to first make it private and don't provide any setter of any other method which changes that field. This way nobody can change the reference of that variable.
If the field is a mutable Object then again its value can be changed. For that you would need to do deep cloning before returning that object.
I'd add to cletus' first suggestion - the easiest way of making bar immutable would be to use a List instead of an array and return it wrapped in an unmodifiableList. That way it's immediately clear to the client of the class that the contents of bar can't be altered - an UnsupportedOperationException is thrown. Messing about with deep cloning will probably be pretty inefficient, depending on the complexity of your objects, and still returns a bunch of mutable objects - it's just that any changes made to those will be ignored by Foo.
class Foo {
private List<String> bar = new ArrayList<String>();
public Collection<String> getBar() {
return Collection.unmodifiableList(bar);
}
}
(Also might be worth noting that with generics in Java 5+, a list behaves much more like an array than it used to).
Please tell the professor that all non-final fields must be private to preserve encapsulation.
Protected allows your subclass or other classes in the same package to modify the field without your class knowing it.
The only class that should touch non-final fields directly is the class that defines them.
(Think about what would happen if you wanted to later fire an event when the field changes... you can only do that if all access is through the setter...)

Categories

Resources