Short instance creation, lazy default constructors and much more...

Hello all,

I was just browsing the proposed changes for Java 7 and came across a section on "short instance creation". I had though about this myself ages ago, and it seemed to me that I had a better idea than those that were being proposed! I though I'd post my idea here and see what you all thought of it. This is something that I wrote a while ago, so here you go. Let me know what you think.

Thanks.

Remove "new" Operator

Problem

"new" is superfluous to the language.

"new" refers at a fairly low level to memory management mechanics whereas it is preferable to use a more logic-based approach.

Solution

"new" is made optional syntax with the view of eventually removing it altogether.

Integer i = Integer();

Integer i = Integer(1);

myCall(Integer(1));

Benefits

The language grammar is simplified.

The language takes a step in the direction of abstracting away from low-level memory allocation/management mechanics and in favour of a logic-based approach.

Drawbacks

It may be considered that "new" provides clarity of description that a new object is being allocated.

Clarity is not regarded as a problem. As long as it is possible to determine that a constructor is being invoked (which it is via the capitalisation of the method name) then it is considered that the programmer will easily become acustomed to the syntax.

Compatibility

The optional nature of "new" maintains backwards compatibility.

Instance Constructors

Problem

Declaration syntax is overly verbose and cumbersome.

Solution

Constructors are embedded int the declaration.

Integer i =new Integer(i);

...is replaced by:

Integer i(1);

Benefits

Declaration syntax is simplified.

Drawbacks

It may be considered that "= new <Constructor>(..." provides clarity of description that a new object is being allocated.

Clarity is not regarded as a problem. As long as it is possible to determine that a constructor is being invoked (which it is via the bracket organisation) then it is considered that the programmer will easily become acustomed to the syntax.

Compatibility

The optional nature of the new declaration structure maintains backwards compatibility.

Better Memory Allocation and Management Syntax in Java

This is a suggestion for a modification to the Java language. The report first identifies some (of what in my opinion are) problems in the Java language in the area of memory allocation/management then suggests some possible solutions.

Problems

* Syntax for "new" is cumbersome and not aesthetic:

Integer i =new Integer();

* "null" is not aesthetic syntax and is a left-over reminant of C/C++.

if(i==null) ...

* "null" and "new" refer to memory allocation at too low a level.

* The fact that all objects may or may not be null is "untidy" and can lead to disorganised code:

void myMethod(String s)

{

if(s!=null || s.size()==0) ...

}

* The null property of an object is used to specify that an object may or may not exist. It may be useful to explicitly specify that an object's existance is optional.

Solutions

Removal of the "new" Operator

The "new" operator is completely removed and replaced with a much more compact syntax. Point-of-declaration constructors are introduced:

Integer i;

Integer i =new Integer();

Integer i =new Integer(1);

Integer i =null;

is replaced by:

Integer i;

Integer i();

Integer i(1);

Integer i;

Two advantages are gained, firstly the syntax is neater, more simple and more compact and secondly the syntax abstracts away from low level memory allocation mechanics in favour of a more logic-based approach.

For consistency, point-of-declaration constructors are introduced for ordinal types:

int i(1);

Lazy Default Construction

Newly created objects without constructors are created as "null" objects. At any point that an object is used it's state (null or not-null) is checked and if the state is null the default constructor is invoked.

Integer i;// i = null;

i.call();// if(i==null) i = new Integer(); i.call();

This method of construction allows an object to be declared but initialised at some future point, as is often useful. There is a further performance advantage that unused objects are never initialised. The current VM always performs null pointer checks on objects before using them so there is no performance loss from performing this check.

Syntax is now much cleaner and memory management does not even appear to come into the equation:

Integer i =new Integer();

i.intValue();

Compared with:

Integer i;

i.intValue();

Re-construction

Objects may be reconstructed by invoking a particular constructor:

Integer i;

i = Integer(1);

In this example, i is only constructed once due to lazy default construction.

Bypassing Lazy Default Construction

If there is any particular need to ensure an object is constructed at the point of declaration then an explicit default constructor may be used:

Integer i();

Optional Objects

The only use of null objects is to specify that an object is "optional". "null" is removed and replaced with an explicit "Optional Object" specification. The default construction of an optional object is null. There is no lazy default construction for optional objects:

!Integer i;// i = null;

An optional object's state (exists or does not exist) is determinedwith a boolean-type expression:

if(i) i.call();

else ...

Optional objects are useful for expressing optional parameters to a method:

Item find(Criteria c0, !Criteria c1)

{

...

Item i = getItem();

// New syntax:

if(c0.match(i) && (!c1 || c1.match(i)))return i;

// Old syntax:

if(c0.match(i) && (c1!=null || c1.match(i)))return i;

...

}

Optional paramters may be omitted instead of using "null":

Item i = find(c0,);

Optional objects may be set to null using:

i = !;

For consistency, optional parameters may written as:

Item i = find(c0,!);

Conclusions

"null" and "new" have been removed from the syntax altogether producing a more compact syntax which abstracts away from memory management mechanics.

Lazy default construction neatly and efficiently takes care of deferred construction.

Removal of "new" and "null" allows a guarentee that all standard objects are always valid thereby promoting cleaner code and removing the problem of forgetting to initialise objects.

Optional Objects are introduced which allow for explicit specification of objects that may be null. This removes dependence on documentation to describe allowed object state and reduces possible confusion over object state.

Optional method parameters may be omitted instead of using "null", and "null" detection is replaced with a boolean expression for compact and neat syntax that abstracts away from memory management mechanics.

Finally, and importantly for future discussions, objects are now initialised with the same syntax as ordinal types:

Integer i;

int i;

[8563 byte] By [chris1a] at [2007-11-27 3:43:57]
# 1
didn't get what were the duke stars here for
calvino_inda at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 2

> "new" is superfluous to the language.

Why? I don't readily agree with this claim.

> "new" refers at a fairly low level to memory management

> mechanics whereas it is preferable to use a more logic-based approach.

Why? The new operator creates an object and returns a reference to it. In a language where objects are created by instantiating classes there can hardly be operations that are higher level.

> Integer i = Integer(1);

You find the word "new" superfluous but not the repetition of the word Integer?

> myCall(Integer(1));

How do you know if this calls a constructor and not just a method called Integer?

jsalonena at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 3

> * The null property of an object is used to specify

> that an object may or may not exist. It may be useful

> to explicitly specify that an object's existance is optional.

Being null is not a property of an objectit is a/the reference that doesn't point to an object. This is definitely needed in a language that uses reference semantics. I don't understand how an object's existance could be optional: an object either is or is not.

jsalonena at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 4

> Being null is not a property of an objectit is a/the reference that doesn't point to an object. This is definitely needed in a language that uses reference semantics.

A value which doesn't point to an object isn't strictly needed - some reference based languages have a lattice type system where null is a reference to an object whose type is a subtype of all object types and the implementation of all its methods is to throw the equivalent of NullPointerException. Java's single inheritance and final methods prevent such an OO interpretation, but there's no requirement for a null value to not point to an object. Sometimes this language feature becomes a pattern, http://c2.com/cgi/wiki?NullObject . In lisp, for example, null is the empty list, and in some variants can have methods dispatched on it. The little I've seen of ML doesn't seem to have a global null value, but instead various types define their own.

Pete

pm_kirkhama at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 5

>

> > myCall(Integer(1));

>

> How do you know if this calls a constructor and not

> just a method called Integer?

That is true. You would have to impose capitalisation rules on the language (as in Haskell, for example), such that constructors are capitalised and methods are not etc. This should not be a problem in general as this is pretty much standard Java.

chris1a at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 6

> > * The null property of an object is used to

> specify

> > that an object may or may not exist. It may be

> useful

> > to explicitly specify that an object's existance is

> optional.

>

> Being null is not a property of an objectit is

> a/the reference that doesn't point to an object. This

> is definitely needed in a language that uses

> reference semantics. I don't understand how an

> object's existance could be optional: an object

> either is or is not.

An object's existance can be optional in situations like this:

Object cache = null;

...

if(cache!=null) return cache;

else return getObject();

Here, the cache object is essentially optional - there may or may not be a cached object. The problem is that most objects are not optional in this sense, ie. the object may always be assumed to exist, however, the language essentially allows the object to exist or not. Suppose I write a method:

f(Object o)

{

o.g();

}

It is possible to call this as f(null), but this would cause a runtime error. By ensuring that objects are never null (ie. never optional) then you remove the possibility of this error. If you want allow a null object, then this can be explicitly specified as an optional object:

f(!Object o)

{

if(o) o.g();

else doSomethingElse();

}

This makes it more obvious how to call the method, and also more obvious how the method code should treat the parameter. It is also more logical and less technical!

null is not really being removed, it is replaced by a more concise syntax, eg. f(!) instead of f(null) and the ability to evaluate the existance of an object with if(o) instead of if(o!=null). More importantly though, we are constraining some (in practice, most) objects to never allowing them to be null, thereby removing null object errors.

chris1a at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 7

foo (!Boolean b) {

if (b) {

...

with autoboxing, if b can be null, this does not distinguish between null and falsefoo (boolean b) {

if (b) {

...

with autoboxing, if b is false, it can be autoboxed to Boolean.valueOf(false), which is not null, therefore true.

So you need to get rid of autoboxing (or have extra logic to say coercing a Boolean reference uses its boolValue() rather than the normal path). This doesn't occur in C++ as you have to provide explicit coercion for values/references, and pointer coercion can't be overloaded.

There's a lot of Java code in the world that doesn't use the case conventions, even when the class and method names are in languages where it would be possible to do so. If you want to start something incompatible with Java but on the JVM, there's probably much more you could do, for example Scala seems a very nice general purpose language.

Pete

pm_kirkhama at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 8

> foo (!Boolean b) {

>if (b) {

>...

> with autoboxing, if b can be null, this does not

> distinguish between null and false foo (boolean

> b) {

>if (b) {

>...

> with autoboxing, if b is false, it can be

> autoboxed to Boolean.valueOf(false), which is not

> null, therefore true.

>

> So you need to get rid of autoboxing (or have extra

> logic to say coercing a Boolean reference uses its

> boolValue() rather than the normal path). This

> doesn't occur in C++ as you have to provide explicit

> coercion for values/references, and pointer coercion

> can't be overloaded.

>

> There's a lot of Java code in the world that doesn't

> use the case conventions, even when the class and

> method names are in languages where it would be

> possible to do so. If you want to start something

> incompatible with Java but on the JVM, there's

> probably much more you could do, for example Scala

> seems a very nice general purpose language.

>

>

> Pete

Absolutely, I realised that after I made the first post! You would have to have a different syntax, maybe:

foo(?Boolean b)

{

if(?b) ...

}

foo(b);

foo(?);

I've looked at Scala, and you probably have a point about that. It's not so widespread though so I wondered if a bit of crowbarring of syntax into Java might work (maybe with compilation compliance options). Maybe not though!

I also just wanted to put forward a few options that may be worth working towards or building on. I really think it could be a nice improvement to the language.

chris1a at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 9

For Java 7, current proposals for reducing the size of statements like this:

HashMap<String, Integer> map = new HashMap<String, Integer>();

are

map := new HashMap<String, Integer>();

and

final map = new HashMap<String, Integer>();

But isn't

HashMap<String, Integer> map;

much nicer? That is how it would look with my proposal. And then you could do this:

?Integer i = map.find(s);

if(?i) print(i);

else print("not found"):

And what's more, it would be impossible to do this

String s = null;

map.find(s); // Error

And impossible to do this:

Integer i = map.find(s);

And because you had to write

?Integer i = map.find(s);

You would be much less likely to forget to check whether or not i was null (or ?i was false).

chris1a at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 10

If you add lazy contruction then, effectively, this adds a synchronized test to the entry of every method, and field reference. When it's, say, an accessor method or simple field reference, this could easilly more than double it's execution time, even once it's constructed.

I guess this has to be true of static references and methods already, BTW.

malcolmmca at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 11

Integer i = map.find(s);

Actually, this would be allowed, but since the method declaration would look like this

?Integer find(String s) { ... }

So you would be more likely to write

?Integer i = find(s);

And therefore more likely to check if i was null (or ?i is false).

chris1a at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 12

> If you add lazy contruction then, effectively, this

> adds a synchronized test to the entry of every

> method, and field reference. When it's, say, an

> accessor method or simple field reference, this could

> easilly more than double it's execution time, even

> once it's constructed.

>

> I guess this has to be true of static references and

> methods already, BTW.

I don't think this is true, because I can directly emulate this with current Java, without needing to synchronize the constructor. I can just put if(o==null) o = new Object() before every use of o.

Object o = null;

if(o==null) o = new Object();

o.f();

Equivalent with lazy construction:

Object o;

o.f();

What do you think? Can you explain further?

chris1a at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 13

> I don't think this is true, because I can directly

> emulate this with current Java, without needing to

> synchronize the constructor. I can just put

> if(o==null) o = new Object() before every use of o.

You can use exactly the same data flow analysis mechanism as is currently used in the compiler to ensure that variables are assigned values before use; you'd insert the assignment rather than reporting an error; there's no requirement for a null check.

pm_kirkhama at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 14

> > I don't think this is true, because I can directly

> > emulate this with current Java, without needing

> to

> synchronize the constructor. I can just put

> if(o==null) o = new Object() before every use of o.

> ou can use exactly the same data flow analysis

> mechanism as is currently used in the compiler to

> ensure that variables are assigned values before use;

> you'd insert the assignment rather than reporting an

> error; there's no requirement for a null check.

I don't think that will catch every case though. You can write code where you can't determine that.

class C

{

void f() { o = new Object(); }

void g() { o.foo(); }

Object o = null;

}

When you call g(), how do you know that f() has not already been called?

chris1a at 2007-7-12 8:47:35 > top of Java-index,Java Essentials,Java Programming...
# 15

>I don't think this is true, because I can directly emulate this with current Java,

>without needing to synchronize the constructor. I can just put if(o==null) o =

>new Object() before every use of o.

That's not threadsafe. Suppose another thread tries to use the o reference while the constructor is running?

So a method like:

public int getThingy() {

return someField;

}

Which would probably get inlined by the JIT compiler in most uses becomes, effectively:

public int getThingy() {

synchronized(this) {

if(!_initialized) {

_intialized = true;

_init();

}

}

return someField;

}

Indeed, that has to happen every time a field is referenced. I guess it would be a process build into the JVM itself, but that doesn't remove the overheads of synchronization.

malcolmmca at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 16
My previous reply was based on the above examples being variables, not fields. If you use for fields, then you do have to do null checks and it does becomes thread sensitive. It also would break much more existing Java code, which often relies on uninitialised fields being
pm_kirkhama at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 17

> >

> > > myCall(Integer(1));

> >

> > How do you know if this calls a constructor and

> not

> > just a method called Integer?

>

> That is true. You would have to impose capitalisation

> rules on the language (as in Haskell, for example),

> such that constructors are capitalised and methods

> are not etc. This should not be a problem in general

> as this is pretty much standard Java.

I suspect that would be a very significant change to the language.

Methods are defined to use identifiers, just like classes, variables, arguments, etc are.

jschella at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 18

>

> null is not really being removed, it is replaced by a

> more concise syntax, eg. f(!) instead of f(null) and

> the ability to evaluate the existance of an object

> with if(o) instead of if(o!=null). More importantly

> though, we are constraining some (in practice, most)

> objects to never allowing them to be null, thereby

> removing null object errors.

So I have the following.....

class MyTableRecord

{

public String CustomerName; // Required.

public String Comment; // Optional.

}

In the database the comment column specifically allows for null values. Any textual value is legal. So exactly what value do I use to indicate that the value in the database is null?

jschella at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 19

> I don't think this is true, because I can directly

> emulate this with current Java, without needing to

> synchronize the constructor. I can just put

> if(o==null) o = new Object() before every use of o.

Not without synchronization you can't.

If you have something like the following the assignment to f is not allowed to occur until construction is complete.

final MyClass f = new MyClass();

Because of that it insures that it is not possible for two threads to access f at the same time and only one invokes the constructor. With your code example that can occur.

jschella at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 20

You use "optional" variables.

class MyTableRecord

{

// Notice how you don't need the comments either, because

// the code explains it for you!

public String CustomerName;

public ?String Comment;

}

?String indicates the variable is optionally null. It starts off as null, and to set it to null or to whatever you would just use:

Comment = "abc";

Comment = ?;

if(?Comment) insert(Comment);

else insertNull();

chris1a at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 21
Agreed.
chris1a at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 22

> > >

> > > > myCall(Integer(1));

> > >

> > > How do you know if this calls a constructor and

> > not

> > > just a method called Integer?

> >

> > That is true. You would have to impose

> capitalisation

> > rules on the language (as in Haskell, for

> example),

> > such that constructors are capitalised and methods

> > are not etc. This should not be a problem in

> general

> > as this is pretty much standard Java.

>

> I suspect that would be a very significant change to

> the language.

>

> Methods are defined to use identifiers, just like

> classes, variables, arguments, etc are.

I was agreeing to this!

chris1a at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 23

> Not without synchronization you can't.

>

> If you have something like the following the

> assignment to f is not allowed to occur until

> construction is complete.

>

> final MyClass f = new MyClass();

>

> Because of that it insures that it is not possible

> for two threads to access f at the same time and only

> one invokes the constructor. With your code example

> that can occur.

Yes, fair point.

chris1a at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 24

You could of course get round this by explicitly calling the constructor (as I said would be allowed if there was a particular need).

Object o();

thread1(o);

thread2(o);

Or, simply assigning the object a value before sharing between threads.

Object p;

p = Object();

thread1(p);

thread2(p);

However, this could potentially be confusing and error prone with people forgetting to use o().

chris1a at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 25

>

> > public int getThingy() {

>synchronized(this) {

>if(!_initialized) {

> _intialized = true;

>_init();

> }

>

>return someField;

>

>

>

> Indeed, that has to happen every time a field is

> referenced. I guess it would be a process build into

> the JVM itself, but that doesn't remove the overheads

> of synchronization.

You could do this:

public int getThingy()

{

if(this==null) // This already occurs in Java

{

synchronized(this)

{

this = _init();

}

}

return someField;

}

Such that you would only perform synchronization around the constructor and the methods would not be affected.

It's better, but far from ideal.

chris1a at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 26
Actually, no that wouldn't work either would it?!
chris1a at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...
# 27

I can't understand the need for changing the language in this way.

It seems like another attempt by Sun to try and bastardize the Java programming language by incorporating trivial code conventions.

All this does is add more complexity and in my opinion makes it MUCH harder to read.

Minimalist code doesn't necessarily mean easily maintainable code.

(sigh) ... I must be fighting an uphill battle because it seems that the minimalists have taken over at Sun. It all started going down hill with Java 5 and that is my professional opinion.

maple_shafta at 2007-7-21 20:54:15 > top of Java-index,Java Essentials,Java Programming...