I have this code:
MyClass object;
.... some code here where object may or may not be initialised...
if (object.getId > 0) {
....
}
Which results in a compile error: object may not have been initialised, which is fair enough.
Now I change my code to this:
MyClass object;
.... some conditional code here where object may or may not be initialised...
if (object != null && object.getId > 0) {
....
}
I get the same compile error! I have to initialise object to null:
MyClass object = null;
So what's the difference between not initialising an object, and initialising to null? If I declare an object without initialisation isn't it null anyway?
Thanks
fields (member-variables) are initialized to null (or to a default primitive value, if they are primitives)
local variables are not initialized and you are responsible for setting the initial value.
It's a language-definition thing.
The language states that variables of METHOD-scope MUST be manually initialized -- if you want them to start out as NULL, you must explicitly say so -- if you fail to do so, they are basically in an undefined state.
Contrarily, the language states that variables of CLASS-scope do not need to be manually initialized -- failure to initialize them results in them automatically getting initialized to NULL -- so you don't have to worry about it.
As far as the difference between the two states (null vs. undefined), yes they are basically the same -- but the language dictates that you need to initialize a variable (whether that's done automatically for you or not, depending on the variable's scope).
Your declaration of object is really a declaration of a pointer, or reference, to an instance of MyClass on the heap. If you don't initialize the pointer you essentially get a pointer pointing to somewhere random. By explicity initializing the pointer to NULL you are setting it to point to a NULL address that the compiler knows is invalid.
Extra confusion is introduced in Java because it implicitly initialises member variables to NULL for you.
It makes a bit more sense if you've used lower level languages like C++.
Related
I'm working in Java.
I commonly setup some objects as such:
public class Foo {
private SomeObject someName;
// do stuff
public void someMethod() {
if (this.someName != null) {
// do some stuff
}
}
}
The question is: Is someName in this example equated to null, as-in I can reliably for all objects assume null-checking uninitialized objects will be accurate?
Correct, both static and instance members of reference type not explicitly initialized are set to null by Java. The same rule applies to array members.
From the Java Language Specification, section 4.12.5:
Initial Values of Variables
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
[...] For all reference types, the default value is null.
Note that the above rule excludes local variables: they must be initialized explicitly, otherwise the program will not compile.
If an Object reference has been declared but not instantiated, its value is null.
I was wondering what happens at memory level when an object in defined, but not initialized.
For example:
public class MainClass {
public static void main (String[] args){
Object foo;
}
}
Is foo pointing to a memory space?
Does this behaviour change between different programming languages?
Thanks in advance.
Edit: I know the object will point to null when used, but I am interested to know what happens just after the object has been defined, and not instantiated yet.
Is there a reference to the memory in this case?
I was wondering what happens at memory level when an object in defined, but not initialized.
Lets assume that we are talking about Java here.
First I must correct your incorrect description. (For reasons that will become apparent ...)
This is not defining an object. Rather, it is declaring a variable. The identifier foo denotes a variable. Since the type of the variable is (in this case) Object which is a reference type, the variable may contain either a reference to a Java object or null.
Is foo pointing to a memory space?
The answer is slightly complicated.
If the variable is initialized, it will either point to some object or it will contain null.
If the variable is NOT initialized, then it depends on what type of variablle we are talking about:
For a field of a class (static or instance), a variable that is not explicitly initialized is default initialized to null.
For a variable that is a parameter or a catch variable, the Java language semantics ensure that the variable is always initialized ... so this is moot.
For a local variable, the JLS doesn't say what it contains before a value is assigned to it. You could say that the value is indeterminate. However the JLS (and at runtime, the JVM's classfile verifier) ensure that a program cannot use a local variable that is in an indeterminate state. (It is a compilation error in Java code to read a variable that has not been definitely assigned.) So it really makes no difference what the variable actually contains.
Note that in pure Java1 it is not possible to access a variable that contains a value that it wasn't set by either assignment or initialization. The Java Language Specification doesn't allow it and neither does the JVM Specification. A variable can never be observed to contain a random memory address.
Does this behavior change between different programming languages?
Err ... yes. For example, in C and C++, a program may use the value of a pointer variable that has not been initialized. The behavior that ensues is unspecified.
1 - If you use native code or Unsafe, it is possible for the code to corrupt a variable to contain anything. But don't do this deliberately as this is liable to hard crash the JVM. Native code and Unsafe means not pure Java.
In java , foo will point to "null" when it define in class ,
and foo will point to nothing where it define in function .
In Java you can think of object variables as pointers. By default they point to nothing, only the pointer itself is allocated (e.g. 8 bytes on the stack).
You can have it point to an actual instance of an object by allocating that object and assigning to the variable:
Object foo; // points to nothing (and may not be used)
foo.toString(); // compile error: The local variable obj may not have been initialized
foo = new Object(); // points to an instance of a new Object
foo = null; // again points to nothing, but is now initialized
foo.toString(); // will compile, but throw NullPointerException at run time
This is fundamentally different from C or C++, where Object foo; would actually be a local object allocated on the stack. Java never allocates objects on the stack, only primitive types or pointers.
In Java, what is the difference and best way to do?
Integer x = null; // x later assign some value.
Integer y; // y later initialize and use it.
The answer depends on what type of variable are you referring.
For class variables, there's no difference, see the JLS - 4.12.5. Initial Values of Variables:
... Every variable in a program must have a value before its value is
used:
For all reference types (§4.3), the default value is null.
Meaning, there is no difference, the later is implicitly set to null.
If the variables are local, they must be assigned before you pass them to a method:
myMethod(x); //will compile :)
myMethod(y) //won't compile :(
Local variables must be assigned to something before they are used.
Integer x = null;
myFunction(x);
// myFunction is called with the argument null
Integer y;
myFunction(y);
// This will not compile because the variable has not been initialised
Class variables are always initialised to a default value (null for object types, something like zero for primitives) if you don't explicitly initialise them. Local variables are not implicitly initialised.
Its better to not set it to null, otherwise you can by accident use it and cause NPE. Compiler wont help you with compile error. Only set to null if you want to have logic like if ( x != null ) { /use it/ }
No difference at all. Both cases when ever you want to use it, local variable must be in initialized form(must have a value).
From Java doc
Similar to how an object stores its state in fields, a method will
often store its temporary state in local variables. The syntax for
declaring a local variable is similar to declaring a field (for
example, int count = 0;). There is no special keyword designating a
variable as local; that determination comes entirely from the location
in which the variable is declared — which is between the opening and
closing braces of a method. As such, local variables are only visible
to the methods in which they are declared; they are not accessible
from the rest of the class.
Internally there is no difference. Also it is a debatable topic.
Use the local variable only if it is really required. Local variables are mostly in the following scenarios (I may be missing few other).
As a shorthand or for Readability
Integer myObject = someObject.someFunction().someOtherFunction();
If we use the syntax like that in many places, code will become clumsy.
For accessibility
Object returnObject = null;
if(mycondition)
{
returnObject = value1;
}
else if(secondCondition)
{
returnObject = value2;
}
return returnObject;
The caller of the above code snippet will take decision based on the return value.
Honestly speaking i am not seeing other valid use case to declare a variable without initial value.
Conclusion (Best Practice):
Declare local variable only if required
Always create local variable with default value.
No differences at all expect for one thing, if you don't initialize it and later on you try to use this variable (without changing the reference) means an error at compilation time, but if you initialize it and you use it later on (without changing the reference) means a NullPointerException.
I show you with an example.
Without initializing
Integer y;
y.intValue(); // Compilation error
With initializing
Integer x = null;
x.intValue(); // You are able to compile it but NullPointerException
I'm Getting this Comment from PMD.But i have to empty the data.Is there any way to remove the content of that Object.
Setting a variable to null just removes a reference to the object. it does not change the actual object.
If you need to clean up, you most likely need to do actions to the object referenced by your variable instead.
Assigning an object reference the value null does not 'empty the data'; it merely sets that variable reference to null.
It probably wants you to use the Null Object pattern.
Just set your variable to final.
For instance, if there is the following code, SONAR will report as a code smell:
private Object obj = null;
However, if you just add final, it can be resolved.
private final Object obj = null;
Consider this:
public class TestClass {
private String a;
private String b;
public TestClass()
{
a = "initialized";
}
public void doSomething()
{
String c;
a.notify(); // This is fine
b.notify(); // This is fine - but will end in an exception
c.notify(); // "Local variable c may not have been initialised"
}
}
I don't get it. "b" is never initialized but will give the same run-time error as "c", which is a compile-time error. Why the difference between local variables and members?
Edit: making the members private was my initial intention, and the question still stands...
The language defines it this way.
Instance variables of object type default to being initialized to null.
Local variables of object type are not initialized by default and it's a compile time error to access an undefined variable.
See section 4.12.5 for SE7 (same section still as of SE14)
http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5
Here's the deal. When you call
TestClass tc = new TestClass();
the new command performs four important tasks:
Allocates memory on the heap for the new object.
Initiates the class fields to their default values (numerics to 0, boolean to false, objects to null).
Calls the constructor (which may re-initiate the fields, or may not).
Returns a reference to the new object.
So your fields 'a' and 'b' are both initiated to null, and 'a' is re-initiated in the constructor. This process is not relevant for method calling, so local variable 'c' is never initialized.
For the gravely insomniac, read this.
The rules for definite assignment are quite difficult (read chapter 16 of JLS 3rd Ed). It's not practical to enforce definite assignment on fields. As it stands, it's even possible to observe final fields before they are initialised.
The compiler can figure out that c will never be set. The b variable could be set by someone else after the constructor is called, but before doSomething(). Make b private and the compiler may be able to help.
The compiler can tell from the code for doSomething() that c is declared there and never initialized. Because it is local, there is no possibility that it is initialized elsewhere.
It can't tell when or where you are going to call doSomething(). b is a public member. It is entirely possible that you would initialize it in other code before calling the method.
Member-variables are initialized to null or to their default primitive values, if they are primitives.
Local variables are UNDEFINED and are not initialized and you are responsible for setting the initial value. The compiler prevents you from using them.
Therefore, b is initialized when the class TestClass is instantiated while c is undefined.
Note: null is different from undefined.
You've actually identified one of the bigger holes in Java's system of generally attempting to find errors at edit/compile time rather than run time because--as the accepted answer said--it's difficult to tell if b is initialized or not.
There are a few patterns to work around this flaw. First is "Final by default". If your members were final, you would have to fill them in with the constructor--and it would use path-analysis to ensure that every possible path fills in the finals (You could still assign it "Null" which would defeat the purpose but at least you would be forced to recognize that you were doing it intentionally).
A second approach is strict null checking. You can turn it on in eclipse settings either by project or in default properties. I believe it would force you to null-check your b.notify() before you call it. This can quickly get out of hand so it tends to go with a set of annotations to make things simpler:
The annotations might have different names but in concept once you turn on strict null checking and the annotations the types of variables are "nullable" and "NotNull". If you try to place a Nullable into a not-null variable you must check it for null first. Parameters and return types are also annotated so you don't have to check for null every single time you assign to a not-null variable.
There is also a "NotNullByDefault" package level annotation that will make the editor assume that no variable can ever have a null value unless you tag it Nullable.
These annotations mostly apply at the editor level--You can turn them on within eclipse and probably other editors--which is why they aren't necessarily standardized. (At least last time I check, Java 8 might have some annotations I haven't found yet)