简体   繁体   中英

Why is making variables public visibility a bad practice

I am in a Introduction to Java class and I was doing a bit of research on variables. It seems that knowledgeable programers state that it is bad practice to define the variables in public visibility. I see them stating it is bad practice but I can not find a rhyme or reason to their claims. This is how I defined my variables in a application for my course.

public class DykhoffWk3Calculator 
    {
        /*
        * This class is used to define the variables in a static form so all 
        * classes can access them.
        */
        public static double commissionRate = .03, startSalary = 45000,
                accelerationFactor = 1.25; 
        public static double annualSales, commissionTotal, totalCompensation,
                total, count, count2;
        private static Object input; Object keyboard;

public static class UserInput
    { //Then continue with my other classes

I thought this was a logical method of defining them so all classes, not just main, could access them. Can someone explain to me why this is bad practice, and where variables should be defined? Any assistance would be greatly appreciated.

In short: because all of your public "surface area" for a class effectively defines its API.

If you expose things through methods, then you can change the details of how they work later. But if you expose a field, and some other class outside of your control (and quite possibly outside of your knowledge) starts referencing that field, then you're stuck with exposing that field for the rest of time. Or until you decide to break backwards-compatibility.

I thought this was a logical method of defining them so all classes, not just main, could access them.

As a general rule, you don't want "all classes" to access them. The vast majority of work with software, is spent maintaining code, not writing it for the first time. And so experienced developers realise that best practices for code, are generally the ones that make it most maintainable, not necessarily the ones that make it most convenient to write in the first place.

And if you have a variable that could be accessed from anywhere, at any time, and you want to make some tweaks to how it is modified - how can you be sure that this is safe? How long will it take you to track down all the ways that this is referenced, and determine what the effects of your change will be? (And specific to public fields, you can kiss goodbye to any sort of reusability regarding running at the same time from multiple threads, or running reentrantly.)

Broadly speaking, reducing the "surface area" of classes is a really good thing to do. Restricting the ways that other classes can interact with this one, makes it much easier to control and understand the relationships, as well as making it easier to make internal changes "invisible" to those other classes. Think about what this class does , what it will provide to other classes, as defining an interface (whether an actual interface or not). And only expose to other classes, the bare minimum that is required to fulfil those requirements.

And that never involves letting them have arbitrary access to variables.

So the general point is that you in fact DON'T want anyone to be able to access those values. Not only can I see those variables, but I can also change them to anything I like. This can lead to problems in larger, more complex programs.

Furthermore, if you wanted to later change how the class uses/stores these values, you couldn't without having to go out and change all the other classes that access those public variables directly. Instead, you should offer methods that provide just the amount of access that you want to give.

The standard analogy is that of driving a car. You know how to turn the wheel, hit the brake, etc, but not how the car actually does these things. So if the engine needed to be dramatically changed, or you got in a new car, then you'd still know how to drive. You don't need to worry about what's happening behind the scenes.

Public variables in general in a class are a bad idea. Since this means other classes/programs, can modify the state of instances.

Since it is the responsibility of a class to protect its state and ensure the state is "consistent", one can enforce this by defining public setters (since this allows to run code to check/repair state).

By setting the variables public, the state is not protected. If later not all representable states are valid states, one has a problem.

Example :

Say you want to implement an ArrayList<T> , then it will look like (not fully implemented):

public class ArrayList<T> {

    public int size = 0;
    public Object[] data = new Object[5];

}

Now one can modify the size of the arrayList. Without adding an element. Now if you would ask the ArrayList<T> instance to remove/add/copy/...whatever, the data on which it works can be wrong.

Perhaps you can claim that a programmer is nice: he will not modify the object unless he needs to and according to the "rules". But such things eventually always go wrong, and what if you decide to modify your definition of the ArrayList (for instance using two int 's for the size ). In that case you would need to rewrite all code that sets such fields.

To conclude: private / protected is invented to protect a class instance from other instances that would turn the instance corrupt/invalid/inconsistent/...

Firstly you state it wrong.

its bad to make your variable public ie: public String name = null; this is bad. You should always do it as private String name = null;

To understand why, you need to dig a bit into the ideology of OOPs OPPS ideology states that each object of your class will have 2 things:

  • Properties: something which we also call variables or state.
  • Behavior: something which we call methods or functions.

Properties identify the object over a period of time. Behaviors allow you to manage the properties of the object so that the same object over time can appear to be in different states.eg: a Product object over a period of can be an 'Available line item' or 'Added to cart' or 'Sold' or 'Out of stock' depending on its state. Since state is critically important to the object so the object should not allow direct nonsense mutation operations on its state. Objects should keep their variables private to them and expose behaviors that the outside world can use to interact with the object and change the state based on the operation executed in the behavior. eg: calling the 'addToCart()' behavior on the Product object that was in 'Available line item' state would probably mean: changing not just its state to 'Added to cart' but probably making other users aware that the number of this Products now available is 1 less.

So long story short: don't expose properties directly to outside work for mutation unless needed. This means dont make them public and also dont give setter methods if not needed.

根据约定字段,在Java程序中的任何类都可以看到在公共类中被声明为public(最不严格)的方法和构造函数,无论这些类在同一个包中还是在另一个包中,这意味着a值的变化字段肯定会影响其他访问该字段的类。从而破坏了整个封装的含义。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM