JavaFX: Let’s clarify public-read and public-init

Coming from the Java world, most access modifiers in JavaFX make sense to me as they have equivalents in Java (although the syntax is slightly changed). What isn’t in Java are the two access modifiers public-read and public-init, and at least to me, it is not immediately clear what these modifiers do.

It turns out that public-read means pretty much just that – that the variable can be publicly read from anywhere, but that it can only be written to within the script which declares it. It is possible to ‘widen’ the write-access by prepending either package or protected before the public-read, but this has no effect on the read-access, which remains at publicly accessible.

The public-init access modifier defines a variable that can be publicly initialized in any package. Subsequent write access, however, is controlled in the same manner as public-read, as detailed above. Because of this, the value of this variable is always readable from any package.

So, in summary, when you see anything declared public-*, you should think that the variable can always be publicly read, but it has limitations on being written to. The ability to write to the variable is only available to code within the same script as the variable, unless it has been modified with package or protected access.

For further information and examples, check out the JavaFX Language Tutorial, particularly the section on access modifiers.

6 thoughts on “JavaFX: Let’s clarify public-read and public-init”

    1. We went through many different iterations and ideas. One day Robert Field and Brian Goetz whiteboarded all the different usage scenarios and found that pretty well all the different use cases we had could be boiled down to normal access modifiers and these two new ones.

      From an API perspective, what we needed was the ability to make variables “read only” to the world, but allow us ourselves (the API developer) to update the variable. This is the equivalent of:

      public String getFoo() { … }
      private void setFoo(String s) { … }

      But with the option of specifying a different value than “private” for the setter. So:

      public-read protected foo:String

      is

      public String getFoo() { … }
      protected void setFoo() { … }

      One use case that we didn’t expose is the write-only use case:

      private String getFoo() { … }
      public void setFoo(String s) { … }

      Seemed of dubious usage.

      public-init has a very specific usage in JavaFX. Because we don’t have constructors, we needed some way to allow initialization of variables but thereafter not allow them to be changed. This is important for immutable classes for example. So that’s what we got public-init for.

    1. Just a different approach I guess. Through public-init variable declarations and init {..} and postinit {…} blocks you get effectively the same thing as you do with a constructor.

      Some might say it’s change for the sake of change, others will argue that it is a simpler approach. I think what is missing in general is a mapping for Java developers to understand how they move to JavaFX. Most things are obvious, but areas such as this result in confusion.

      I’m trying to blog about things which don’t have an obvious mapping from the Java world. If you have anything you’d like me to try and blog about, let me know.

      btw, thanks to Richard for such a good reply above. It’s much appreciated and it’s great to see you sharing your knowledge from your work on JavaFX.

  1. Pingback: Gooder Code
  2. Poor naming convention used here.
    It is very confusing. Naming should be self explanatory. And it should not be hidden. Here in this case write access is hidden.

    package public-read

    Common sense interpretation tells me that the only package has read access. Unless you remember the write access.

    package public-init

    This one I can interpret as it has only package level public-init access.

    package-write public-read is more meaning full than “package public-read”

    package-write public-init.

Leave a Reply