1

Is there a case when an object is declared without a call to the constructor? as in, for example:

ArrayList<Integer> grades;

Or is it always the case that ArrayList<Integer> grades (as in our example here) would always be followed by a call to a constructor as in,

ArrayList<Integer> grades = new ArrayList<Integer>();

?

If the latter is the case i.e. a declaration of an object is always followed by its initialization with a constructor then why isn't

ArrayList<Integer> grades;

already implies

ArrayList<Integer> grades = new ArrayList<Integer>();

Otherwise when is it the case that an object is declared without an immediate call to the constructor following it?

Is it the case that

ArrayList<Integer> grades;

can be initialized by anything other than

= new ArrayList<Integer>();
Zvi
  • 21
  • 4
  • 2
    Related reading: [Which arguments pass by value and which pass by reference in Java?](http://programmers.stackexchange.com/q/131624/22815) –  Mar 13 '15 at 02:37

5 Answers5

6

Consider two distinct concepts: objects and references.

References 'point' to objects in memory, but they are not the objects themselves. In Java, we always refer to and control objects through references to them. In Java, you never store the object itself in the variable, only it's address in memory (not exactly - implementation dependent - but you get the idea).

So by declaring ArrayList<Integer> grades;, what you do is create a reference, which is able to point to objects of type ArrayList<Integer> (and any subtype).

And by declaring new ArrayList<Integer>(), what you do is create a new object in memory, and have a 'pointer' to it returned to you (not the actual object data).

So by declaring ArrayList<Integer> grades = new ArrayList<Integer>();, you create an ArrayList<Integer> somewhere in memory, and assign its memory address (again, sort of) to the variable grades.

Declaring only ArrayList<Integer> grades; creates an empty reference that points nowhere.

Makoto
  • 837
  • 1
  • 8
  • 14
Aviv Cohn
  • 21,190
  • 31
  • 118
  • 178
1

Yes, references to objects can be initialized without constructors or visible assignments. This effect is often achieved by using Dependency Injection containers like Guice or Spring.

class Foo {
  @Inject
  Integer bar;
};

Foo foo = container.create(Foo.class);
assert foo.bar != null;

If this class is instantiated in Injection container context, its field bar will get a value without ever being directly assigned. These usually use reflection to set values, so while assignment is not explicit it still happens. I don't think we can do same trick for local variables.

Basilevs
  • 1,221
  • 9
  • 11
1

Is there a case when an object is declared without a call to the constructor?

There certainly is.
All of them, in fact.

Declaring an object variable creates a location ("address") into which the program can later write a reference ("pointer") to an instance of an object [of the specified Type].

Instantiating an object is the action that calls the relevant constructor.

The ...

Type name = expression ; 

... syntax is just a compact way of doing the declaration and instantiation as a "one-liner", but it is functionally no different to ...

Type name [ = null ] ; 
name = new Type( argument, ...); 

Secondly:

Is it the case that "ArrayList<Integer> grades" can be initialized by anything other than "= new ArrayList<Integer>()".

Again, Yes.
You can initialise the variable called grades to the value of any expression of the data Type "ArrayList", for example.

ArrayList<Integer> grades = class.getStudentGrades(); 
Phill W.
  • 11,891
  • 4
  • 21
  • 36
1

For the sake of simplicity, Java designers decided Strings, despite not being primitives, can be declared and initialized as such.

String s = "test";

which is the same as

String s = String("test");

Something similar they did with arrays:

int[] numbers = {1,2,3};

Those are examples of objects being initialized without explicitly calling their constructors with new(). but you ca be sure the constructor is being called anyway.

Tulains Córdova
  • 39,201
  • 12
  • 97
  • 154
0

then why isn't

ArrayList<Integer> grades;

already implies

ArrayList<Integer> grades = new ArrayList<Integer>();

First, read @AvivCohn's answer about references.

Second, besides @Basilev's answer about dependency injection, there are also two reasons why an implicit call to new may not be desired (what follows are Java-specific and not programming concepts in general):

  1. Construction of a new object is "expensive"

    • edit: As @MikePartridge mentioned helpfully in the comments, I don't mean "expensive" in the sense of object creation per se, but whether an object can be created with just a new MyObject(...) one-liner or not. Do see this link that dispels with the myth that object creation is expensive.
    • Your ArrayList example will be a bad example of showing why this is so, but consider an object that requires many fields to be set, which may each require their own expensive construction. The fields' values may have to be retrieved from a database or remote procedure calls. That is why we have the builder or factory patterns that builds the object for us, before assigning that to the reference.
    • This is related to dependency injection.
    • Of course, implicitly, there will be a new MyObject(...) called in the builder/factory, but the object will be initialized properly before the assignment.
    • On a related note, sometimes the constructor then becomes a private constructor following the builder pattern, as callers to the instantiation of said class need not know how the object is initialized.
  2. There can be different ways of assigning an object to a reference

    • Here are actually two examples to show this, but I'm just going to club them under the same reason. In both examples, test can only be set once due to its final modifier, which prevents simple programming mistakes such as over-writing the reference (and then possibly making the wrong comparisons). In any case, they (hopefully) show why there cannot be an implicit assignment to new String(), and why it is not desired. Again, the call to new (just declaring "..." does that in Java) is done explictly during the assignment, instead of implicit as you have asked in your question.
    • switch/if logic to determine value to set

      final String test;
      switch (value) {
      case A:
          test = "some-text";
          break;
      case B:
          test = "more-text-please";
          break;
      ...
      }
      
    • try-catch to do alternative assignment in case of exceptions

      final String test;
      try {
          test = someMethodThatReturnsAStringOrMayThrowAnException();
      } catch (SomeException e) {
          logThisException(e);
          test = "alternate-value";
      }
      
h.j.k.
  • 1,737
  • 1
  • 16
  • 20
  • 1
    Object creation (in Java at least) is not expensive: http://programmers.stackexchange.com/a/149569/34183 – Mike Partridge Mar 13 '15 at 12:15
  • @MikePartridge by "expensive", I meant cases where instantiating a new object is not as trivial as a one-liner `new MyObject(...)`. I have tweaked my answer - hopefully in a slightly positive way - to reflect your contribution on the link as well. Thanks anyway! – h.j.k. Mar 13 '15 at 14:38
  • 1
    In that case, a more accurate word might be "verbose". – Mike Partridge Mar 13 '15 at 17:49