"Returning" a value from a constructor

P

Paul Chapman

I figured out the following interesting solution to the problem of returning
a value from a super ctor to a this ctor.

class Obj extends Header
{
final Handle handle;
final Mapper mapper;

private Obj(Cache cache, Handle handle, byte[] rawBytes,
int[] dataOffsetHolder)
{
super(cache, rawBytes, dataOffsetHolder);
this.handle = handle;
mapper = buildMapper(rawBytes, dataOffsetHolder[0]);
}

Obj(Cache cache, Handle handle, byte[] rawBytes)
{
this(cache, handle, rawBytes, new int[1]);
}

...
}

The problem was to retrieve an integer value from the super ctor. There's
no room to define a local temporary int[] variable before calling super,
because super() must be the first statement. But you can get a named
temporary int[] variable at the very beginning of a ctor by passing it in as
an argument.

The compiler is apparently clever enough to figure out that, despite the
fact that the second ctor doesn't set the final variables, they will
nevertheless be set by the ctor called with this().

However, if you rearrange things slightly:

private Obj(Cache cache, byte[] rawBytes, int[] dataOffsetHolder)
{
super(cache, rawBytes, dataOffsetHolder);
mapper = buildMapper(rawBytes, dataOffsetHolder[0]);
}

Obj(Cache cache, Handle handle, byte[] rawBytes)
{
this(cache, rawBytes, new int[1]);
this.handle = handle;
}

The compiler now reports two errors relating to whether handle has been set.
Strange.

Cheers, Paul
 
J

John C. Bollinger

Paul said:
class Obj extends Header
{
final Handle handle;
final Mapper mapper;
[...]

private Obj(Cache cache, byte[] rawBytes, int[] dataOffsetHolder)
{
super(cache, rawBytes, dataOffsetHolder);
mapper = buildMapper(rawBytes, dataOffsetHolder[0]);
}

Obj(Cache cache, Handle handle, byte[] rawBytes)
{
this(cache, rawBytes, new int[1]);
this.handle = handle;
}

The compiler now reports two errors relating to whether handle has been set.
Strange.

Not so strange to me. Every constructor must ensure that every final
field of its class is initialized, either by setting it directly or by
delegating to another constructor, but not both (because a final field
can only be set once). The private constructor does not set the
"handle" field, which is an error. (Consider what would happen if a
static method of the class created an instance via the directly private
constructor.) The other constructor attempts to set a final field after
having delegated to another constructor of its class, which is also an
error. (The the delegate constructor is supposed to have already set
the value.)
 
P

Paul Chapman

John,
Not so strange to me. Every constructor must ensure that every final
field of its class is initialized, either by setting it directly or by
delegating to another constructor, but not both (because a final field
can only be set once).

Ah, yes. I should have tried the other experiment, where the private
constructor set none of the finals, and the delegating constructor set all
of them. I just have, and of course it doesn't work.

Cheers, Paul
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,781
Messages
2,569,619
Members
45,316
Latest member
naturesElixirCBDGummies

Latest Threads

Top