Inefficiency of defensive copy in Java [closed] - java

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'm a longtime C/C++ programmer who's learning Java. I've read about the problem of breaking encapsulation by having an accessor method that returns a reference to a private field. The standard Java solution seems to be defensive copying - calling the copy constructor or clone() to create a copy of the field and returning a reference to the copy. I don't understand why no one seems concerned about the inefficiency of making a defensive copy. In C++, the accessor would just return a pointer to const, protecting the private member without copying. Why doesn't Java have a reference to const?

Why doesn't Java have a reference to const?
Questions can only be properly answered by the language designer, but I think that the problem was that they couldn't figure out how to make it work as part of the language design. My recollection (from some "Java design rationale" document that I came across one time) was that Gosling et al originally wanted to support const ...
In fact, though both C and C++ both support const as a way of expressing a mutability constraint, they both also have loopholes that allow some code to "break" the constraint. (See the Wikipedia article on const-correctness.) It could be that it was the difficulty of coming up with a design for Java that didn't have (or need) such loopholes that caused Gosling et al to abandon that idea.
The flip-side is that the need for defensive copying in Java is not as great as you might imagine, and that the cost of doing it is not as great as you might imagine. And when the cost of the defensive copy is significant, there are other options in Java ... like creating "unmodifiable" wrapper objects, or interfaces that only support "read" operations.

NOTE: I don't know that you're going to find a direct answer to the question of why there is no const in Java. (My guess is because due to the dynamic nature of Java, having a const keyword did not provide as many compiler optimizations and thus was deemed not worth putting in - but that's just my opinion. [In C++ you have all of the final concrete types available to you at compile time, in Java, you don't.])
As for what is generally done instead, you have to make a decision based on the data types and what your fields semantically mean.
Some common types (String, Date) are immutable and are designed to be passed around and returned from getters with as little overhead as possible while not allowing modification.
As #DavidWallace points out, there are methods which create a shallow, unmodifiable copy of a Map and allow you to return that to caller - to guarantee they won't mess with it. This is a practical solution, however it does not enforce it at compile time.
If we're talking about maps: A java.util.Map is, per the interface contract, mutable. To achieve something close to const, you can easily create a different but simple interface with only a lookup method:
public interface Lookup<K,V> {
public V get(K);
}
And return an instance of that. Thus guaranteeing nobody will modify it... at compile time... because no such method exists.
And implementing a MapLookup that implements the above by wrapping a map without making a copy is like 5 lines of code.
If you want to make really sure that nobody modifies what you send back, don't send back something that is mutable. (And there's no reason it has to be done via an inefficient deep copy, as explained above.)

Related

Better to reference field instance or parameter in this constructor? [closed]

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...)

why using stack data structure for storing primitive values instead of linked lists or arrays ? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Since Stacks internally uses either Linked Lists / Arrays, why don't java directly store primitive values in Linked Lists / Arrays instead of Stacks ?
The key problem is that generics are a compile time feature and all implementation of generics use the same code, they are all List<? extends Object> and can be cast to this type. However List<int> is not a List of Object and would need it's own code generated on demand (something the compiler doesn't do).
Also consider what is the parent of List<Object> and List<int> it could be a List<*> or something like that which has a size() method. This means adding a parent to List<object> which it previously didn't have and doing it for data types which have already been compiled. e.g. say you have your own Stack implementation in a JAR when the JVM designers have never seen and without re-compiling you JAR you now want a Stack<int> which is a class which never existed before, where does it go? what should it be called? If the compiler creates it and you release it in one JAR but later you compile it again for another JAR you have two versions of the same class.
These means that most likely this class will need to be understood at compile time for the javac but actually created on demand at runtime to ensure there is one, most up to date version of the classes.
Supporting primitive generics is non-trivial but can be done. In fact they are looking to do it in Java 10.
I believe it's a nice question on SO.
Let me start with java.util.Stack which extends Vector and have certain methods which internally calls the methods defined in Vector class. (For ex: removeElementAt(..), addElement(..) and so on.
The Vector implementation involves "Array" as you rightly said.(if you consider jdk version)
Basically java.util.Stack works on the principle of LIFO which makes it an wonderful data structure. (with simple push and pop)
Now coming back to your question why java doesn't make use of array for stack memory. Let me give you a brief overview of stack memory.
Stack Memory contains method specific values that are short-lived and references to other objects in the heap that are getting referred from the method used by threads.
If you consider your program flow the great main() will be called first and all subsequent nested method calls will be followed by it. So this is how stack should look like if you only consider methods in stack memory of your program flow:
main() <----- 1st call
method1()
main() <------ 2nd call
method2()
method1()
main() <------ 3rd call
So here if you visualize all control of you program should come back to main(). The principle of LIFO is certainly best choice here. When you have a handy data structure to do that why to reinvent the wheel and make use of Array?
Note : Ideal option to visualize read out a .class file.

Java 8 way to work with an enum [closed]

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 4 years ago.
Improve this question
I'm wondering what the best way is in Java 8 to work with all the values of an enum. Specifically when you need to get all the values and add it to somewhere, for example, supposing that we have the following enum:
public enum Letter {
A, B, C, D;
}
I could of course do the following:
for (Letter l : Letter.values()) {
foo(l);
}
But, I could also add the following method to the enum definition:
public static Stream<Letter> stream() {
return Arrays.stream(Letter.values());
}
And then replace the for from above with:
Letter.stream().forEach(l -> foo(l));
Is this approach OK or does it have some fault in design or performance? Moreover, why don't enums have a stream() method?
I'd go for EnumSet. Because forEach() is also defined on Iterable, you can avoid creating the stream altogether:
EnumSet.allOf(Letter.class).forEach(x -> foo(x));
Or with a method reference:
EnumSet.allOf(Letter.class).forEach(this::foo);
Still, the oldschool for-loop feels a bit simpler:
for (Letter x : Letter.values()) {
foo(x);
}
Three questions: three-part answer:
Is it okay from a design point of view?
Absolutely. Nothing wrong with it. If you need to do lots of iterating over your enum, the stream API is the clean way to go and hiding the boiler plate behind a little method is fine. Although I’d consider OldCumudgeon’s version even better.
Is it okay from a performance point of view?
It most likely doesn’t matter. Most of the time, enums are not that big. Therefore, whatever overhead there is for one method or the other probably doesn’t matter in 99.9% of the cases.
Of course, there are the 0.1% where it does. In that case: measure properly, with your real-world data and consumers.
If I had to bet, I’d expect the for each loop to be faster, since it maps more directly to the memory model, but don’t guess when talking performance, and don’t tune before there is actual need for tuning. Write your code in a way that is correct first, easy to read second and only then worry about performance of code style.
Why aren’t Enums properly integrated into the Stream API?
If you compare Java’s Stream API to the equivalent in many other languages, it appears seriously limited. There are various pieces that are missing (reusable Streams and Optionals as Streams, for example). On the other hand, implementing the Stream API was certainly a huge change for the API. It was postponed multiple times for a reason. So I guess Oracle wanted to limit the changes to the most important use cases. Enums aren’t used that much anyway. Sure, every project has a couple of them, but they’re nothing compared to the number of Lists and other Collections. Even when you have an Enum, in many cases you won’t ever iterate over it. Lists and Sets, on the other hand, are probably iterated over almost every time. I assume that these were the reasons why the Enums didn’t get their own adapter to the Stream world. We’ll see whether more of this gets added in future versions. And until then you always can use Arrays.stream.
My guess is that enums are limited in size (i.e the size is not limited by language but limited by usage)and thus they don't need a native stream api. Streams are very good when you have to manipulate transform and recollect the elements in a stream; these are not common uses case for Enum (usually you iterate over enum values, but rarely you need to transform, map and collect them).
If you need only to do an action over each elements perhaps you should expose only a forEach method
public static void forEach(Consumer<Letter> action) {
Arrays.stream(Letter.values()).forEach(action);
}
.... //example of usage
Letter.forEach(e->System.out.println(e));
I think the shortest code to get a Stream of enum constants is Stream.of(Letter.values()). It's not as nice as Letter.values().stream() but that's an issue with arrays, not specifically enums.
Moreover, why don't enums have a stream() method?
You are right that the nicest possible call would be Letter.stream(). Unfortunately a class cannot have two methods with the same signature, so it would not be possible to implicitly add a static method stream() to every enum (in the same way that every enum has an implicitly added static method values()) as this would break every existing enum that already has a static or instance method without parameters called stream().
Is this approach OK?
I think so. The drawback is that stream is a static method, so there is no way to avoid code duplication; it would have to be added to every enum separately.

I'm conditioned to avoid local variables - am I doing it right? [closed]

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.)

Is Java fully object-oriented? [duplicate]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 12 years ago.
Java has primitive data types which doesn't derive from object like in Ruby. So can we consider Java as a 100% object oriented language? Another question: Why doesn't Java design primitive data types the object way?
When Java first appeared (versions 1.x) the JVM was really, really slow.
Not implementing primitives as first-class objects was a compromise they had taken for speed purposes, although I think in the long run it was a really bad decision.
"Object oriented" also means lots of things for lots of people.
You can have class-based OO (C++, Java, C#), or you can have prototype-based OO (Javascript, Lua).
100% object oriented doesn't mean much, really. Ruby also has problems that you'll encounter from time to time.
What bothers me about Java is that it doesn't provide the means to abstract ideas efficiently, to extend the language where it has problems. And whenever this issue was raised (see Guy Steele's "Growing a Language") the "oh noes, but what about Joe Sixpack?" argument is given. Even if you design a language that prevents shooting yourself in the foot, there's a difference between accidental complexity and real complexity (see No Silver Bullet) and mediocre developers will always find creative ways to shoot themselves.
For example Perl 5 is not object-oriented, but it is extensible enough that it allows Moose, an object system that allows very advanced techniques for dealing with the complexity of OO. And syntactic sugar is no problem.
No, because it has data types that are not objects (such as int and byte). I believe Smalltalk is truly object-oriented but I have only a little experience with that language (about two months worth some five years ago).
I've also heard claims from the Ruby crowd but I have zero experience with that language.
This is, of course, using the definition of "truly OO" meaning it only has objects and no other types. Others may not agree with this definition.
It appears, after a little research into Python (I had no idea about the name/object distinction despite having coded in it for a year or so - more fool me, I guess), that it may indeed be truly OO.
The following code works fine:
#!/usr/bin/python
i = 7
print id(i)
print type(i)
print i.__str__()
outputting:
6701648
<type 'int'>
7
so even the base integers are objects here.
To get to true 100% OO think Smalltalk for instance, where everything is an object, including the compiler itself, and even if statements: ifTrue: is a message sent to a Boolean with a block of code parameter.
The problem is that object-oriented is not really well defined and can mean a lot of things. This article explains the problem in more detail:
http://www.paulgraham.com/reesoo.html
Also, Alan Kay (the inventor of Smalltalk and author(?) of the term "object-oriented") famously said that he hadn't C++ in mind when thought about OOP. So I think this could apply to Java as well.
The language being fully OO (whatever that means) is desirable, because it means better orthogonality, which is a good thing. But given that Java is not very orthogonal anyway in other respects, the small bit of its OO incompleteness probably doesn't matter in practice.
Java is not 100% OO.
Java may going towards 99% OO (think of auto-boxing, Scala).
I would say Java is now 87% OO.
Why java doesn't design primitive data
types as object way ?
Back in the 90's there were Performance reasons and at the same time Java stays backward compatible. So they cannot take them out.
No, Java is not, since it has primitive data types, which are different from objects (they don't have methods, instance variables, etc.). Ruby, on the other hand, is completely OOP. Everything is an object. I can do this:
1.class
And it will return the class of 1 (Fixnum, which is basically a number). You can't do this in Java.
Java, for the reason you mentioned, having primitives, doesn't make it a purely object-oriented programming language. However, the enforcement of having every program be a class makes it very oriented toward object-oriented programming.
Ruby, as you mentioned, and happened to be the first language that came to my mind as well, is a language that does not have primitives, and all values are objects. This certainly does make it more object-oriented than Java. On the other hand, to my knowledge, there is no requirement that a piece of code must be associated with a class, as is the case with Java.
That said, Java does have objects that wrap around the primitives such as Integer, Boolean, Character and such. The reason for having primitives is probably the reason given in Peter's answer -- back when Java was introduced in the mid-90's, memory on systems were mostly in the double-digit megabytes, so having each and every value be an object was large overhead.
(Large, of course is relative. I can't remember the exact numbers, but an object overhead was around 50-100 bytes of memory. Definitely more than the minimum of several bytes required for primitive values)
Today, with many desktops with multiple gigabytes of memory, the overhead of objects are less of an issue.
"Why java doesn't design primitive data types as object way ?"
At Sun developer days, quite a few years ago I remember James Gosling answering this. He said that they'd liked to have totally abstracted away from primitives - to leave only standard objects, but then ran out of time and decided to ship with what they had. Very sad.
So can we consider java as 100% object
oriented language?
No.
Another question : Why java doesn't
design primitive data types as object
way?
Mainly for performance reasons, possibly also to be more familiar to people coming from C++.
One reason Java can't obviously do away with non-object primitives (int, etc.) is that it does not support native data members. Imagine:
class int extends object
{
// need some data member here. but what type?
public native int();
public native int plus(int x);
// several more non-mutating methods
};
On second thoughts, we know Java maintains internal data per object (locks, etc.). Maybe we could define class int with no data members, but with native methods that manipulate this internal data.
Remaining issues: Constants -- but these can be dealt with similarly to strings. Operators are just syntactical sugar and + and would be mapped do the plus method at compile time, although we need to be careful that int.plus(float) returns float as does float.plus(int), and so on.
Ultimately I think the justification for primitives is efficiency: the static analysis needed to determine that an int object can be treated purely as JVM integer value may have been considered too big a problem when the language was designed.
I'd say that full-OO languages are those which have their elements (classes, methods) accessible as objects to work with.
From this POV, Java is not fully OOP language, and JavaScript is (no matter it has primitives).
According to Concepts in Programming Languages book, there is something called Ingalls test, proposed by Dan Ingalls a leader of the Smalltalk group. That is:
Can you define a new kind of integer,
put your new integers into rectangles
(which are already part of the window
system), ask the system to blacken a
rectangle, and have everything work?
And again according to the book Smalltalk passes this test but C++ and Java do not. Unfortunately book is not available online but here are some supporting slides (slide 33 answers your question).
No. Javascript, for example, is.
What would those Integer and Long and Boolean classes be written in?
How would you write an ArrayList or HashMap without primitive arrays?
This is one of those questions that really only matters in an academic sense. Ruby is optimized to treat ints, longs, etc. as primitives whenever possible. Java just made this explicit. If Java had primitives be objects, there would be IntPrimitive, LongPrimitive, etc (by whatever name) classes. which would most likely be final without special methods (e.g. no IntPrimitive.factorial). Which would mean for most purposes they would be primitives.
Java clearly is not 100% OO. You can easily program it in a procedural style. Most people do. It's true that the libraries and containers tend not to be as forgiving of this paradigm.
Java is not fully object oriented. I would consider Smalltalk and Eiffel the most popular fully object oriented languages.

Categories

Resources