This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Static fields on a null reference in Java
I am new to Java. I know if any object point to and if we try to perform any operation on that object, a Nullpointer exception is thrown by JVM. But in my case there is no Nullpointer exception please help me ?. Below is my code
public class Employee
{
public static String empName = "John"
public static void main(String args[])
{
Employee emp = new Employee();
emp = null;
System.out.println(emp.empName);
}
}
It prints John as output even emp object is pointion to null. But I am expecting a nullpointer exception.
because field is static.
In your case emp.empName equals to Employee.empName
Since you are accessing a static variable, so you will not get NPE if your reference is referencing null. This is because static fields are bound to class rather than any instance.
So, for static variable: -
Employee emp = null;
emp.empName; // This is evaluated as `Employee.empName;`
So, only the reference type is used. Regardless of whether that reference is pointing to null, or any subclass object.
As empName is static the call would be Employee.empName in the byte code, Thus no NPE:
original Code: System.out.println(emp.empName);
Byte code: GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
GETSTATIC oops/Employee.empName : Ljava/lang/String;
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 2 years ago.
Please see my code below. I have a functional interface IFace with a method. I'm creating an implementation using Method reference from a class instance of Test. Can anyone tell me how the interface still refers to the instance method even if the reference is nullified? or reference is changed...?
public class Test {
private int intVar;
public Test() {
intVar = 123;
}
public Test(int intVar) {
this.intVar = intVar;
}
public void myInstanceMethod() {
System.out.println("Hello from instance: " + intVar);
}
public static void main(String[] args) {
Test t = new Test();
IFace i = t::myInstanceMethod;
i.method(); // Hello from instance: 123
t = null; // Nullifying the reference
i.method(); // Hello from instance: 123
// Why still executing the method if reference is nullified?????
t = new Test(456);
i.method(); // Hello from instance: 123
// Why not Hello from instance: 456 ??????
}
static interface IFace {
void method();
}
}
In a sense, the question is similar to asking why printing b does not output null in the following program:
String a = "abc";
String b = a;
a = null;
System.out.println(b);
When IFace i = t::myInstanceMethod; finishes running, i has captured a reference to the object that t points to at this time. That reference is independent from the variable t. Look at it like i, the method reference, has its own variable pointing to the same object.
The memory is not freed when you nullified the reference. It's freed when ALL references are gone. By passing method reference you created new reference to object itself, so the ref count is 2 at that point, i.e. the i holds reference to t underneath
The following simple code snippet is working fine and is accessing a static field with a null object.
final class TestNull
{
public static int field=100;
public TestNull temp()
{
return(null);
}
}
public class Main
{
public static void main(String[] args)
{
System.out.println(new TestNull().temp().field);
}
}
In the above code, the statement System.out.println(new TestNull().temp().field); in which the static field field is being associated with a NULL objectnew TestNull().temp(), still it is returning a correct value of it which is 100 instead of throwing a null pointer exception in Java! Why?
As opposed to regular member variables, static variables belong to the class and not to the instances of the class. The reason it works is thus simply because you don't need an instance in order to access a static field.
In fact I'd say it would me more surprising if accessing a static field could ever throw a NullPointerException.
If you're curious, here's the bytecode looks for your program:
// Create TestNull object
3: new #3; //class TestNull
6: dup
7: invokespecial #4; //Method TestNull."<init>":()V
// Invoke the temp method
10: invokevirtual #5; //Method TestNull.temp:()LTestNull;
// Discard the result of the call to temp.
13: pop
// Load the content of the static field.
14: getstatic #6; //Field TestNull.field:I
This is described in the Java Language Specification, Section 15.11.1: Field Access Using a Primary. They even provide an example:
The following example demonstrates that a null reference may be used to access a class (static) variable without causing an exception:
class Test {
static String mountain = "Chocorua";
static Test favorite(){
System.out.print("Mount ");
return null;
}
public static void main(String[] args) {
System.out.println(favorite().mountain);
}
}
It compiles, executes, and prints:
Mount Chocorua
Static variables are shared among every object of a class. So while the actual object reference you are returning is null (In C++: TestNull* temp = null;), you have an object of type TestNull which Java can use to find static values of that class.
Remember in Java objects are really pointers. Pointers have a type. From that type Java can discern certain information, even if its pointing to null.
Static fields are associated with the class not an instance of that class. Therefore you don't need an instance of an object to access the static field.
You could also access the field by calling TestNull.field
I've come across a weird thing while learning Java. Consider the following program:
public class GetClassNameInheritance {
public static void main(String[] args) {
Employee e = new Employee();
Person p = (Person) e;
System.out.println(p.getClass());
}
}
class Person {
}
class Employee extends Person {
}
I was expecting the output to be Person because of the cast, but it is Employee! Honestly, I'm stumped and can't find an explanation. The official Oracle tutorial doesn't mention this behavior, and the docs seem too terse to be helpful. I can make out from other StackOverflow examples that this is something to do with "runtime class" but I don't understand the underlying idea. Can someone explain what's going on here?
In Java, Type casting does not change the type of object. Once an Employee, your object is always an Employee. Type casts do not work like in other languages such as C/C++.
Though the p reference is of type Person, it is in fact referring to an object of type Employee in the JVM heap. When you invoke the p.getClass() method, the reference in turn invokes the method on the object and not on the reference. That's the reason you see Employee in your output.
The only type of casts that would work is the one that you can perform on primitives.
int x = (int)2.5f;
The return value will be type cast to int.
You can read more about type casts and conversions here:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html
http://www.wideskills.com/java-tutorial/java-object-typecasting
Well let's look what happens when the main method is compiled:
0: new #2 // class Employee
3: dup
4: invokespecial #3 // Method Employee (Constructor)
7: astore_1 // Save local variable "e"
8: aload_1 // Load local variable "e"
9: astore_2 // Save to local variable "p"
10: getstatic #4 // Field System.out PrintStream;
13: aload_2 // Load local variable "p"
14: invokevirtual #5 // Method Object.getClass()
17: invokevirtual #6 // Method PrintStream.println(Object)
And if we were to look at a decompiler's interpretation of this bytecode:
public static void main(String[] args) {
Employee e = new Employee();
System.out.println(e.getClass());
}
The compiler has "optimized" the code which results in your cast being removed since it was deemed unnecessary. Anacron's answer explains why the compiler deemed it unnecessary.
If you want to know the super class of current class, you can use
p.getClass().getSuperclass() //returns person.
From the docs
getClass() always returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.
And a runtime class is one which has been instantiated with the constructor call.
Actually, if you will see, here Person p = (Person) e; the cast is not needed, you can always assign a derived class object to a base class.
For Example
List<String> list = new ArrayList<>();
Above will not throw an error.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
If the Employee reference is made null in the changedetails(), variable id value is retained and NullPointerException is not thrown (Code 1) may be because we just pass a copy of object's reference, but in Code 2 why the variables value has changed
Code 1:
public class JavaPassing {
public static void changedetails(Employee e)
{
e=null;
}
public static void main(String args[])
{
Employee emp = new Employee("Vishal",7);
changedetails(emp);
System.out.println(emp.id);
}
}
Code 2:
public class JavaPassing {
public static void changedetails(Employee e)
{
e.id=9;
}
public static void main(String args[])
{
Employee emp = new Employee("Vishal",7);
changedetails(emp);
System.out.println(emp.id);
}
}
In both cases Reference 'e' in changedetails() and 'emp' in main() both point to same object.
In code (1)
In changedetails() when you make e=null; ONLY e STOPS POINTING TO OBJECT. BUT emp CONTINUES TO POINT TO OBJECT. So in main() when you do emp.id value prints and no NullPointerException
In code (2)
In changedetails() when you make e.id=9 remember Both References are pointing to same object i.e.
'e' in changedetails() and 'emp' in main() point to same object ....
So e.id=9 means change made on same object hence when you do emp.id in main() value is 9
In java references to objects are passed by value.
So,
public static void main(String args[])
{
Employee emp = new Employee("Vishal",7);
changedetails(emp); / /object Employee ahs only one reference - "emp"
System.out.println(emp.id);
}
public void changedetails(Employee emp1){ // here both emp1 and emp of main() point to the same Employee object.
emp1.setId(100); // now since emp1 also points to same Employee object, the data will be changed.
emp1 = null;// now emp1 points to null. So, only emp is pointing to E,ployee
}
--------
A -->| Object |<-- B
--------
A.id = 10; // Property of object modified
B.id = 10; // Property of object modified here also
B = null ; // B is set to null
--------
A -->| Object | B (reference is null)
--------
Here when you set B to null, A is not modified it will continue to point the Object in heap.
And that is why it will not throw NullPointerException if you will access id from reference A. All you are confused is between reference of Object and Object in memory.
In your case, A is emp and B is e.
You can find some good explanation in this question.
The argument you pass into the method changedetails() is a variable of its own, different from the variable emp in your main() method. They both refer to the same eployee so. Hence if you refer to the employee and change its state, the change is visible in both methods, changedetails() and main(). But if you assign null to the argument variable of the method changedetails() this is a local change visible only in that method.
Sidenote: it is considered bad practice to change the value of method arguments. And after leaving the method changedetails(), the method arguments are gone, because they live on the stack and not on the heap.
The following simple code snippet is working fine and is accessing a static field with a null object.
final class TestNull
{
public static int field=100;
public TestNull temp()
{
return(null);
}
}
public class Main
{
public static void main(String[] args)
{
System.out.println(new TestNull().temp().field);
}
}
In the above code, the statement System.out.println(new TestNull().temp().field); in which the static field field is being associated with a NULL objectnew TestNull().temp(), still it is returning a correct value of it which is 100 instead of throwing a null pointer exception in Java! Why?
As opposed to regular member variables, static variables belong to the class and not to the instances of the class. The reason it works is thus simply because you don't need an instance in order to access a static field.
In fact I'd say it would me more surprising if accessing a static field could ever throw a NullPointerException.
If you're curious, here's the bytecode looks for your program:
// Create TestNull object
3: new #3; //class TestNull
6: dup
7: invokespecial #4; //Method TestNull."<init>":()V
// Invoke the temp method
10: invokevirtual #5; //Method TestNull.temp:()LTestNull;
// Discard the result of the call to temp.
13: pop
// Load the content of the static field.
14: getstatic #6; //Field TestNull.field:I
This is described in the Java Language Specification, Section 15.11.1: Field Access Using a Primary. They even provide an example:
The following example demonstrates that a null reference may be used to access a class (static) variable without causing an exception:
class Test {
static String mountain = "Chocorua";
static Test favorite(){
System.out.print("Mount ");
return null;
}
public static void main(String[] args) {
System.out.println(favorite().mountain);
}
}
It compiles, executes, and prints:
Mount Chocorua
Static variables are shared among every object of a class. So while the actual object reference you are returning is null (In C++: TestNull* temp = null;), you have an object of type TestNull which Java can use to find static values of that class.
Remember in Java objects are really pointers. Pointers have a type. From that type Java can discern certain information, even if its pointing to null.
Static fields are associated with the class not an instance of that class. Therefore you don't need an instance of an object to access the static field.
You could also access the field by calling TestNull.field