Non static block and constructor

A

asit

yesterday I read ab Non Static block.

I tried the following code

public class NonSta
{
int i;
NonSta()
{
System.out.println("Constructor");
i++;
System.out.println(i);
}
{
System.out.println("Non Static Block");
i += 10;
System.out.println(i);
add(100);
new NonSta();
}
void add(int k)
{
System.out.println("Add Block");
i += k;
System.out.println(i);
}
public static void main(String args[])
{
NonSta n = new NonSta();
}
}

I found that it becomes an infinite loop if the non static block
contains a call to constructor.

Does it logically imply "Non static block can't contain a
constructor".

Plz reply me !!!
 
A

Arne Vajhøj

asit said:
yesterday I read ab Non Static block.

I tried the following code

public class NonSta
{
int i;
NonSta()
{
System.out.println("Constructor");
i++;
System.out.println(i);
}
{
System.out.println("Non Static Block");
i += 10;
System.out.println(i);
add(100);
new NonSta();
}
void add(int k)
{
System.out.println("Add Block");
i += k;
System.out.println(i);
}
public static void main(String args[])
{
NonSta n = new NonSta();
}
}

I found that it becomes an infinite loop if the non static block
contains a call to constructor.

Does it logically imply "Non static block can't contain a
constructor".

You will have to check the JLS and the JVM spec to find out what
exactly is specified for this case.

It seems obvious to me that it should not work well.

The static initializer should start and complete before
any instances of the class is created.

So creating an instance in the static initialized does
not make any sense to me.

Whether it should be a compile time error or a runtime
error or what runtime error must be in the specs somewhere.

Arne
 
L

Lew

asit said:
yesterday I read ab [sic] Non Static [sic] block.
"ab"?
I tried the following code

public class NonSta
{
int i;
NonSta()
{
System.out.println("Constructor");
i++;
System.out.println(i);
}
{
System.out.println("Non Static Block");
i += 10;
System.out.println(i);
add(100);
new NonSta();
}
void add(int k)
{
System.out.println("Add Block");
i += k;
System.out.println(i);
}
public static void main(String args[])
{
NonSta n = new NonSta();
}
}

I found that it becomes an infinite loop if the non static [sic] block
contains a call to constructor.

It's not a loop.
Does it logically imply "Non static block [sic] can't contain a
constructor".

It should be obvious that a constructor cannot contain a constructor for
objects of the same class.
It seems obvious to me that it should not work well.

The static initializer should start and complete before
any instances of the class is created.

It's a *non*-static initializer.

Calling a constructor inside a constructor is bound to fail. How can it ever
conclude?

asit, the non-static initializer block is part of the constructor. The
constructor tries to construct another object of the type that it's
constructing. That object tries to construct yet another object in its
constructor. And so on, /ad infinitum/. No constructor can ever finish.

I'm sure if you think about it you'll figure out why this cannot succeed.
 
A

Arne Vajhøj

Lew said:
asit said:
I tried the following code

public class NonSta
{
int i;
NonSta()
{
System.out.println("Constructor");
i++;
System.out.println(i);
}
{
System.out.println("Non Static Block");
i += 10;
System.out.println(i);
add(100);
new NonSta();
}
void add(int k)
{
System.out.println("Add Block");
i += k;
System.out.println(i);
}
public static void main(String args[])
{
NonSta n = new NonSta();
}
}

I found that it becomes an infinite loop if the non static [sic] block
contains a call to constructor.
Does it logically imply "Non static block [sic] can't contain a
constructor".

It should be obvious that a constructor cannot contain a constructor for
objects of the same class.
It seems obvious to me that it should not work well.

The static initializer should start and complete before
any instances of the class is created.

It's a *non*-static initializer.

Ooops.

Then the rest of my reply does not make much sense.

Arne

PS: Weird construct - I have never used it or seen it used.
 
J

John B. Matthews

[...]
I found that it becomes an infinite loop if the non static block
contains a call to constructor.

Yes, your program recursively invokes the constructor in an instance.
Here is a simpler version of the same problem. Try running it with an
artificially small heap to see the effect, e.g.:

java -Xms1M -Xmx1M InstanceInitializer

Contrast this with a static initializer:

<http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html>
<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.6>
<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.7>

<code>
public class InstanceInitializer {

private static int count; {
System.out.print(++count + ", ");
new InstanceInitializer();
}

public static void main(String args[]) {
InstanceInitializer n = new InstanceInitializer();
}
}
Does it logically imply "Non static block can't contain a
constructor".

No. Infinite recursion is a programming error.
 
J

John B. Matthews

PS: Weird construct - I have never used it or seen it used.

It's handy when you want to initialize something as part of
construction, the initialization is rather complex (e.g., involves
temporary variables), there is more than one constructor, and the
initialization is common to all the constructors.[/QUOTE]

The difference bit me the other day when I intended to have a static
initializer but neglected the keyword. A static initializer would have
completed as part of class initialization, but the errant instance
initializer was happening later. I switched to a private static method.
 
J

Joshua Cranmer

asit said:
public class NonSta
{
{
System.out.println("Non Static Block");
i += 10;
System.out.println(i);
add(100);
new NonSta();
}

If you look at the actual bytecode, you will notice that this becomes
part of the constructor. So you have created infinite recursion.

I believe the proper name is an instance initialization block, but I
don't have my JLS reference up.
 
M

Mark Space

asit said:
I found that it becomes an infinite loop if the non static block
contains a call to constructor.

Does it logically imply "Non static block can't contain a
constructor".


"Can't" is a bit strong. It's a bad idea, usually. The following is
also a bad idea:

class Wtf {
public static void main( String ... args ) {
main( args );
}
}

but I could possibly think of a few reasons to call the main entry point
recursively, so "can't" is too strong, just you didn't do it correctly,
or for the right reason.
 
L

Lew

Patricia said:
Lew wrote:
...
...

How does this differ from any other recursive call? This program runs,
and terminates, despite the new Node instance expression inside the Node
constructor.

There was no terminating condition in the OP's situation.
 
L

Lew

Patricia said:
Of course. It is that lack of an appropriate bound on the recursion,
rather than the fact of new instance creation during new instance
creation for the same class, that caused the stack overflow.

I was just pointing out that calling a constructor inside a constructor
is not *bound* to fail. As with any other recursive call, it fails or
not depending on whether there are appropriate limits on the recursion.

But it is not "as with any other recursive call". Constructors are not methods.

You are correct to point out that it was the lack the terminating condition
that was the trouble, but my words were in the specific context of the O.P.'s
example.

Beyond that, it is not smart to construct another instance of a class within
the constructor of that class. This is not like calling a recursive method;
constructors are fundamentally different from methods. Constructors are for
the purpose of constructing the 'this' instance, and pretty much always cause
trouble when they exceed that mandate. Can you think of a case where it's
ever a good idea to construct an additional instance from within the constructor?
 
B

blue indigo

But it is not "as with any other recursive call".

It is too.
Beyond that, it is not smart to construct another instance of a class within
the constructor of that class.

I mostly agree with Peter Duniho's objections to this statement, but I'd
like to add that the tail-recursive construction of Node in Patricia
Shanahan's (since snipped by someone) example code is, while not
conventional for Java (where I would tend myself to use a static factory
method), exactly the norm for constructing things like that in lisp.
 
A

Arne Vajhøj

Lew said:
It's handy when you want to initialize something as part of
construction, the initialization is rather complex (e.g., involves
temporary variables), there is more than one constructor, and the
initialization is common to all the constructors.

It saves lines.

But I like to be able to read the sequence of lines in a constructor
without having to read in the JLS whether those non-static initializer
lines are executed first or last.

Arne
 
A

Arne Vajhøj

Peter said:
[...]
Beyond that, it is not smart to construct another instance of a class
within the constructor of that class.

Why not? Other than the general difficulty of getting recursion
correct, what's the problem? How is constructing an instance of the
object currently being constructed any worse than constructing an
instance of any other object? Or are you suggesting that when
constructing the instance of an object, you should not construct _any_
instance of _any_ object?

It adds the risk of making an infinite recursion.

It is a difference.

And we don't need an "other" to justify it not being good.
But if constructing another instance of the object being constructed is
an essential part of the construction of the object, why shouldn't it be
in the constructor?

I think that experience has shown that constructors should be kept
simple to bring object in consistent state and not to contain major
logic.
Sure. Consider a recursive data structure represented in a string (or
other data structure) passed to the constructor. Each constructor would
extract from the string whatever information pertains to the immediate
instance, creating any children indicated by the string, and passing to
those children whatever information remains in the string and is
pertinent to the construction of those children.

Eventually the string will be exhausted, the recursion will stop, all of
the constructors will exit normally and you'll be left with your
recursive data structure.

I would code that in another way.

I don't like the idea of new X() triggering half the codebase. A simple
constructor and a buildTree method would make the code easier to
understand.

Arne
 
L

Lew

Arne said:
It saves lines.

But I like to be able to read the sequence of lines in a constructor
without having to read in the JLS whether those non-static initializer
lines are executed first or last.

A good point, that has two solutions I can think of immediately that let you
still use instance initializer blocks. Get over your prejudice against
knowing the language in detail, or code those lines so they can be executed
either first or last without harm.

Otherwise, don't use them. Just because the language supports a feature
doesn't mean you have to use it. If you do use it, it behooves you to
understand the implications.
 
A

Arne Vajhøj

Lew said:
A good point, that has two solutions I can think of immediately that let
you still use instance initializer blocks. Get over your prejudice
against knowing the language in detail, or code those lines so they can
be executed either first or last without harm.

Otherwise, don't use them. Just because the language supports a feature
doesn't mean you have to use it. If you do use it, it behooves you to
understand the implications.

It is not only the original author - it is also all the
maintenance programmer that have to touch the code for a decade
or two.

The best code is not code that uses every subtle feature of the
language - the best code is code that everyone can read even without
knowing the language.

Arne
 

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,979
Messages
2,570,184
Members
46,721
Latest member
DollieSawt

Latest Threads

Top