a question related to "final static" field variable

Discussion in 'Java' started by www, May 4, 2007.

  1. www

    www Guest

    Hi,

    I want to have a static field variable. I want to initiate it once and
    don't want it to be changed any more. So

    public MyClass
    {
    public final static rootDir; //error: saying rootDir may not be
    initialized

    public MyClass(String dir)
    {
    rootDir =dir; //error: saying that I cannot assign to a final variable
    }

    ...

    public void doIt()
    {
    ...
    }

    public static void main(String[] args)
    {
    String str = args[0];
    MyClass class = new MyClass(str);

    }
    }

    I thought final variable can be assigned value once and only once. And
    this can be done inside constructor. Cited from this web page:
    http://renaud.waldura.com/doc/java/final-keyword.shtml in Final Field part.

    Thank you for your help.
     
    www, May 4, 2007
    #1
    1. Advertising

  2. www wrote:
    > Hi,
    >
    > I want to have a static field variable. I want to initiate it once and
    > don't want it to be changed any more. So
    >
    > public MyClass
    > {
    > public final static rootDir; //error: saying rootDir may not be
    > initialized
    >
    > public MyClass(String dir)
    > {
    > rootDir =dir; //error: saying that I cannot assign to a final
    > variable
    > }
    >
    > ...
    >
    > public void doIt()
    > {
    > ...
    > }
    >
    > public static void main(String[] args)
    > {
    > String str = args[0];
    > MyClass class = new MyClass(str);
    >
    > }
    > }
    >
    > I thought final variable can be assigned value once and only once. And
    > this can be done inside constructor. Cited from this web page:
    > http://renaud.waldura.com/doc/java/final-keyword.shtml in Final Field part.
    >
    > Thank you for your help.


    Unfortunately not if it is also static.

    --

    Knute Johnson
    email s/nospam/knute/
     
    Knute Johnson, May 4, 2007
    #2
    1. Advertising

  3. www

    visionset Guest

    "www" <> wrote in message
    news:f1ftq1$co1$...

    > I want to have a static field variable. I want to initiate it once and
    > don't want it to be changed any more. So
    >
    > public MyClass
    > {
    > public final static rootDir; //error: saying rootDir may not be
    > initialized
    >...
    > I thought final variable can be assigned value once and only once. And
    > this can be done inside constructor. Cited from this web page:
    > http://renaud.waldura.com/doc/java/final-keyword.shtml in Final Field
    > part.
    >
    > Thank you for your help.


    The problem is that the rootDir reference may be accessed before the
    constructor is called since it is static.
    The obvious value for it to hold would be null, so you therefore would not
    be able to reasign in your constructor. Because of this the compiler forces
    you to assign at the point of declaration.

    --
    Mike W
     
    visionset, May 4, 2007
    #3
  4. www

    Sanjay Guest


    > I thought final variable can be assigned value once and only once. And


    It is a static variable and has nothing to do with the object of that
    class. It get its value when classloader loads the class. What you are
    trying to do is, not assigning value to 'rootDir' at all and then are
    trying to change it in the contructor, hence the error.

    > this can be done inside constructor. Cited from this web page:
    > http://renaud.waldura.com/doc/java/final-keyword.shtml in Final Field

    part.

    I am not sure what that web page says, but there is a subtle difference
    between final and final static variable. May be you want to read this

    http://java.sun.com/docs/books/tutorial/java/javaOO/classvars.html
     
    Sanjay, May 4, 2007
    #4
  5. www

    www Guest

    Thank you all. I have realized I was wrong. But, to achieve my purpose,
    do you have any suggestions?

    Thank you.
     
    www, May 4, 2007
    #5
  6. www

    Roman Guest

    www pisze:
    > Hi,
    >
    > I want to have a static field variable. I want to initiate it once and
    > don't want it to be changed any more. So
    >
    > public MyClass
    > {
    > public final static rootDir; //error: saying rootDir may not be
    > initialized
    >
    > public MyClass(String dir)
    > {
    > rootDir =dir; //error: saying that I cannot assign to a final
    > variable
    > }
    >
    > ...
    >
    > public void doIt()
    > {
    > ...
    > }
    >
    > public static void main(String[] args)
    > {
    > String str = args[0];
    > MyClass class = new MyClass(str);
    >
    > }
    > }
    >
    > I thought final variable can be assigned value once and only once. And
    > this can be done inside constructor. Cited from this web page:
    > http://renaud.waldura.com/doc/java/final-keyword.shtml in Final Field
    > part.
    >
    > Thank you for your help.

    you cannot assign value to final variable in an any method (even
    constructors). You have to decide: final or assigne value during
    declaration.
    Regards,
    Roman
     
    Roman, May 4, 2007
    #6
  7. www wrote:
    > Thank you all. I have realized I was wrong. But, to achieve my purpose,
    > do you have any suggestions?
    >
    > Thank you.


    Make rootDir private and change it only once inside the class, from main.

    If other classes need access you can provide a getRootDir() method,
    which can check for attempts to read it before it has been set.

    Patricia
     
    Patricia Shanahan, May 4, 2007
    #7
  8. www

    Tom Hawtin Guest

    www wrote:
    >
    > I want to have a static field variable. I want to initiate it once and
    > don't want it to be changed any more. So


    > public final static rootDir; //error: saying rootDir may not be

    ^String
    > initialized


    > public static void main(String[] args)
    > {
    > String str = args[0];
    > MyClass class = new MyClass(str);


    It doesn't really make sense for this kind of variable to be static. Any
    code that uses the variable, directly or indirectly, is specifying the
    interpretation of class loader scope. Stick with instance variables, and
    keep dependencies as narrow as possible.

    Use static fields judiciously. They are good for constants[1], really
    difficult for caches and hopeless for practically anything else.

    Tom Hawtin

    [1] Constants as in things that cannot change, not just as in the JLS
    "compile-time constant".
     
    Tom Hawtin, May 4, 2007
    #8
  9. www

    visionset Guest

    "Roman" <> wrote in message
    news:f1g0k5$c8a$...

    >> I thought final variable can be assigned value once and only once. And
    >> this can be done inside constructor. Cited from this web page:
    >> http://renaud.waldura.com/doc/java/final-keyword.shtml in Final Field
    >> part.
    >>


    > you cannot assign value to final variable in an any method (even
    > constructors). You have to decide: final or assigne value during
    > declaration.


    That is not true, a final instance variable (attribute) can be assigned
    inline or in the constructor.

    --
    Mike W
     
    visionset, May 4, 2007
    #9
  10. www

    www Guest

    Patricia Shanahan wrote:

    >
    > Make rootDir private and change it only once inside the class, from main.
    >
    > If other classes need access you can provide a getRootDir() method,
    > which can check for attempts to read it before it has been set.
    >
    > Patricia


    Suppose my program has about 20 classes and the class with main method
    is MyClass provided in my original posting. Suppose one class
    "Worker.java" needs to know the root directory in order to read in the
    text file. Right now, Worker does NOT have a MyClass in it. But, if I
    follow your method, I need:
    <inside Worker.java>
    MyClass class = new MyClass();
    String rootDir = class.getRootDir();
    ....//append rootDir in the front of text file name

    </inside Worker.java>

    I feel it is kind of silly that in order to get to know what the root
    directory it is, Worker is forced to have a MyClass in it.
     
    www, May 4, 2007
    #10
  11. www wrote:
    > Patricia Shanahan wrote:
    >
    >>
    >> Make rootDir private and change it only once inside the class, from main.
    >>
    >> If other classes need access you can provide a getRootDir() method,
    >> which can check for attempts to read it before it has been set.
    >>
    >> Patricia

    >
    >
    > Suppose my program has about 20 classes and the class with main method
    > is MyClass provided in my original posting. Suppose one class
    > "Worker.java" needs to know the root directory in order to read in the
    > text file. Right now, Worker does NOT have a MyClass in it. But, if I
    > follow your method, I need:
    > <inside Worker.java>
    > MyClass class = new MyClass();
    > String rootDir = class.getRootDir();
    > ...//append rootDir in the front of text file name
    >
    > </inside Worker.java>
    >
    > I feel it is kind of silly that in order to get to know what the root
    > directory it is, Worker is forced to have a MyClass in it.


    Huh? There is no more need to create an object to call a static method
    than there is to access a static field. If Worker could have accessed
    MyClass.rootDir, it could call MyClass.getRootDir().

    Whether the root directory attribute should be a static attribute of the
    MyClass class is arguable, but is orthogonal to the question of whether
    it should be accessed as a variable or through an access method.

    Patricia
     
    Patricia Shanahan, May 4, 2007
    #11
  12. www

    Eric Sosman Guest

    www wrote On 05/04/07 16:06,:
    > Patricia Shanahan wrote:
    >
    >
    >>Make rootDir private and change it only once inside the class, from main.
    >>
    >>If other classes need access you can provide a getRootDir() method,
    >>which can check for attempts to read it before it has been set.
    >>
    >>Patricia

    >
    >
    > Suppose my program has about 20 classes and the class with main method
    > is MyClass provided in my original posting. Suppose one class
    > "Worker.java" needs to know the root directory in order to read in the
    > text file. Right now, Worker does NOT have a MyClass in it. But, if I
    > follow your method, I need:
    > <inside Worker.java>
    > MyClass class = new MyClass();
    > String rootDir = class.getRootDir();
    > ...//append rootDir in the front of text file name
    >
    > </inside Worker.java>
    >
    > I feel it is kind of silly that in order to get to know what the root
    > directory it is, Worker is forced to have a MyClass in it.


    In the class as you wrote it, the only way MyClass
    discovers where rootDir is supposed to be is by having
    somebody, somewhere, create a MyClass object and pass
    the value in as an argument to the constructor. If you
    never construct a MyClass, nobody ever tells a constructor
    what rootDir should be. What should MyClass do? Just
    make something up out of thin air?

    I'm not 100% sure what you're trying to do, but if
    the idea is for MyClass to "remember" the first rootDir
    from the construction of the first MyClass instance,
    then you can't use a static final. Why? Because the
    static field belongs to the class and not to the instance,
    and must be initialized when the class is loaded and not
    later on when instances are (or aren't) constructed.

    What you might want to do instead is use a private
    static variable and an accessor method, something like:

    public class MyClass {

    private static String rootDir;

    public MyClass(String dir) {
    if (rootDir == null) {
    // first instance: initialize
    rootDir = dir;
    }
    }

    public string getRootDir() {
    if (rootDir == null) {
    // optional: could just return null
    throw new IllegalStateException(...);
    }
    return rootDir;
    }
    }

    --
     
    Eric Sosman, May 4, 2007
    #12
  13. www wrote:
    > Patricia Shanahan wrote:
    >
    >>
    >> Make rootDir private and change it only once inside the class, from main.
    >>
    >> If other classes need access you can provide a getRootDir() method,
    >> which can check for attempts to read it before it has been set.
    >>
    >> Patricia

    >
    > Suppose my program has about 20 classes and the class with main method
    > is MyClass provided in my original posting. Suppose one class
    > "Worker.java" needs to know the root directory in order to read in the
    > text file. Right now, Worker does NOT have a MyClass in it. But, if I
    > follow your method, I need:
    > <inside Worker.java>
    > MyClass class = new MyClass();
    > String rootDir = class.getRootDir();
    > ...//append rootDir in the front of text file name
    >
    > </inside Worker.java>
    >
    > I feel it is kind of silly that in order to get to know what the root
    > directory it is, Worker is forced to have a MyClass in it.


    There are several ways to get your variable to other classes, such as
    pass them in arguments or use a singleton. In the end it is probably
    going to be easiest to have a static variable that is visible to your
    other classes. People are going to shudder though so just don't tell
    them that you are doing that.

    --

    Knute Johnson
    email s/nospam/knute/
     
    Knute Johnson, May 4, 2007
    #13
  14. www

    Eric Sosman Guest

    Eric Sosman wrote On 05/04/07 17:08,:
    > www wrote On 05/04/07 16:06,:
    >
    >>Patricia Shanahan wrote:
    >>
    >>
    >>
    >>>Make rootDir private and change it only once inside the class, from main.
    >>>
    >>>If other classes need access you can provide a getRootDir() method,
    >>>which can check for attempts to read it before it has been set.
    >>>
    >>>Patricia

    >>
    >>
    >>Suppose my program has about 20 classes and the class with main method
    >>is MyClass provided in my original posting. Suppose one class
    >>"Worker.java" needs to know the root directory in order to read in the
    >>text file. Right now, Worker does NOT have a MyClass in it. But, if I
    >>follow your method, I need:
    >><inside Worker.java>
    >>MyClass class = new MyClass();
    >>String rootDir = class.getRootDir();
    >>...//append rootDir in the front of text file name
    >>
    >></inside Worker.java>
    >>
    >>I feel it is kind of silly that in order to get to know what the root
    >>directory it is, Worker is forced to have a MyClass in it.

    >
    >
    > In the class as you wrote it, the only way MyClass
    > discovers where rootDir is supposed to be is by having
    > somebody, somewhere, create a MyClass object and pass
    > the value in as an argument to the constructor. If you
    > never construct a MyClass, nobody ever tells a constructor
    > what rootDir should be. What should MyClass do? Just
    > make something up out of thin air?
    >
    > I'm not 100% sure what you're trying to do, but if
    > the idea is for MyClass to "remember" the first rootDir
    > from the construction of the first MyClass instance,
    > then you can't use a static final. Why? Because the
    > static field belongs to the class and not to the instance,
    > and must be initialized when the class is loaded and not
    > later on when instances are (or aren't) constructed.
    >
    > What you might want to do instead is use a private
    > static variable and an accessor method, something like:
    >
    > public class MyClass {
    >
    > private static String rootDir;
    >
    > public MyClass(String dir) {
    > if (rootDir == null) {
    > // first instance: initialize
    > rootDir = dir;
    > }
    > }
    >
    > public string getRootDir() {
    > if (rootDir == null) {
    > // optional: could just return null
    > throw new IllegalStateException(...);
    > }
    > return rootDir;
    > }
    > }


    Drat. Make that `public static String getRootDir()',
    adding `static' and changing `string' to `String', and
    the weekend had better come soon ...

    --
     
    Eric Sosman, May 4, 2007
    #14
  15. www wrote:
    > I want to have a static field variable. I want to initiate it once and
    > don't want it to be changed any more. So
    >
    > public MyClass
    > {
    > public final static rootDir; //error: saying rootDir may not be
    > initialized
    >
    > public MyClass(String dir)
    > {
    > rootDir =dir; //error: saying that I cannot assign to a final
    > variable
    > }
    >
    > ...
    >
    > public void doIt()
    > {
    > ...
    > }
    >
    > public static void main(String[] args)
    > {
    > String str = args[0];
    > MyClass class = new MyClass(str);
    >
    > }
    > }
    >
    > I thought final variable can be assigned value once and only once. And
    > this can be done inside constructor. Cited from this web page:
    > http://renaud.waldura.com/doc/java/final-keyword.shtml in Final Field part.


    As other have already stated then the whole construct is not good.

    But to complete the understanding of final and initialization, then
    the following compiles:

    public class FinalDemo {
    public final static String s1;
    public final String s2;
    static {
    s1 = "A";
    }
    public FinalDemo()
    {
    s2 = "B";
    }
    }

    final static can be initialized in "static constructor" and
    final non-static can be initialized in constructor.

    Which I think makes sense.

    Arne
     
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=, May 5, 2007
    #15
  16. www

    Mark Space Guest

    www wrote:

    > I feel it is kind of silly that in order to get to know what the root
    > directory it is, Worker is forced to have a MyClass in it.


    I think I see what you are trying to say. If I understand, you don't
    like the fact that there is some dependency that the worker thread knows
    about the MyClass class. I think one way to fix this is to use what is
    sometimes called a Strategy Pattern or Dependency Injection. Rather
    than have Worker know about MyClass, you inject the information into
    Worker, thus breaking the dependency.

    In plain English, I think Worker needs to know about the context in
    which it's running, so let's call this dependency a "context"

    public class Worker {
    private Context localCntxt;

    public Worker( Context c ) {
    localCntxt = c;
    }
    public void doStuff() {
    //...
    String rootDir = localCntxt.getRootDir();
    //...
    }
    }

    Now just make MyClass a type of Context object:

    public class Context { // used to be type MyClass
    private String rootDir;
    public void setRootDir( String s ) {
    rootDir = s;
    }
    public String getRootDir() {
    return rootDir;
    }
    }

    Feel free to stuff Context full of every sort of variable that your
    classes might ever need.

    Now you can easily make lots of workers all running in the same context,
    or even different contexts.

    public class Main {
    public void main( String [] args ) {
    Context a = new Context();
    Context b = new Context();
    Context c = new Context();

    a.setRootDir( "/" );
    b.setRootDir( "/Users/Mark/pub" );
    c.setRootDir( "/argle/bargle/blet/foo/bar" );

    Worker w1 = new Worker( a ); // Three workers all
    Worker w2 = new Worker( a ); // running in the same
    Worker w3 = new Worker( a ); // Context
    Worker w4 = new Worker( b ); // A Different Context b
    Worker w5 = new Worker( c ); // And Context c
    }
    }

    I hope this made some sense to you.
     
    Mark Space, May 5, 2007
    #16
  17. Mark Space wrote:
    > www wrote:
    >
    >> I feel it is kind of silly that in order to get to know what the root
    >> directory it is, Worker is forced to have a MyClass in it.

    >
    > I think I see what you are trying to say. If I understand, you don't
    > like the fact that there is some dependency that the worker thread knows
    > about the MyClass class. I think one way to fix this is to use what is
    > sometimes called a Strategy Pattern or Dependency Injection. Rather
    > than have Worker know about MyClass, you inject the information into
    > Worker, thus breaking the dependency.


    This sort of approach is certainly something to keep in mind, in case
    the situation gets sufficiently complicated to warrant it. I might do it
    that way from the start if this were a public interface that cannot be
    changed in the future.

    However, if the root directory is the only thing that needs this sort of
    handling, and the code can be refactored later if it looks like a good
    idea, I would give this the KISS treatment.

    To do what seems to be the end objective, static access to the args[0]
    from the main call:

    public class MyClass {
    private static String rootDir;

    public static String getRootDir() {
    // Optionally test for null and throw exception
    return rootDir;
    }

    public static void main(String[] args) {
    rootDir = args[0];
    }
    }

    A worker can call MyClass.getRootDir() to get the root directory name.
    Short of nasty reflection abuse, a worker cannot modify rootDir.

    Patricia
     
    Patricia Shanahan, May 5, 2007
    #17
  18. www

    Mark Space Guest

    Patricia Shanahan wrote:

    > However, if the root directory is the only thing that needs this sort of
    > handling, and the code can be refactored later if it looks like a good
    > idea, I would give this the KISS treatment.


    I see what you are saying, and it's quite good. However, the OP himself
    raised the objection, so I thought I'd pop up with a possible solution.
    The program he's working on may in fact be rather complicated; we may
    have only seen a short example here on the news group. Or he may be
    trying to learn better techniques, so the added complexity would be
    useful for the example it provides. (Not that I think my example is all
    that great.) Besides, the dependency injection style is often much
    easier to break down for unit testing.
     
    Mark Space, May 6, 2007
    #18
  19. Patricia Shanahan wrote:
    > Mark Space wrote:
    >> www wrote:
    >>
    >>> I feel it is kind of silly that in order to get to know what the root
    >>> directory it is, Worker is forced to have a MyClass in it.

    >>
    >> I think I see what you are trying to say. If I understand, you don't
    >> like the fact that there is some dependency that the worker thread
    >> knows about the MyClass class. I think one way to fix this is to use
    >> what is sometimes called a Strategy Pattern or Dependency Injection.
    >> Rather than have Worker know about MyClass, you inject the information
    >> into Worker, thus breaking the dependency.

    >
    > This sort of approach is certainly something to keep in mind, in case
    > the situation gets sufficiently complicated to warrant it. I might do it
    > that way from the start if this were a public interface that cannot be
    > changed in the future.
    >
    > However, if the root directory is the only thing that needs this sort of
    > handling, and the code can be refactored later if it looks like a good
    > idea, I would give this the KISS treatment.
    >
    > To do what seems to be the end objective, static access to the args[0]
    > from the main call:
    >
    > public class MyClass {
    > private static String rootDir;
    >
    > public static String getRootDir() {
    > // Optionally test for null and throw exception
    > return rootDir;
    > }
    >
    > public static void main(String[] args) {
    > rootDir = args[0];
    > }
    > }
    >
    > A worker can call MyClass.getRootDir() to get the root directory name.
    > Short of nasty reflection abuse, a worker cannot modify rootDir.
    >
    > Patricia


    Access to rootDir needs synchronization if it is going to be accessed by
    multiple threads which is guaranteed to be the case here.

    --

    Knute Johnson
    email s/nospam/knute/
     
    Knute Johnson, May 6, 2007
    #19
  20. Arne Vajhøj wrote:
    > www wrote:
    >> I want to have a static field variable. I want to initiate it once and
    >> don't want it to be changed any more. So
    >>
    >> public MyClass
    >> {
    >> public final static rootDir; //error: saying rootDir may not be
    >> initialized
    >>
    >> public MyClass(String dir)
    >> {
    >> rootDir =dir; //error: saying that I cannot assign to a final
    >> variable
    >> }
    >>
    >> ...
    >>
    >> public void doIt()
    >> {
    >> ...
    >> }
    >>
    >> public static void main(String[] args)
    >> {
    >> String str = args[0];
    >> MyClass class = new MyClass(str);
    >>
    >> }
    >> }
    >>
    >> I thought final variable can be assigned value once and only once. And
    >> this can be done inside constructor. Cited from this web page:
    >> http://renaud.waldura.com/doc/java/final-keyword.shtml in Final Field
    >> part.

    >
    > As other have already stated then the whole construct is not good.
    >
    > But to complete the understanding of final and initialization, then
    > the following compiles:
    >
    > public class FinalDemo {
    > public final static String s1;
    > public final String s2;
    > static {
    > s1 = "A";
    > }
    > public FinalDemo()
    > {
    > s2 = "B";
    > }
    > }
    >
    > final static can be initialized in "static constructor" and
    > final non-static can be initialized in constructor.
    >
    > Which I think makes sense.
    >
    > Arne


    Arne:

    Is there any practical difference between;

    static final String s1 = "A";

    and

    static final String s1;
    static { s1 = "A" };

    Thanks,

    --

    Knute Johnson
    email s/nospam/knute/
     
    Knute Johnson, May 6, 2007
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JFCM
    Replies:
    4
    Views:
    5,780
  2. Maxwell Hammer
    Replies:
    7
    Views:
    669
    Peter Hansen
    Jun 18, 2005
  3. Dan

    supply final static value

    Dan, Mar 11, 2005, in forum: ASP .Net Web Services
    Replies:
    2
    Views:
    120
    Manohar Kamath
    Mar 11, 2005
  4. Sound
    Replies:
    2
    Views:
    499
    Randy Webb
    Sep 28, 2006
  5. jr
    Replies:
    3
    Views:
    497
Loading...

Share This Page