When I declare an instance variable, such as:
BSTNode node;
I know that node is now null, since the instance variable is not initialized. But is some memory allocated to store the value of null, and is node now a reference to that location?
I tried using
System.out.println(node);
Hoping that I would see the address of the reference, but just saw "null" printed out. Why do I not see an address?
Instance variables are initialized to their default values, if the code doesn't explicitly initialize them. All reference variables are initialized to null, per JLS Section 4.12.5:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10):
...
For all reference types (§4.3), the default value is null.
When a null is passed to System.out.println, the string literal "null" is outputted. The Javadocs for println defer to the print method to cover what happens when a null is passed:
If the argument is null then the string "null" is printed.
There is no address because there is no object yet.
Yes, memory is allocated and a value assigned no matter the initialization.
There is no such thing as "uninitialized": there's explicitly initialized, or initialized with the default value.
Java has no pointers like C/C++. You will never See the memory pointer where you object is located. And if you would get it, it might even chance as garbage collection might move it.
If you print an object, it is made a string calling toString().
"Is node now a reference to that location?"
How is null represented in the memory?
That is implementation specific, and you won't be able to see the representation of null in a pure Java program. (But null is represented as a zero machine address / pointer in most if not all Java implementations.)
There is already a very detailed answer to this question in Stackoverflow: You should check it out!
Also watch this video by Tony Hoare, "Null References: The Billion Dollar Mistake".
Related
Why must local variables, including primitives, always be initialized in Java? Why is the same not applicable in the case of instance variables?
Basically, requiring a variable to be assigned a value before you read it is a Good Thing. It means you won't accidentally read something you didn't intend to. Yes, variables could have default values - but isn't it better for the compiler to be able to catch your bug instead, if it can prove that you're trying to read something which might not have been assigned yet? If you want to give a local variable a default value, you can always assign that explicitly.
Now that's fine for local variables - but for instance and static variables, the compiler has no way of knowing the order in which methods will be called. Will a property "setter" be called before the "getter"? It has no way of knowing, so it has no way of alerting you to the danger. That's why default values are used for instance/static variables - at least then you'll get a known value (0, false, null etc) instead of just "whatever happened to be in memory at the time." (It also removes the potential security issue of reading sensitive data which hadn't been explicitly wiped.)
There was a question about this very recently for C#... - read the answers there as well, as it's basically the same thing. You might also find Eric Lippert's recent blog post interesting; it's at least around the same area, even though it has a somewhat different thrust.
In Java, class and instance variables assume a default value (null, 0, false) if they are not initialized manually. However, local variables don't have a default value. Unless a local variable has been assigned a value, the compiler will refuse to compile the code that reads it. IMHO, this leads to the conclusion, that initializing a local variable with some default value (like null, which might lead to a NullPointerException later) when it is declared is actually a bad thing. Consider the following example:
Object o;
if (<some boolean condition>)
o = <some value>;
else
o = <some other value>;
System.out.println(o);
An initialization of o with null is completely unnecessary, since the Java compiler checks at compile time, that any code-path initializes o (with either null or some non-null value) before the variable is read. That means, that the compiler will refuse to compile the line System.out.println(o); if you would comment out any of the two initializations of the variable o in the code snippet above.
This holds for Java, and maybe for Java only. I don't know about language like C#. In good old C (and maybe C++) however, it is still recommended to always initialize variables when declaring them, AFAIK. Such "old-school" programming languages might be the reason, that the recommendation to always initialize variables pops up in books and discussions about modern languages like Java, where the compiler keeps track of whether a variable has been initialized or not.
Not totally true. Local variables only need to be initialized if being reference. A local variable can be left uninitialized if never referenced. For example:
int x; // Valid
int y;
println("y=" + y); // Not valid since y's value has never been assigned
Well, in case of local variable it's clear what it means 'before' since the program flow between declaration (in method) and reference is sequential. In case of fields declared outside of the method compiler never knows which code is going to be used when so it cannot generate an error as possibly some other method is going to initialize the field before it is used.
Local variables and primitives should be initialized before use because you would know what to expect from the values. Historically, when a new variable was created it would contain random values from the memory [and one could not predict the value]. Java also requires this because it prevents the presence of orphaned variables.
In practice all variables need to be initialized before using them.
I can't think of a time you'd want to use a variable before setting its value (unless you're comparing it against null).
It is necessary to initialize local variables (only when we use them) because they don't get any default value like instance variables.
And as basic rule, we should always initialize any variable before using it. Otherwise it may result in an error like nullPointer, etc
Now, why don't local variables get default value? The reason is that local variables reside on stack and is visible only in local method context, unlike instance variables which resides on heap and has scope throughout the program.
So when the stack will end local method's value will also get destroyed therefore:
1] They are supposed to be initialized explicitly (when we use them)
2] They should not be initialized implicitly (by null,0 or false) like instance variables
Going by the definition of local variable which state, a local variable is declared within a function or is passed as an argument in a function. If you do not initialized a local variable you will encounter exception handling problem because, the compiler will not be able to understand what value the variable holds
Why must local variables, including primitives, always be initialized in Java? Why is the same not applicable in the case of instance variables?
Basically, requiring a variable to be assigned a value before you read it is a Good Thing. It means you won't accidentally read something you didn't intend to. Yes, variables could have default values - but isn't it better for the compiler to be able to catch your bug instead, if it can prove that you're trying to read something which might not have been assigned yet? If you want to give a local variable a default value, you can always assign that explicitly.
Now that's fine for local variables - but for instance and static variables, the compiler has no way of knowing the order in which methods will be called. Will a property "setter" be called before the "getter"? It has no way of knowing, so it has no way of alerting you to the danger. That's why default values are used for instance/static variables - at least then you'll get a known value (0, false, null etc) instead of just "whatever happened to be in memory at the time." (It also removes the potential security issue of reading sensitive data which hadn't been explicitly wiped.)
There was a question about this very recently for C#... - read the answers there as well, as it's basically the same thing. You might also find Eric Lippert's recent blog post interesting; it's at least around the same area, even though it has a somewhat different thrust.
In Java, class and instance variables assume a default value (null, 0, false) if they are not initialized manually. However, local variables don't have a default value. Unless a local variable has been assigned a value, the compiler will refuse to compile the code that reads it. IMHO, this leads to the conclusion, that initializing a local variable with some default value (like null, which might lead to a NullPointerException later) when it is declared is actually a bad thing. Consider the following example:
Object o;
if (<some boolean condition>)
o = <some value>;
else
o = <some other value>;
System.out.println(o);
An initialization of o with null is completely unnecessary, since the Java compiler checks at compile time, that any code-path initializes o (with either null or some non-null value) before the variable is read. That means, that the compiler will refuse to compile the line System.out.println(o); if you would comment out any of the two initializations of the variable o in the code snippet above.
This holds for Java, and maybe for Java only. I don't know about language like C#. In good old C (and maybe C++) however, it is still recommended to always initialize variables when declaring them, AFAIK. Such "old-school" programming languages might be the reason, that the recommendation to always initialize variables pops up in books and discussions about modern languages like Java, where the compiler keeps track of whether a variable has been initialized or not.
Not totally true. Local variables only need to be initialized if being reference. A local variable can be left uninitialized if never referenced. For example:
int x; // Valid
int y;
println("y=" + y); // Not valid since y's value has never been assigned
Well, in case of local variable it's clear what it means 'before' since the program flow between declaration (in method) and reference is sequential. In case of fields declared outside of the method compiler never knows which code is going to be used when so it cannot generate an error as possibly some other method is going to initialize the field before it is used.
Local variables and primitives should be initialized before use because you would know what to expect from the values. Historically, when a new variable was created it would contain random values from the memory [and one could not predict the value]. Java also requires this because it prevents the presence of orphaned variables.
In practice all variables need to be initialized before using them.
I can't think of a time you'd want to use a variable before setting its value (unless you're comparing it against null).
It is necessary to initialize local variables (only when we use them) because they don't get any default value like instance variables.
And as basic rule, we should always initialize any variable before using it. Otherwise it may result in an error like nullPointer, etc
Now, why don't local variables get default value? The reason is that local variables reside on stack and is visible only in local method context, unlike instance variables which resides on heap and has scope throughout the program.
So when the stack will end local method's value will also get destroyed therefore:
1] They are supposed to be initialized explicitly (when we use them)
2] They should not be initialized implicitly (by null,0 or false) like instance variables
Going by the definition of local variable which state, a local variable is declared within a function or is passed as an argument in a function. If you do not initialized a local variable you will encounter exception handling problem because, the compiler will not be able to understand what value the variable holds
More specifically, assuming an object is partially initialized and a field x is initialized to null by the object's constructor, is it possible that some other thread reading this partially initialized object can see any other value than null?
If I understand it correctly, there's no guarantee in Java Memory Model itself that the value will always be null in such case. The question is: considering CPU caches and JVM memory architecture, should it be reasonably expected that the value could be not null?
Yes this is possible – there is no guarantee that an object which has been initialised in a constructor by one thread will be correctly read by another thread. The Java memory model allows the compiler to reorder statements within the constructor so long at the reordering does not effect the the state of the object on completion of the initialisation.
Another thread can obtain a reference to the object after it has been allocated in memory but before the constructor has completed and may read an uninitialised value.
You need to protect access to such variables using the synchronised keyword or by using synchronized collections.
See: Java Memory Model
By default, reference member variables are initialized to null. If the constructor had set the field to a non-null value, then it'd have been possible for other threads to see a null or non-null value. But if the constructor also is setting the value as null (which seems redundant in a simple scenario), then it is NOT possible for other threads to see any value other than null (the only value the field ever had is null, so there is no question of seeing any other value)
In C++ where we use pass by reference we reference the address of whatever it is that we passed from the argument to the parameter of the function which is essentially a pointer right? So while they are essentially the same thing, alias and all, doesnt a pointer require memory space as well? So shouldnt whatever we have in a parameter function let us call B point to the memory location of whatever the argument was that was passed let us call A which in turn is the memory location of our value( since A passed the memory location of our value as the argument)?
In java where we use pass by value we make a copy of the address of whatever it was we passed(the reference to the object for example).
So in the end i'm not truely seeing the difference between pass by value and pass by reference. Pass by value allocates space in memory for the original passed argument and the copy that both point to the value and pass by reference passes the memory location of our value as the argument which the parameter(the pointer which allocates space in the memory ) in our function uses to point to the value.
In C++ where we use pass by reference we reference the address of whatever it is that we passed
from the argument to the parameter of the function which is essentially a pointer right?
No. A reference is an alias (ie an alternative name) for an existing variable.
But at the assembly level your implementation may put the address of the referenced variable in an address register (or something similar) for the called function to use (if that is what you mean).
But for simplification you can think of it as a pointer that is automatically de-referenced (that is what I did when I first started). But when you get into the language references are actually fundamentally different from pointers.
So while they are essentially the same thing, alias and all, doesnt a pointer require memory space as well?
A pointer at the C++ level requies space (as it is addressable). You can take the address of a pointer. Fundamentally a reference does not require space (as you can't take its address). At an implementation level it may or may not have a physical memory location depending on how the compiler is implementing it.
So shouldnt whatever we have in a parameter function let us call B point to the memory location of whatever the argument was that was passed let us call A
It would have been nice if you had explained the above with a code example. But I think I understand. Assuming the function is not inlined then any parameter passed as reference needs some form of link back to the original object (as references always fundamentally refer to live objects). So how does it do. Compiler implementation detail (so you should not care). But probably a pointer on the stack or maybe just an address in an address register.
which in turn is the memory location of our value( since A passed the memory location of our value as the argument)?
Maybe or not. References do not have a physical location at the language level. So the compiler can play lots of nice little tricks with that.
In java where we use pass by value we make a copy of the address of whatever it was we passed(the reference to the object for example).
In Java you pass references by value. But Java references are fundamentally just pointers at a memory location. So you are passing a pointer by value. Which is one technique to use. Luckily C++ does not limit you to a single technique.
You can pass parameters by value or reference. You can even pass a pointer to an object by value or reference. So a couple of interesting techniques to use depending on the situation.
So in the end i'm not truely seeing the difference between pass by value and pass by reference.
Maybe that is because you are thinking about java references (which are passed by value).
In C++. If you pass by value, you are creating a new object that is passed as the parameter (which means you make a copy of the original, which can cost). If you pass by reference you are passing an alias to an object. So when you interact with the object you are modifying the original object.
int inc(int val) // pass by value
{
return ++val; // increment the passed value and return as a result.
}
int incref(int& val) // pass by reference
{
return ++val; // increment the reference.
// Since the reference is an alias this increment affects the
// original object. The result is returned.
}
void code()
{
int x = 5;
int y = inc(x); // x =5 and y = 6
int a = 8;
int b = incref(a); // a = 9 and b = 9
}
Pass by value allocates space in memory for the original passed argument and the copy that both point to the value and pass by reference passes the memory location of our value as the argument which the parameter(the pointer which allocates space in the memory ) in our function uses to point to the value.
Sorry I lost that.
Honest-to-god pass-by-value makes a copy of the variable's value and passes that to the function. This is usually done by pushing the value directly onto the stack. There is no way for the called function to modify the original value.
example:
a = 5
double(a); <-- but this is pass-by-value
print a
end
function double(x) <-- x is a variable with a value of 5
x = 2*x;
print x;
return x;
In the example above, the value of 5 is passed into double(). x in the function becomes 10, and 10 is printed. The function returns, and 5 is printed. Since a's value (not its address) was passed to the double(), where is no way for double() to change the value of a.
Had we passed a pointer to a (pass by reference), it would have not been a problem to change the value of a.
In pass by value the value in the address is calculated and passed at run time. but in pass by reference no value is determined only an address is passed to the function you are reading the value yourself and making changes directly in the memory location -not to the value that is passed to you as in pass by value- this is very low level and can result in problems because if one or more programs are performing operations on the memory location at the same time then the may be ambiguity.That is one of the reasons java doesn't support pointers.
In pass by value the data in the memory location is not changed while your function is performing operations. Because it is performing operations on a copy of it. Some thing like multithreading in java.
In Java, is null an existing object on the heap?
I'm trying to understand the difference between an uninitialized local variable (what does not compile) and one initialized with null (what compiles).
See here:
The Java IAQ:
Infrequently Answered Questions: Is null an Object?
Or, to save you the clicking, the answer is no, it is not an object. Being null means that no object is referenced.
This question highlights the connection between scope and definite assignment. If you step through the code below in a debugger, you can see several features as you break on each line:
No breakpoint possible; i is not in scope.
i is in scope, but "not a known variable in the current context."
The reference i has been assigned, and it has the value null.
The reference i has the value 1, which will be incremented after line 4.
Listing:
Integer i;
i = null;
i = Integer.valueOf(1);
i++;
Addendum:
So, what's the difference between null and uninitialized?
Prior to definite assignment, a local variable's value is inaccessible; any attempt to access the value is rejected at compile-time. Once a definite value is assigned, even null, that value can be accessed. This is a critical security feature in Java. In some languages, an uninitialized variable may reference values in memory left by a previous process.
Addendum: The content of a frame's local variables prior to initialization is unspecified. The bytecode verifier precludes bytecode that accesses uninitialized memory, but deviant bytecode is possible.
a local variable that hasn't been assigned yet, probably points to null too. I'm not a JVM expert, but that seems to be the logical choice.
so compiler checks for you to make sure you assigned something to the variable. other than that there's no difference. at runtime local variables not initialized yet are assigned to null.
Null is NOT an object. In fact it is the opposite of an object, and why you can't make method calls against a reference pointing at null. If you really must know what null is you can think of it as a something like zero. In fact a reference that points to null doesn't take up anymore memory, ie. zero. It has no value so it's a reference that doesn't refer to any object.
In Java you have to initialize a variable before you can use it. For reasons of history Java doesn't want you to assume values so the compiler forces you to assign a value to it. Part of the reasons for this is the bugs and security problems that C caused because it didn't initialize values or force you to do it before they were used. Java does initialize some values for primitives, and instance variables: 0, 0.0, false, and null etc, but for local variables you have to give it a value. It's for your own protection. :-)