I have a philosophy of security question, something that has been on my mind for while and that I have never gotten a satisfactory answer to. I'm going to use JavaBean specification as an example but this is a general Java philosophy as far as I can tell.
The JavaBean spec, so I'm told, requires that variables be private but "The getter and setter methods [that access them] must be public so that anyone who uses the bean can invoke them." This is supposed to aid in security somehow but I'm not sure whats going on. If you can write code to manipulate a variable in another class that's public, I would think you can write code to call a variable manipulating method in another class that's public when the corresponding variable is private. How is this safer?
Its like locking your bike to the stop sign but waiting nearby so that you can undo the lock yourself for anyone who asks...
If you had code like this:
I could see that being safer but JavaBean spec states that getters take no arguments and setters have void return type.
It's not that it is safer in terms of better security, it is safer in terms of a less error prone operation. For example, when setting a birth date via a setter, a Person class might calculate the person's age and retirement date immediately upon doing so and set them as well as the date of birth. If a developer had direct access the birthDate field and set it, the Person's age and retirement date would be wrong.
Also, a setter and getter allows for some validation to occur (such as not setting a negative interest rate) where as direct access to the variable would not.
As for your example, you could accomplish the the same thing via an exception, and still conform to the Java Bean specification:
You could of course write a custom exception specific to the reason you can not set the variable.
p.s. even when something is marked private, it can be set using reflection. In the example below, the SomeBean class does not have a setter for the id field, and the id field is marked as private. Yet via reflection it can be changed:
Note that doing something like this in "real" code is risky. First off, it is very brittle. A developer could rename the 'id' field to some thing like 'identification' and that would break the reflection code unless it was also updated. Secondly, the 'id' field was marked private for a reason. It's like a chain link fence; I can still climb over it, but if I get attacked by the tiger on the other side, I have no one to blame but myself. There are times (such as in unit tests) where doing something like this might be useful. But one must always be aware of the risks.
Here though, it was just to demonstrate that even marking a field as private would not prevent a determined individual from being able to change it. So it doesn't really provide "security". Just safer operation.
Leroy J Brown
Joined: Dec 02, 2007
Kind of embarrassing that I just misunderstood what was meant by "secure." Had I seen reflection in action before as opposed to just hearing about it I would have known that I misunderstood something important rather than just suspecting I had poor instructors! Thanks very much for the replies.
Another key concept is to hide the implementation detals. Consider a US phone number. You can simply store it as a String. That works.
But a better implementation might want to validate that the length is either 7 or 10 digits, which is with and without the "area code" so if you are inside Washington DC, you could call the White House using 456-1414 (the seven digit number) but all over the country, you would call 202-456-1414
If you were writing an application in the TelCo space (a business that is a telephone company) they don't think of a phone number as a dataless key, rather it is made up of three fields, the Area code (202) the Exchange (physcial building with the switches) and the line. So the White House is in the 456 exchange, and the main switchboard line is 1414.
If you were writing this TelCo application, you probably would store the three fields separately, and add "getExchange()" and getAreaCode() functions. If the code exposed that the storage was a String, you would break everything. But with encapsulation, you can hide the implementation details.