Anonymous blocks for memory saving and flexibility?

G

gajo

I was wondering if it's possible to use anonymous inner blocks the same way
you use anonymous classes. Like in the following case:

int i = {
int a = 5;
return a*2;
};
System.out.println(i);

I know this won't work, but you get the idea. This is only a simple example,
but I actually did come to this while writing a huge chunk of code which had
only the purpose of initializing an object. Many variables were used that
would only be used once, and then later the program would never use them
again, but they would stay resident in the memory because they belong to the
same block.
Now, if I was able to do what I wrote in that example above, I could use
tons of variables in one inner block, and in the end throw them all away and
return only the finished "product"

Oh, and don't tell me that I should put that block in a method of a class,
and call that method. I did do that in the end, but I had to add a lot of
extra inner-connections between the classes, and the program lost its
flexibility. If I was able to do the above mentioned code, I would have
solved the problem in minutes, not hours.

Gajo
 
T

Thomas Kellerer

I was wondering if it's possible to use anonymous inner blocks the same way
you use anonymous classes. Like in the following case:

int i = {
int a = 5;
return a*2;
};
System.out.println(i);

I know this won't work, but you get the idea. This is only a simple example,
but I actually did come to this while writing a huge chunk of code which had
only the purpose of initializing an object. Many variables were used that
would only be used once, and then later the program would never use them
again, but they would stay resident in the memory because they belong to the
same block.

Hmm, wouldn't this

int i = 0;
{
int a = 5;

i = a*2;
}

be roughly equivalent to what you would like to do?

Thomas
 
C

Chris Smith

gajo said:
I was wondering if it's possible to use anonymous inner blocks the same way
you use anonymous classes. Like in the following case:

int i = {
int a = 5;
return a*2;
};
System.out.println(i);
Oh, and don't tell me that I should put that block in a method of a class,
and call that method. I did do that in the end, but I had to add a lot of
extra inner-connections between the classes, and the program lost its
flexibility. If I was able to do the above mentioned code, I would have
solved the problem in minutes, not hours.

Why did you put the method in some new class? Why not make it a private
method in the current class?

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

John C. Bollinger

gajo said:
I was wondering if it's possible to use anonymous inner blocks the same way
you use anonymous classes. Like in the following case:

int i = {
int a = 5;
return a*2;
};
System.out.println(i);

I know this won't work, but you get the idea. This is only a simple example,
but I actually did come to this while writing a huge chunk of code which had
only the purpose of initializing an object. Many variables were used that
would only be used once, and then later the program would never use them
again, but they would stay resident in the memory because they belong to the
same block.

I wouldn't assume so. Java compilers conceivably can make local
variables share storage, provided that they can prove that the variables
involved will not be corrupted. If you want to make sure that an object
becomes eligible for GC then you can always clear all its references (if
you can find them all). And then there's the JIT compiler. Once it
kicks in, all bets are off.
Now, if I was able to do what I wrote in that example above, I could use
tons of variables in one inner block, and in the end throw them all away and
return only the finished "product"

You can write this:

int i = 0;
{
int a = 5;
i = a * 2;
}

But it doesn't really address your goal very well because variables
declared inside a block actually live at the method level. Java has
nested scopes, but bytecode doesn't. The only way in Java to _ensure_
that the storage for your temporary variables is released when you're
done with them is to return from the method in which they are declared.
The above does provide a clue to the compiler, however, that it would
be OK for some other variable outside the block to share storage with a.
In fact, a smart compiler might even determine that i can share
storage with a in that simple example.
Oh, and don't tell me that I should put that block in a method of a class,
and call that method. I did do that in the end, but I had to add a lot of
extra inner-connections between the classes, and the program lost its
flexibility. If I was able to do the above mentioned code, I would have
solved the problem in minutes, not hours.

If you had waited until you knew you had a real problem then you might
not have even had to spend minutes. Shaving a few bytes or even a few
kB from your program's memory footprint is probably not worth hours of
work. It is not worth any work if your application is wasting megabytes
somewhere else. Make it work. *See* where the biggest problems are.
Then, if necessary, make it faster / more efficient.


John Bollinger
(e-mail address removed)
 
G

gajo

Thomas Kellerer said:
Hmm, wouldn't this

int i = 0;
{
int a = 5;

i = a*2;
}

be roughly equivalent to what you would like to do?

Thomas

I knew there was going to be some confusion. OK, let me give you a more
general idea of what was going on.
I have a class TestClass, who has only one constructor which requires 5
parameters to be called.
Let's say it's TestClass T = new TestClass(string, integer, integer,
someClass, someStream);

I can write something like TestClass T;
Because T is not static, I cannot open a block and say
{
T = new TestClass(...);
}

However, it would be favorable if I could use a block, because then I could
do like:
TestClass T = {
System.out.print("Write a number: ");
int tmp = Integer.parseInt(stdin.readLine());
System.out.print("Write a string: ");
String str = ............
.....
return new TestClass(tmp, str, blablablah, ...);
};

You see what I mean? The variables tmp, str etc. would all be gone from the
memory, and I would only return a newly constructed TestClass which will be
received by T.

Gajo
 
G

gajo

Chris Smith said:
Why did you put the method in some new class? Why not make it a private
method in the current class?

I didn't put it in a new class, I've put it in a new method inside my main
class, but because of that I needed to change some of the other classes so
that they would properly communicate with my main class. Some private
methods had to be made public, or static, etc...
 
C

Chris Smith

gajo said:
I didn't put it in a new class, I've put it in a new method inside my main
class, but because of that I needed to change some of the other classes so
that they would properly communicate with my main class. Some private
methods had to be made public, or static, etc...

That was not necessary. Refactoring a section of code into a new
private method will never change the non-private API of a class, nor
therefore the way other classes interact with that class.

In your case, the solution would look like:

public void yourOriginalMethod()
{
int i = getI();
System.out.println(i);
}

private int getI()
{
int a = 5;
return a*2;
}

All of your original code (which I called yourOriginalMethod) can still
be called exactly as it was before. This is identical to your
"anonymous block" syntax, in that getI() is a private implementation
detail of yourOriginalMethod(), and there's no way to externally observe
whether it even exists.
--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Smith

John said:
The above does provide a clue to the compiler, however, that it would
be OK for some other variable outside the block to share storage with a.
In fact, a smart compiler might even determine that i can share
storage with a in that simple example.

It's worth emphasizing that this is true for a not-very-strict
definition of "smart".

Practically *any* modern compiler is going to notice and do this.
Modern compilers convert code into intermediate forms, generally using
something called SSA ("static single assignment"). SSA makes it
remarkably obvious which data can be shared in the same memory, but not
at all obvious which data originally had what scope or was assigned to
which local variable. In fact, if information about local variables and
scopes is saved at all, it's only so that the compiler can output
debugging information.

It's not necessarily true that *all* compilers use an SSA intermediate
form, and I haven't paid attention for a number of years, but it's quite
unlikely that a newer compiler would be less capable or more tied to the
form of the source code. That's true for native source compilers *and*
for Java JIT compilers. (I don't know about the Java bytecode compiler;
generally, it benefits from preserving information about source code, so
it may choose not to do this.)

The point is that while it may seem to a naive oberver to require some
degree of intelligence or special effort to rewrite the code in that
way, for a compiler with an SSA intermediate form or equivalent, it
would require immense amounts of intelligence to *not* do that
optimization. So don't look at this as an ideal-case scenario, but
rather as the norm. Small scope in a method's local variables is good
for code quality, but not performance.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

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

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top