Can I use public fields in Java?

The question in the title is a bit generalized, and many other similar questions have already been answered, so I understand the big picture. Basically, using a public field in a Java class creates a dependency on the implementation details of that class, resulting in poor software quality.

With this in mind, I still get the feeling that I can use them somehow. To explain this, I'll use an example: with the upcoming Java 8 functional interfaces, I can finally use the event model I like, which is similar to how events are handled in C #.

The event model is implemented in a package that is intended to be used as a third party API in all of my projects. These are the main classes:

EventArgs.java

public class EventArgs implements Serializable {
}

      

EventHandler.java

@FunctionalInterface
public interface EventHandler<T extends EventArgs> {
    void fire(Object sender, T args);
}

      

Event.java

public class Event<T extends EventArgs> {

    private final Set<EventHandler<T>> handlers = new LinkedHashSet<>();

    public void addEventHandler(EventHandler<T> handler) {
        handlers.add(handler);
    }

    public void removeEventHandler(EventHandler<T> handler) {
        handlers.remove(handler);
    }

    public void fire(Object sender, T args) {
        for (EventHandler<T> e : handlers) {
            e.fire(sender, args);
        }
    }
}

      

What I usually like to do in my classes that want to fire events is something like this:

public class SomeClass {

    public final Event<SomeEventArgs> someEvent = new Event<>();

    public void someMethod() {
         // ...
         someEvent.fire();
    }
}

      

and in classes that want to subscribe to the event:

public class SomeOtherClass {
    private SomeClass someInstance;

    public SomeOtherClass() {
        someInstance = new SomeClass();
        someInstance.someEvent.addEventHandler(this::someEventHandler);
    }

    private void someEventHandler(Object sender, SomeEventArgs args) {
         // do some stuff ...
    }
}

      

This seems fine to me because I am not disclosing any implementation details, in fact this event is part of the class interface. Am I completely wrong? Shoud Am I still using a getter to interact with the event?

Another example I can think of is a log that is used in the classroom but can be set externally to get a certain level of detail.

So, to expand on the question, can a public modifier be used if the field is a third party component that can be accessed to achieve a specific behavior?

+3


source to share


2 answers


There is a reason why you can declare fields public, but beyond simple transport objects like a 2D point ... declaring a public field can lead to unexpected results.

Let's take a look at SomeClass

and continue it in SomeChildClass

and out SomeGrandChildClass

like this:

public class SomeChildClass extends SomeClass {

    public SomeChildClass() {
         super();
         someEvent.addEventHandler(...);
    }
}

      

and



public class SomeGrandChildClass extends SomeChildClass  {

    public SomeGrandChildClass() {
         super();
         // Lets say FilteredEvent will ensure a Event will only be fired if a condition holds
         someEvent = new FilteredEvent();
    }
}

      

So what happened? We are just lost EventHandler

due to the sequence of calls between super constructors and constructors. I can think of various situations where it seems like a good idea to replace a specific Event

with a specific implementation from the outside (since the field is public). You can of course use public final

to prevent reassignment, but again you lose the ability to override behavior in subclasses as well.

Thus, Event

the class of the class, but the implementation addSomeHandler

- and removeSomeHandler

-methods ensures that subclasses can use another event management and involve parents, students, if they are also using the override.

Another example would be changing the Event

-handling mechanism . If you implement these short methods, you can instantly wrap old style handlers, assign them additional Event

s, ...

0


source


Yes, in principle there is nothing wrong with Java having public or more informal fields. It is supported by the Java language, and use cases are of course used for them. Having said that, I personally only use them in non-public, often nested helper classes. In classes to be used outside of their packages, I want to check property values ​​or prevent the user from modifying instances of a class, I want to wrap collections in non-modifiable views, replace default values ​​for null values, etc. And when I don't want it now, I usually want to be able to add them later without having to parse a lot of code. So I would say no, non-private fields have no place in classes belonging to the general interface of the package.



In your specific case, for me, an event is an object that encapsulates information about one specific event, like one key press or one mouse click, etc. Therefore, I find it odd to store event listeners in the event object itself, as this means that event listeners must be added every time an event occurs. For me, an event is a key example of a class that should probably be unmodified. The presence of public fields immediately makes the class instance modifiable, so in the event object, I would especially recommend public fields.

0


source







All Articles