0

I just saw an constructor like this:

 public class Test {

     private int x;

     public int getX(){
         return x; 
     }

     public Test(){ // Default constructor
         x= 0;
     }

     public Test(int x){ // Constructor with parameter
         this.x= x;
     }

     public Test(Test t){ // Copy-constructor   <----This one!!!
         if (t!=null){
             this.x= t.getX();
         }  
     }
} 

I tried to imagine a situation where "t=null" could be the case. I tried this:

public class Fruit {

    public static void main(String[] args) {

        Test banane;
        Test jogurt = new Test(banane);
   }
}

Nevertheless I was unable to compile as for"The local variable banane may not have been initialized"

When I thought more about this it actually made sense for me. The compiler knows that the object and has not been initiliazed yet and complains about that. Since where unable to typecast a long to an object to make it look like a pointer/reference to an object, I cannot imagine a way to fool the compiler.

Or is this just state of the art for the case that JVM ***** up. If so, is there a document about this from Oracle?

Felix Crazzolara
  • 982
  • 9
  • 24

4 Answers4

2

You have two potential ways. Either pass a null reference, or a null literal.

public class Fruit {

    public static void main(String[] args) {

        Test banane = null;
        Test jogurt = new Test(banane);
        Test basicStuff = new Test(null);
   }
}
Kayaman
  • 72,141
  • 5
  • 83
  • 121
2

Here is the situation when t==null:

Test jogurt = new Test(null);

Your code does not compile because variable banane indeed is not initialized. The following fixes this:

Test banane = null;
AlexR
  • 114,158
  • 16
  • 130
  • 208
  • Take a closer look to my question please. I did not ask about how to fix the compiler errror. – Felix Crazzolara Aug 29 '16 at 12:07
  • OK, I have read your question again. Yes, this behavior is defined in JLS (Java Language Specification). Local variable must be initialized, members accept values automatically. Frankly speaking I do not remember why. – AlexR Aug 29 '16 at 12:11
0

JAVA could have come with 2 extreme options,

  1. No need to initialize fields or local variables, garbage values will be served. If this is the case lot of developers will debug their applications to find out problems because they forgot to assign values to variables.

2.variables and fields will be automatically initialized to default values. this is a cost, memory locations should be clean up even though the value is going to be overwritten in the next line.

So JAVA has come up with the best option, compiler can analyze local variables because it is life time start from "{" and ends with "}". if a variable has not been initialized compiler can complain us at the compile time.

But for field variables, compiler cannot do that, so java will initialize them to default value.

hunter
  • 3,963
  • 1
  • 16
  • 19
0

First, let's clear some stuff up. You're trying to apply some C++ concepts to Java, which does not always make sense.

  • in Java, an object can't be "not initialized"2
  • you're confusing null with an uninitialized variable
  • Variables in Java and C++ work differently
  • also, Java does not have copy constructors

If you declare a variable in Java of object type1, that variable stores what we call a "reference" in Java. This is not related to C++ references, although it may seem similar.

A variable can be either bound to an object (i.e. it stores a reference), or not, in which case the value that it stores is "null", a special kind of reference. If you want to draw an analogy to C++, the most apt comparison would be Test(Test *t). So an object variable in Java always stores a pointer, never an object. There is no way to store an object in a variable in Java. In C++ on the other hand, storing an object in a variable is the default.

This is the most important part. In C++, Test banane; this would create an object and call the default constructor. Java doesn't do that. Rather, in C++ speak, it declares a Test *banane variable which you aren't allowed to access. That's where your confusion stems from.


Java tracks which local variables have definitively been initialized (taking branches into account). Fields are always initialized by default.

Java will never allow you to pass a variable that wasn't initialized to a method. Actually, Java will refuse to compile a program, if you have an expression that accesses a possibly-uninitialized-variable.

Since we've learned that object variables in Java are essentially pointers, it makes sense to ask t == null. It doesn't check whether the variable is initialized.

null is a perfectly valid (and "initialized") value for an object variable to have. So t is null if you pass an expression to new Test(<expr>) that evaluates to null as @Kayaman explained. Either by storing that value in banane using banane = null or by using the literal directly when calling Test: new Test(null).

I strongly recommend you read Is Java "pass-by-reference" or "pass-by-value"?

1: e.g. your t variable in the Test(Test) constructor
2: ignoring a base constructor calling an overridden method

Community
  • 1
  • 1
phant0m
  • 16,595
  • 5
  • 50
  • 82