Updates to a single class instance

U

unlikeablePorpoise

I hope you guys can help me.
I am planning to write a program with multiple packages and one of
these packages will have a class with storage variables that I would
like to update from any other class. I would like to know whether
there is a way to "point" to a single instance of this class so that I
can update the variables from anywhere in the program.

Thanks,
Sarah
 
K

Knute Johnson

I hope you guys can help me.
I am planning to write a program with multiple packages and one of
these packages will have a class with storage variables that I would
like to update from any other class. I would like to know whether
there is a way to "point" to a single instance of this class so that I
can update the variables from anywhere in the program.

Thanks,
Sarah

Search Google or Wikipedia for Singleton. The other non-OO (and don't
tell anybody that I suggested this) is to use public static variables in
your globals class.
 
E

Eric Sosman

I hope you guys can help me.
I am planning to write a program with multiple packages and one of
these packages will have a class with storage variables that I would
like to update from any other class. I would like to know whether
there is a way to "point" to a single instance of this class so that I
can update the variables from anywhere in the program.

... effectively making all of them "global variables."
Global variables are very convenient when you start to write
a program, but they have drawbacks that tend to become more
and more troublesome as the program grows and changes. Be
warned! Global variables deserve their ill repute.

... but if you're sure this is what you want, it sounds
like you should use what's called a "singleton:" a class with
exactly one instance (you can enforce this by making the only
constructor private and calling it exactly once from within
the class). You could make that one instance be a member of
the class:

public class Global {
private Global() { }
public static final Global INSTANCE = new Global();
}

.... or you could keep the instance private and use an accessor
method to provide it to the rest of the program:

public class Global {
private Global() { }
private static final Global INSTANCE = new Global();
public static Global getInstance() {
return INSTANCE;
}
}

For the variables the Global instance contains you have a
similar choice: Make them public, or keep them private and
write methods to set and retrieve their values. Usually the
latter is the better choice, because it allows for much more
flexibility: it's easy to make validity checks on the values
that are set, it's easy to keep valueB up to date when valueA
changes, and so on.

You can even do without the Global instance altogether,
making all the variables static members of the Global class
itself:

public class Global {
private Global() { }

private static int valueA;
public static int getValueA() { return valueA; }
public void setValueA(int newValue) {
if (newValue < 42)
throw new IllegalArgumentException(...);
valueA = newValue;
}
...
}

Keep in mind, though, that all of these techniques are
just variations on the global variable, a construct that is
capable of causing a surprising amount of trouble.
 
T

Thomas Hawtin

Knute said:
Search Google or Wikipedia for Singleton. The other non-OO (and don't
tell anybody that I suggested this) is to use public static variables in
your globals class.

Or private static variables with static get/set methods. That is to all
intents and purposes the same thing as a singleton, only there is no
pretend OO.

It's better to write code that doesn't use static variables, whether
Singletons or not. That is easier if the code is coherent.

Tom Hawtin
 
U

unlikeablePorpoise

Thanks for your replies. I tried to use a singleton, but for some
reason each attempt to create the singleton from different classes
says the object is null (the second and subsequent calls should say
that the object has been created). Here's the test code:


package org.collector;

public class Collector{

private Collector() {}

private static Collector ref;

public static synchronized Collector getCollectorObject()
{
if(ref == null)
{
System.out.println("ref is null");
ref = new Collector();
}
else
{
System.out.println("ref exists");
}

return ref;
}
}

When I call 'Collector col = Collector.getCollectorObject();' twice in
two different classes, it returns "ref is null". However, if I do this
twice in the same class method, ie

Collector col = Collector.getCollectorObject();
Collector col2 = Collector.getCollectorObject();

I get the expected result:

"ref is null"
"ref exists"

Just to clarify, the Collector singleton is in its own package, and
the methods that have to access it are in different packages.

Am I missing something here? Or is the singleton limited to use one
class or package?

Thanks for your help!
Sarah
 
S

Stefan Ram

Thomas Hawtin said:
It's better to write code that doesn't use static variables,
whether Singletons or not. That is easier if the code is
coherent.

The first Java-Program a programmer encounters:

public class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( "Hello world!" ); }}

uses a static variable »out«.

To avoid it, we might need a new Java with:

public class Main
{ public static void main( final System system )
{ system.out.println( "Hello world!" ); }}

Then, »system« needs to be passed to many methods and
constructors, whereever it possibly might be needed.
Or private static variables with static get/set methods. That
is to all intents and purposes the same thing as a singleton,
only there is no pretend OO.

An example would be the getter:

java.lang.Thread.currentThread()

It is not the same as a singleton, because there is no
intention that the result is the /only/ instance of its
class.

To avoid it, we'd need to pass another object, because,
logically, the current thread is not a system property.

public class Main
{ public static void main( final System system, final Thread currentThread )
{ system.out.println( "Hello world!" ); }}

This also would have to be passed to every method that
possibly might need it some day or otherwise many signatures
will need to change in order to add it as a parameter.
 
L

Lew

Stefan said:
An example would be the getter:

java.lang.Thread.currentThread()

It is not the same as a singleton, because there is no
intention that the result is the /only/ instance of its
class.

This is not a static variable but a static method - whole other thing.
 
L

Lew

Thanks for your replies.

Simply to avoid top-posting will indicate thanks.
package org.collector;

Are you an org, named "collector"?

The org domain implies non-profit organizations.
public class Collector{

private Collector() {}

private static Collector ref;

public static synchronized Collector getCollectorObject()

Since everything in Java is an object, having "Object" in your method name is
redundant.
{
if(ref == null)

This is overuse of lazy initialization.

Just establish the object in the class initializer.
{
System.out.println("ref is null");
ref = new Collector();
}
else
{
System.out.println("ref exists");
}

return ref;
}
}

When I call 'Collector col = Collector.getCollectorObject();' twice in
two different classes, it returns "ref is null". However, if I do this
twice in the same class method, ie

I don't know exactly why this happens, but I bet you'll get rid of the problem
altogether like this

public class Collector
{
private Collector()
{
}
private static final Collector UNIQUE = new Collector();
// this has the advantage of making the variable non-replaceable
// and eliminating the need for synchronization

public static Collector getCollector()
{
return UNIQUE;
}
}
 
R

Roedy Green

I am planning to write a program with multiple packages and one of
these packages will have a class with storage variables that I would
like to update from any other class. I would like to know whether
there is a way to "point" to a single instance of this class so that I
can update the variables from anywhere in the program.

the simplest way is to give it some static public members or static
public setter methods. The fancy pants way is to use a Singleton.
See http://mindprod.com/jgloss/singleton.html
 
U

unlikeablePorpoise

I don't know exactly why this happens, but I bet you'll get rid of the problem
altogether like this

public class Collector
{
private Collector()
{
}
private static final Collector UNIQUE = new Collector();
// this has the advantage of making the variable non-replaceable
// and eliminating the need for synchronization

public static Collector getCollector()
{
return UNIQUE;
}

}

I am still getting the same problem with your suggestion implemented
in my code.

Surely the singleton design pattern can work in multiple classes/
packages. Has anybody gotten this to work before?

Thanks,
Sarah
 
E

Eric Sosman

(Please position a reply after the message you're replying
to, or interspersed with it for a point-by-point reply.
Backward things read to harder it's.)

Thanks for your replies. I tried to use a singleton, but for some
reason each attempt to create the singleton from different classes
says the object is null (the second and subsequent calls should say
that the object has been created). Here's the test code:


package org.collector;

public class Collector{

private Collector() {}

private static Collector ref;

public static synchronized Collector getCollectorObject()
{
if(ref == null)
{
System.out.println("ref is null");
ref = new Collector();
}
else
{
System.out.println("ref exists");
}

return ref;
}
}

When I call 'Collector col = Collector.getCollectorObject();' twice in
two different classes, it returns "ref is null". However, if I do this
twice in the same class method, ie

Collector col = Collector.getCollectorObject();
Collector col2 = Collector.getCollectorObject();

I get the expected result:

"ref is null"
"ref exists"

Just to clarify, the Collector singleton is in its own package, and
the methods that have to access it are in different packages.

Am I missing something here? Or is the singleton limited to use one
class or package?

With the code as you've shown it, I don't understand how
the behavior you report can occur. Is the Collector class
truly as lightweight as shown? Or have you deleted other bits
of code for brevity's sake? That's usually a good idea, but
you may have omitted something important -- for instance, a
method that accesses `ref' while synchronizing on something
other than Collector.class, or not synchronizing at all.

As for the interaction of package membership and singletons:
There is none. The package forms part of the complete name of
a class (it's org.collector.Collector, not just Collector), and
package membership affects the reach of some access levels (but
not public and not private). Package membership has nothing to
do with whether `ref' is or isn't null, nor with what the method
synchronizes on, nor with how many times the constructor is used.

Perhaps the secret lies in how you call the method "twice in
two different classes:" if you run one class' main method and let
the program finish, and then run the other class' main method and
let its program finish, these executions are in two different
universes, separated by a Big Crunch and a Big Bang. Nothing that
happened in one execution (aside from modifying persistent storage
like a file system) affects what happens in the other. When the
second program runs, the Collector class is loaded anew -- it is
in this sense a "different" Collector class -- and the singleton
that existed in the first program is long gone. The second program
will then create a new singleton Collector.

If you need a singleton that persists across different JVM
instances, you'll need to work harder. It's doable (I think; I
haven't done it myself), but takes you into the arena of object
serialization and of debates about what "the same" means across
what amounts to a reboot.

By the way, you can visit http://www.collector.org/ to learn
that there's an organization out there who might distribute Java
code of their own. If they do, their package names will begin
with org.collector, and there will be confusion and perhaps bad
consequences if someone tries to use your code and their code in
the same program. Unless you're part of collector.org, you should
probably choose another package name.
 
U

unlikeablePorpoise

(Please position a reply after the message you're replying
to, or interspersed with it for a point-by-point reply.
Backward things read to harder it's.)

















With the code as you've shown it, I don't understand how
the behavior you report can occur. Is the Collector class
truly as lightweight as shown? Or have you deleted other bits
of code for brevity's sake? That's usually a good idea, but
you may have omitted something important -- for instance, a
method that accesses `ref' while synchronizing on something
other than Collector.class, or not synchronizing at all.

As for the interaction of package membership and singletons:
There is none. The package forms part of the complete name of
a class (it's org.collector.Collector, not just Collector), and
package membership affects the reach of some access levels (but
not public and not private). Package membership has nothing to
do with whether `ref' is or isn't null, nor with what the method
synchronizes on, nor with how many times the constructor is used.

Perhaps the secret lies in how you call the method "twice in
two different classes:" if you run one class' main method and let
the program finish, and then run the other class' main method and
let its program finish, these executions are in two different
universes, separated by a Big Crunch and a Big Bang. Nothing that
happened in one execution (aside from modifying persistent storage
like a file system) affects what happens in the other. When the
second program runs, the Collector class is loaded anew -- it is
in this sense a "different" Collector class -- and the singleton
that existed in the first program is long gone. The second program
will then create a new singleton Collector.

If you need a singleton that persists across different JVM
instances, you'll need to work harder. It's doable (I think; I
haven't done it myself), but takes you into the arena of object
serialization and of debates about what "the same" means across
what amounts to a reboot.

By the way, you can visithttp://www.collector.org/to learn
that there's an organization out there who might distribute Java
code of their own. If they do, their package names will begin
with org.collector, and there will be confusion and perhaps bad
consequences if someone tries to use your code and their code in
the same program. Unless you're part of collector.org, you should
probably choose another package name.

I think you are right. I am attempting this in two different main()
methods. Damn.

Thanks,
Sarah
 
D

Daniel Pitts

I think you are right. I am attempting this in two different main()
methods. Damn.

Thanks,
Sarah

So, you mean you want a piece of datum that can persist between
execution of your program, and even different programs...

If you want multiple classes to be able access this object (I'll call
these classes Clients) concurrently, then perhaps the state of this
object should be maintained in a its own class (I'll call this the
Server). The Clients will connect to the Server, probably through
Sockets, Possibly using RMI or some other remoting protocol, and ask
the server to manipulate and report on the state of your "singleton".

If, however, all you need is that the state of your "singleton" be
maintained across multiple runs (that never ever overlap), then you
want to persist your "singleton" to either a disk, database, or some
other persistence technology.

If you really only care about the current execution, then just using
the standard "Singleton" pattern may be good enough, although I would
suggest using the Dependency Injection pattern instead where possible/
feasible.
 
T

Theme

package org.collector;

public class Collector{

private Collector() {}

private static Collector ref;

public static synchronized Collector getCollectorObject()
{
if(ref == null)
{
System.out.println("ref is null");
ref = new Collector();
}
else
{
System.out.println("ref exists");
}

return ref;
}

}

When I call 'Collector col = Collector.getCollectorObject();' twice in
two different classes, it returns "ref is null". However, if I do this
twice in the same class method, ie

Collector col = Collector.getCollectorObject();
Collector col2 = Collector.getCollectorObject();

I get the expected result:

"ref is null"
"ref exists"

IMHO it's ok, since it ptints to System.out message from block with
lazy initialization,
it does not return null, does it?

private Collector() {}
private static Collector ref;

public static synchronized Collector getCollectorObject()
{
if(ref == null)
{
System.out.println("lazy initialization!
here, IMHO static will be better...");
ref = new Collector();
}
else
{
System.out.println("ref exists");
}

return ref;//does not return null object in any case!
}
(first time will print to System.out "lazy initialization! here...")
And yes, removing lazy initialization will make class more concurrent-
compatible.

Good Luck, Theme
 

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,776
Messages
2,569,603
Members
45,197
Latest member
ScottChare

Latest Threads

Top