Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I am completing Sun/Oracle's Trail (http://docs.oracle.com/javase/tutorial/java/TOC.html) and it keeps reiterating the importance of encapsulation.
How important, really, is encapsulation? I mean, if I may need to access the value of a given class field, why would I do so through a method when I could just access the field directly? Since the field would be accessed through its corresponding object anyway, where could this really go wrong?
Is it just for code extensibility purposes? In other words, because that way in the future if I decide I want to somehow alter or sanitize the field before returning it I can?
I'm more looking for an example or two than anything.
Validation.
If you don't use a method, you can't add any validation on the field unless you validate it at every place you want to access the field: unsustainable.
It also separates the data from your class from the outside world. By hiding the actual implementation of data behind methods, you can manipulate your data the way you want (now and in the future) and no other pieces of code will get broken. This allows you to change the way something is represented without a problem, as long as you make sure it can still be returned trough the existing method.
Encapsulation is not only a matter of making getter and setter for a field.
It's about:
Validation (and also consistency)
Hidding implementation (programming to an interface not an implementation)
Getters and setters don't have to reflect the acutal fields. There could be getters (and even setters) for fields which value is calculated on demand
Hide complexity: A getter/setter could peform something more complex than just setting a value
Advanced: Use of a diffrent implementation/modification; patterns like lazy loading which is used in ORM framework wouldn't work if you would use public fields
Even if you as you said "need to access the value of a given class field" you can't be sure that this requirement won't change (cause it will most time).
Actually, I think you're thinking about this the wrong way. The issue isn't encapsulation per se, it's decoupling the behavior of your objects from their data.
Fields are data -- they are part of the internal state of the object. Methods are part of the object's API. Objects shouldn't just be clusters of fields -- if your objects are just dumb collections of data, then that's not object-oriented programming, that's just structured programming.
Objects should be designed to represent real-world entities, and have methods that represent operations you could take on those real-world entities. To put it another way, you don't ask an object for its fields (e.g. getFoo(), getBar()) to pass those to other functions -- instead you should put the relevant operations (e.g. purchase(), validate(), etc.) as methods directly on the object.
That said, there's nothing wrong with having accessor methods -- sometimes you do need to actually retrieve the value. But by making those accessors methods instead of just exposing fields directly, you are implementing information hiding: users of your class don't need to know what the internal state looks like to be able to use it or get data from it.
Basically, in Java (or in any object-oriented language) classes are nouns, and methods are verbs. If you write classes that don't have any verbs, then you're programming in the kingdom of nouns.
Encapsulation allows your object to make guarantees (part of an object's contract), by giving the object control over its own data, which happens to make debugging considerably easier. Consider this class:
public class TravelRoute {
public int distance = 1000;
public int travelSpeed = 60;
public int calculateTravelTime() {
return distance / travelSpeed;
}
}
Any other code is free to set travelSpeed to zero, which will cause all future calls to the calculateTravelTime method to fail. Worse, you will have no way to know who set it to zero, so debugging the problem is going to take a long time.
However, with encapsulation, the class has total control over the value, and can guarantee that it is always valid:
public class TravelRoute {
private int distance = 1000;
private int travelSpeed = 60;
/**
* This is GUARANTEED to return a positive value.
*/
public int getTravelSpeed() {
return travelSpeed;
}
/**
* Sets this instance's travel speed.
*
* #throws IllegalArgumentException if argument is not positive
*/
public void setTravelSpeed(int newSpeed) {
if (newSpeed <= 0) {
throw new IllegalArgumentException("Argument must be positive");
}
this.travelSpeed = newSpeed;
}
public int calculateTravelTime() {
return distance / travelSpeed;
}
}
Now it is absolutely impossible for any outside code to place the object in an invalid state. If anyone tries to do so, the resulting IllegalArgumentException will provide you with an informative stack trace that will immediately expose the culprit.
As a bonus, all other code which uses this class no longer needs to do any checks for its validity, because the object itself can already guarantee that validity. This makes overall development much faster for everyone.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I've written this 'CoreException' Exception subclass. I appear to have three options in the constructor that would all behave identically since they are all referencing the same object.
*note: the question is about the compiler and possible runtime difference from the three different source code options. The constructed Object could be of any class.
public class CoreException extends Exception {
private final Class<?> sourceClass;
private final Method sourceMethod;
public CoreException(#NotNull Method method, #NotNull Throwable thr) {
super("this text is irrelevant", thr);
this.setStackTrace(thr.getStackTrace());
this.sourceMethod = method;
this.sourceClass = this.sourceMethod.getDeclaringClass();
}
public Class<?> getSourceClass() { return sourceClass; }
public Method getSourceMethod() { return sourceMethod; }
}
The construction of the Class<?> sourceClass object seems to have three identical options:
this.sourceClass = this.sourceMethod.getDeclaringClass();
this.sourceClass = sourceMethod.getDeclaringClass();
this.sourceClass = method.getDeclaringClass();
Is there a decent reason to use one over the others, perhaps because of a marginal increase in performance, reliability / resilience, etc..?
Or does the compiler simply turn all three of these into exactly the same result?
In the example, there is no difference between this.sourceMethod and sourceMethod, the resulting bytecode will be the same. It is just a matter of taste which you prefer. Some people prefer using this. always, while others prefer to only use this. when it is necessary for disambiguation if there is also a local variable with the same name.
The only real difference is between [this.]sourceMethod and method: sourceMethod is a field on the object, while method is a parameter. Given method is a parameter, it's on the stack, and it's probably slightly faster than accessing the field sourceMethod of the object. However, in the grand scheme of things, this difference is likely negligible, and even if it's not, it is entirely possible that the JIT compiler optimizes it in a way they are equivalent. If you really need to know, you should write a micro-benchmark to measure that difference.
Personally, I would consider the choice between using sourceMethod or method primarily one of opinion.
This is a bad idea. You're trying to address a thing you find uncomfortable about java, the language, with an API update. This cannot work - the vast majority of exceptions out there just will not be wrapped in a CoreException (e.g. anything that the java core API itself throws, or anything in any third party library such as JUnit, JDBI, etcetera).
Your code will no longer be making sense to other java programmers who do not expect to need to reroute all exceptions through this class of yours.
You also won't be able to write code that 'fits' in existing APIs (i.e. implementations of interfaces), as you will be required to write your own variants of all relevant exception types (as they will need to extend CoreException somewhere in the hierarchy, and the exceptions in java.* and anything written in e.g. jdbi.* wouldn't, and you can't update them to without forking every library you use).
So what DO I do?
The info you are sticking in that exception message are already available in plain jane exceptions - the first line of the stack trace. It's silly to repeat this information in the message.
If you have some logging or error reporting system where currently you do not have this information, and you want it to, that is a real problem. You've just decided to solve it in an unwieldy and inadvisable way.
Instead, updating whatever that system might be to include the first line of the stacktrace. This is generally not hard, but it depends on where the place is that made you go: "Oof, I could really use the method name here".
Note that going your own way has more downsides than just 'it stands out in existing APIs like a sore thumb'. IDEs will not recognize this and you won't be able to click on the class+methodname in the message to automatically jump to the right file. You need to match the 'style' of what StackTraceElement prints if you want that.
Your code also causes straight up erroneous conclusions. This approach (of having a Method object that represents the source) doesn't make much sense when the exception is thrown from within a lambda.
Thus, abort the plan. Whatever you wanted to accomplish by making Method sourceMethod part of the state of all of your exceptions - you either didn't want that, or you can accomplish it far better in a different way (and probably by relying on getStackTrace()[0]) to convey it.
public Class<?> getSourceClass() {
return Class.forName(getStackTrace()[0].getClassName());
}
can do the job just as well, for example, though note that this code may fail (throw ClassNotFoundEx) depending on where the exception came from. Not all code is easily captured in a 'it is in this class and in this method' context (core stuff, native stuff, synthetic methods, bridgers, dynamically generated code, lambdas...)
Latest project I used java8 , found it's very convenient to process Collection type, it gave me great surprise. But suddenly feel some conventional syntax are so cumbersome, for example I have an Object called BuyerOrderCountStats, every time buyer commit an order, will increase his order count,
BuyerOrderCountStats bocs = ...;
bocs.setOrderCount(bocs.getOrderCount()+1);
Is there some convenient manner for this situation in java 8 which I don't know?
Nothing very special exists in java-8 which would help to solve your problem. However you may design your class (even in Java 1.0) to fit the business logic better. Remove setOrderCount method and replace it with addOrder():
class BuyerOrderCountStats {
private int orderCount;
public void addOrder() {
orderCount++;
}
}
In many cases instead of plain setters you can create better business-logic specific methods which modify the object state.
Tagir Valeev’s answer points you into the right direction. Whenever there is a business logic to model, you should avoid public getters and setters (especially setters) and try to provide appropriate business logic specific update operations.
But since you asked about properties and Java 8 features in general, it’s worth noting that there is an alternative, if you still want (or need) to allow external update operations for a property:
class BuyerOrderCountStats {
private int orderCount;
// may still have getters and setters
public void updateOrderCount(IntUnaryOperator op) {
orderCount=op.applyAsInt(orderCount);
}
}
Then you may change the property like:
BuyerOrderCountStats stats= …
stats.updateOrderCount(count -> count+1 );
You only have to keep in mind, that you can’t use the postfix ++ here as count++ only modifies the lambda expression’s parameter but returns the old value. A prefix increment, i.e. ++count, would work here as it evaluates to the result, but the modification of the parameter would be pointless and misleading. Thus, don’t use neither ++ nor += here, use always + like in the above example. The same applies to other operators.
The updateProperty method can verify whether the result is within the legal range for the property before making a change just like setProperty can do. One advantage of the updateProperty method is, that it can provide locking if needed to avoid concurrent updates. This is something, a get-modify-set roundtrip cannot provide.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I've just realised that when I am programming in Java I avoid local variables like the plague, if I really have to I prefix a member with a lower case "L" and have a method that resets that object (if the object is mine, I usually have a private method called init or something that the constructor calls)
I've just realised that this is really ugly in so many ways. Am I doing it right?
C++ programmers will know exactly what I mean, locals that don't leave the function's scope are automatically destroyed for us (if it does leave the function scope, use a pointer, blah blah blah)
Pattern for when this happens
I've found that whenever I fit an adapter to a function parameter and interact with it through this adapter is when I use this.
I also tend tohave the adapter maintain a pool of any objects it uses (up to a certain number)
It also occurs when I want to use data-types that require "new" to initialise but only within the method.
The code is a part of some main loop usually, otherwise it wouldn't matter, obviously (it's not a one off thing)
GC Collection amount:
Amount (Mb): | 30| 60| 90| 120| 150| 180| 210| 240| 270| 300| 330| 360|
--------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
With pattern |## (14)
without |################################################################### (350)
The program was pushed through its unit tests the mean GC amount is shown. The standard deviation was less than 5 for both.
This feels like it is somehow related to the flywheel pattern...
There is no code for this because:
It can manifest itself in so many ways! If you have a ComplexNumber class for example, if you just create them as needed you will generate vast amounts of garbage, if you have any sort of vector or matrix classes, same thing.
Another area is anything involving some sort of graph which is carefully traversed to generate another structure, like a scene graph, critical path, even a stack representing the current directory.
Basically if you have "new" to assign to a local variable in a method that gets called a lot you will find this.
Sample used above
It came from a program I wrote to teach people about finite state automata and other state-machines (Markov Chains, so forth), I noticed crippling ram usage and decided to investigate.
Comparison with other languages
Obviously C++ doesn't have this problem. But nor does Python you'll be glad to know. Python's reference counting means (provided you haven't got any cricles) that the moment the method ends things are deleted, infact there is a meta-method for it and you can use it reliably as a destructor (provided you are disciplined enough not to leak it from the method)
I can't be the first to have this problem, looking at similar questions suggests that there is no solution, but I can't believe that this hasn't been encountered before!
About me
I'm coming from C++ and Python (love them both!) to Java, I am "experienced" in Java in that I can read/write stuff that works, it follows a nice design philosophy and such, but I tend to be very mindful of performance and resources. I'm suffering withdrawal from const, I was a total const whore.
How this is not pooling
Suppose you have a GroupElement class - that represents a member of an algebraic group, we'll use additive notation.
Suppose that g.add(h) returns a new element, if you do this MANY many times you have a lot of elements. if instead you have:
GroupElement f = new GroupElement(0); //identity
g.add(f,h);
where:
add's first argument is the place to put the result, we generate no garbage.
The people who don't follow the above
You should know what a complex number is? Suppose a complex number has a method called add that takes a complex number and returns a new complex number. If you do a=b.add(c); A LOT of times, you get A LOT minus 1 garbage complex numbers floating around.
If you have inplaceAdd(ComplexNumber target, ComplexNumber value) say where:
target.real = value.real+real;
target.im = value.im+im;
you create no garbage if you do: b.inplaceAdd(a,c) - which does the same as the above a=b.add(c)
BTW add could do this: return new ComplexNumber(real+value.real,im+value.im) - see what I mean now?
Implementation of example (seriously guys, how do you not get this!)
public class ComplexNumber {
private double real;
private double im;
public ComplexNumber(double r, double i) {
real = r;
im = i;
}
public ComplexNumber add(ComplexNumber value) {
return new ComplexNumber(real + value.real, im + value.im);
}
public void inplaceAdd(ComplexNumber target, ComplexNumber value) {
target.real = real + value.real;
target.im = im + value.im;
}
}
If you have a ComplexNumber class for example, if you just create them as needed you will generate vast amounts of garbage, if you have any sort of vector or matrix classes, same thing.
Keep in mind that garbage is free; the cost of garbage collection is determined by the non-garbage that has to be traversed. (I mean, the VM spec doesn't actually specify exactly how GC must be implemented, but that's how the major ones all work.) And this is intentional: obviously there's no technical reason that a Java implementation can't use reference-counting; it's just that it's not considered very robust/efficient/reliable/etc. (In C++ and Perl and Python, the reference-counting gives you the advantage of predictable destructors. Java doesn't offer that; instead, it offers finally blocks and try-with-resources.)
I m trying to develop a simulation application. I need to monitor all java objects in simulation environment. During the execution of a simulation, user defined objects methods are called periodically in each tick. I want to trace all field values and method return values of all objects. For example,
public class Person{
int energy,x,y;
public Person(){
this.energy = new Random().nextInt(0,10);
}
#ScheduledMethod(start=1, interval=1)
void step(){
energy--;
// move random x,y
move();
}
void move(){
this.x= new Random().nextInt(1,50);
this.y = new Random().nexInt(1,50);
} }
In my simulator each person instance energy value in each tick until person is dead is traced and saved. Simulation developers generally uses randomized functions so calling a method twice may not be return the same value like x,y value of the Person.
By using reflection API i can access field values dynamically (energy value of the person can be accessed.) but i need to access method return values (x,y value of the person is changed in each call of the move). When i call method using reflection execution of the method is twiced. So, i need to handle method calling differently.
I mention that i need a monitoring mechanism like JAVA Debugging API. How i can do that during the execution of simulation.I need to watch all fields and method return values like debugging code in execution.
Any idea.
Thanks for ideas
If I understand what you're asking correctly, you want to capture changes in values of raw fields after a call to a method with your annotation.
There are a lot of possible solutions to this, depending on how simple the client code needs to be, and how complicated a framework you want to write, and what you actually need it to do. Here are some ideas:
Have a common base class for simulation objects, and give subclasses a way to store values in a Map<String,Object> you give them, instead of in a raw field; they you supply a subclass of Map which records changes, and your code can simply ask the object what has changed since the last time it was called
Instrument the bytecode on the fly when you load it, using something like BCEL, and replace local field accesses with calls to dynamically generated getters and setters, and do the above bookkeeping there
Do the above, but at compile time by dynamically generating subclasses which contain the bookkeeping code
The last two options are non-trivial to implement, so I'd strongly suggest considering the first option first.
Why do i need to use setProperty to be able to set the value of a variable in my java class
When i can just create the instance of the variable and use the intance to access my variable and assign a value.
What you are referring to is Encapsulation. It is one of the corner stones of object oriented programming. You usually want to restrict the ability of other code to mess around with the internal structure of your class.
Imagine a simple example where setting an integer value to a negative value will make your class fail catastrophically. With a setter in place, you could be able to handle this better, for instance with something like so:
public void setNumber(int number)
{
if (number < 0)
{
number = 1;
}
this.number = number
}
OR (more likely)
public void setNumber(int number)
{
if (number < 0)
{
throw new Exception("Number can't be less than 0");
}
else
{
this.number = number
}
}
As pointed out by Raveesh Sharma in the comment below, this is the reason why all instance variables should be declared as private.
You sure can assigned values by directly accessing the attributes from a given instance but that's definitely against the fundamentals of Java Object Oriented principles.
The best practices in Java OO recommend you to encapsulate the attributes from a class by making them private, and giving access to them through getter/setter.
Applying this principle is one way of reducing coupling between classes.
You don't need to use getProperty() or setProperty() (known as getter and setter methods), but it is the preferred way of accessing class-level properties in Java. It is a fundamental principle used in Obejct-Oriented programming, called Encapsulation, which defined which Objects should have access to which Properties, based on ownership, privacy levels, hierarchy in the Object tree, etc.
It also allows you to do more advanced things with your properties, such as making them synchronised. This allows you to make sure order is preserved when accessing a property, so that you don't overwrite values out of order.
All this stuff wasn't obvious to me when I was first learning programming either, but as you learn more about programming the reasons and benefits start to appear and make more sense.
It's a general implementation of of the object-oriented principle of encapsulation. There are a lot of cases when there is no or minimal advantage to using setters. However, there are cases when it can save you from hard to find bugs.
Example
Class Person
Integer age;
....
setAge(Integer age )
{
if (this.age<age || age>120)
{
Throw new RuntimeException("The age: "+age+"is invalid");
}
else {
this.age=age;
}
As the program grows in complexity, this can help you catch errors earlier. Since you may not know ahead of time how a program is going to evolve over time, it's often best to err on the side of caution and use getters/setters to start with. Most IDE's make this fairly painless.