Related
This question already has answers here:
When should one use final for method parameters and local variables?
(15 answers)
Closed 6 years ago.
Maybe my question will be so much silly for 2016 because there exist many similar questions but it is very hard to me to understand when should i use final variable inside a method instead of local variable. Which one will be more efficiency and when should i use it.
public void setmethod(int var)
{
final int variable = var;
System.out.println(variable);
}
public void setmethod(int var)
{
int variable = var;
System.out.println(variable);
}
I know that The result in the Output will be the same and also that Final fields - is making that same fields reference immutable but which one option is more efficiency under certain circumstances and Why?? I am a bit confused
Several things here:
At this point, Java compilers are sophisticated enough that if there is any performance boost, it is imperceptible unless you are in the tightest loop imaginable.
Before you even consider this optimization, you should be looking throughout your code for other, more macro optimizations (eg- reducing http requests, database requests, etc). I can guarantee that you will get more bang looking for those things, instead quibbling over keywords.
Second, I think you meant this:
public void setmethod(final int var)
{
System.out.println(var);
}
Third, I would recommend that you always use a final keyword unless you really can't. This makes the intent of the code clearer to anyone reading. It states a contract about what can and cannot happen in your code.
Making your variables and fields final whenever possible just makes good sense from a clarity point of view. It has nothing to do with performance.
I have always thought that this was a design flaw of Java that variables are mutable by default. Rather, by default variables should be final, and Java should have introduced a mutable keyword.
If you are sure that the variable value should not be changed, then the use of final is a good practice. Assuming you have a complex method, this will cause a compilation error if you accidentally try to change the value of the final variable.
The error I get from the compiler is "The left hand side of an assignment must be a variable". My use case is deep copying, but is not really relevant.
In C++, one can assign to *this.
The question is not how to circumvent assignment to this. It's very simple, but rather what rationale is there behind the decision not to make this a variable.
Are the reasons technical or conceptual?
My guess so far - the possibility of rebuilding an Object in a random method is error-prone (conceptual), but technically possible.
Please restrain from variations of "because java specs say so". I would like to know the reason for the decision.
In C++, one can assign to *this
Yes, but you can't do this = something in C++, which I actually believe is a closer match for what you're asking about on the Java side here.
[...] what rationale is there behind the decision not to make this a variable.
I would say clarity / readability.
this was chosen to be a reserved word, probably since it's not passed as an explicit argument to a method. Using it as an ordinary parameter and being able to reassign a new value to it, would mess up readability severely.
In fact, many people argue that you shouldn't change argument-variables at all, for this very reason.
Are the reasons technical or conceptual?
Mostly conceptual I would presume. A few technical quirks would arise though. If you could reassign a value to this, you could completely hide instance variables behind local variables for example.
My guess so far - the possibility of rebuilding an Object in a random method is error-prone (conceptual), but technically possible.
I'm not sure I understand this statement fully, but yes, error prone is probably the primary reason behind the decision to make it a keyword and not a variable.
because this is final,
this is keyword, not a variable. and you can't assign something to keyword. now for a min consider if it were a reference variable in design spec..and see the example below
and it holds implicit reference to the object calling method. and it is used for reference purpose only, now consider you assign something to this so won't it break everything ?
Example
consider the following code from String class (Note: below code contains compilation error it is just to demonstrate OP the situation)
public CharSequence subSequence(int beginIndex, int endIndex) {
//if you assign something here
this = "XYZ" ;
// you can imagine the zoombie situation here
return this.substring(beginIndex, endIndex);
}
Are the reasons technical or conceptual?
IMO, conceptual.
The this keyword is a short hand for "the reference to the object whose method you are currently executing". You can't change what that object is. It simply makes no sense in the Java execution model.
Since it makes no sense for this to change, there is no sense in making it a variable.
(Note that in C++ you are assigning to *this, not this. And in Java there is no * operator and no real equivalent to it.)
If you take the view that you could change the target object for a method in mid flight, then here are some counter questions.
What is the use of doing this? What problems would this (hypothetical) linguistic feature help you solve ... that can't be solved in a more easy-to-understand way?
How would you deal with mutexes? For instance, what would happen if you assign to this in the middle of a synchronized method ... and does the proposed semantic make sense? (The problem is that you either end up executing in synchronized method on an object that you don't have a lock on ... or you have to unlock the old this and lock the new this with the complications that that entails. And besides, how does this make sense in terms of what mutexes are designed to achieve?)
How would you make sense of something like this:
class Animal {
foo(Animal other) {
this = other;
// At this point we could be executing the overridden
// Animal version of the foo method ... on a Llama.
}
}
class Llama {
foo(Animal other) {
}
}
Sure you can ascribe a semantic to this but:
you've broken encapsulation of the subclass in a way that is hard to understand, and
you've not actually achieved anything particularly useful.
If you try seriously to answer these questions, I expect you'll come to the conclusion that it would have been a bad idea to implement this. (But if you do have satisfactory answers, I'd encourage you to write them up and post them as your own Answer to your Question!)
But in reality, I doubt that the Java designers even gave this idea more than a moment's consideration. (And rightly so, IMO)
The *this = ... form of C++ is really just a shorthand for a sequence of assignments of the the attributes of the current object. We can already do that in Java ... with a sequence of normal assignments. There is certainly no need for new syntax to support this. (How often does a class reinitialize itself from the state of another class?)
I note that you commented thus:
I wonder what the semantics of this = xy; should be. What do you think it should do? – JimmyB Nov 2 '11 at 12:18
Provided xy is of the right type, the reference of this would be set to xy, making the "original" object gc-eligible - kostja Nov 2 '11 at 12:24
That won't work.
The value of this is (effectively) passed by value to the method when the method is invoked. The callee doesn't know where the this reference came from.
Even if it did, that's only one place where the reference is held. Unless null is assigned in all places, the object cannot be eligible of garbage collection.
Ignoring the fact that this is technically impossible, I do not think that your idea would be useful OR conducive to writing readable / maintainable code. Consider this:
public class MyClass {
public void kill(MyClass other) {
this = other;
}
}
MyClass mine = new MyClass();
....
mine.kill(new MyClass());
// 'mine' is now null!
Why would you want to do that? Supposing that the method name was something innocuous rather than kill, would you expect the method to be able to zap the value of mine?
I don't. In fact, I think that this would be a misfeature: useless and dangerous.
Even without these nasty "make it unreachable" semantics, I don't actually see any good use-cases for modifying this.
this isn't even a variable. It's a keyword, as defined in the Java Language Specification:
When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method was invoked (§15.12), or to the object being constructed
So, it's not possible as it's not possible to assign a value to while.
The this in Java is a part of the language, a key word, not a simple variable. It was made for accessing an object from one of its methods, not another object. Assigning another object to it would cause a mess. If you want to save another objects reference in your object, just create a new variable.
The reason is just conceptual. this was made for accessing an Object itself, for example to return it in a method. Like I said, it would cause a mess if you would assign another reference to it. Tell me a reason why altering this would make sense.
Assigning to (*this) in C++ performs a copy operation -- treating the object as a value-type.
Java does not use the concept of a value-type for classes. Object assignment is always by-reference.
To copy an object as if it were a value-type: How do I copy an object in Java?
The terminology used for Java is confusing though: Is Java “pass-by-reference” or “pass-by-value”
Answer: Java passes references by value. (from here)
In other words, because Java never treats non-primitives as value-types, every class-type variable is a reference (effectively a pointer).
So when I say, "object assignment is always by-reference", it might be more technically accurate to phrase that as "object assignment is always by the value of the reference".
The practical implication of the distinction drawn by Java always being pass-by-value is embodied in the question "How do I make my swap function in java?", and its answer: You can't. Languages such as C and C++ are able to provide swap functions because they, unlike Java, allow you to assign from any variable by using a reference to that variable -- thus allowing you to change its value (if non-const) without changing the contents of the object that it previously referenced.
It could make your head spin to try to think this all the way through, but here goes nothing...
Java class-type variables are always "references" which are effectively pointers.
Java pointers are primitive types.
Java assignment is always by the value of the underlying primitive (the pointer in this case).
Java simply has no mechanism equivalent to C/C++ pass-by-reference that would allow you to indirectly modify a free-standing primitive type, which may be a "pointer" such as this.
Additionally, it is interesting to note that C++ actually has two different syntaxes for pass-by-reference. One is based on explicit pointers, and was inherited from the C language. The other is based on the C++ reference-type operator &. [There is also the C++ smart pointer form of reference management, but that is more akin to Java-like semantics -- where the references themselves are passed by value.]
Note: In the above discussion assign-by and pass-by are generally interchangeable terminology. Underlying any assignment, is a conceptual operator function that performs the assignment based on the right-hand-side object being passed in.
So coming back to the original question: If you could assign to this in Java, that would imply changing the value of the reference held by this. That is actually equivalent to assigning directly to this in C++, which is not legal in that language either.
In both Java and C++, this is effectively a pointer that cannot be modified. Java seems different because it uses the . operator to dereference the pointer -- which, if you're used to C++ syntax, gives you the impression that it isn't one.
You can, of course, write something in Java that is similar to a C++ copy constructor, but unlike with C++, there is no way of getting around the fact that the implementation will need to be supplied in terms of an explicit member-wise initialization. [In C++ you can avoid this, ultimately, only because the compiler will provide a member-wise implementation of the assignment operator for you.]
The Java limitation that you can't copy to this as a whole is sort-of artificial though. You can achieve exactly the same result by writing it out member-wise, but the language just doesn't have a natural way of specifying such an operation to be performed on a this -- the C++ syntax, (*this) doesn't have an analogue in Java.
And, in fact, there is no built-in operation in Java that reassigns the contents of any existing object -- even if it's not referred to as this. [Such an operation is probably more important for stack-based objects such as are common in C++.]
Regarding the use-case of performing a deep copy: It's complicated in Java.
For C++, a value-type-oriented language. The semantic intention of assignment is generally obvious. If I say a=b, I typically want a to become and independent clone of b, containing an equal value. C++ does this automatically for assignment, and there are plans to automate the process, also, for the comparison.
For Java, and other reference-oriented languages, copying an object, in a generic sense, has ambiguous meaning. Primitives aside, Java doesn't differentiate between value-types and reference-types, so copying an object has to consider every nested class-type member (including those of the parent) and decide, on a case-by-case basis, if that member object should be copied or just referenced. If left to default implementations, there is a very good chance that result would not be what you want.
Comparing objects for equality in Java suffers from the same ambiguities.
Based on all of this, the answer to the underlying question: why can't I copy an object by some simple, automatically generated, operation on this, is that fundamentally, Java doesn't have a clear notion of what it means to copy an object.
One last point, to answer the literal question:
What rationale is there behind the decision not to make this a variable?
It would simply be pointless to do so. The value of this is just a pointer that has been passed to a function, and if you were able to change the value of this, it could not directly affect whatever object, or reference, was used to invoke that method. After all, Java is pass-by-value.
Assigning to *this in C++ isn't equivalent to assigning this in Java. Assigning this is, and it isn't legal in either language.
Why, in C++, do we prefer static initialization to dynamic initialization?
Whats the big deal?if static initialization is so performant then why do new languages like Java, C# use dynamic initialization?
We don't. We prefer automatic initialisation - i.e. creating objects on the stack (as opposed to the heap). If we do that, their lifetimes are managed for us. This is one of many advantages that C++ has over Java. As to why Java works like this, you ought to ask the designers, but I'd guess that it is to simplify garbage collection (while introducing lots of other problems).
The main reason anyone even notices the difference in C++ is that static initialization cannot depend on the contents of other globals. Hence it doesn't run afoul of the initialization order fiasco.
So, if I'm going to have globals, I probably prefer them to be static-initialized, and then to fill in values in a controlled order, rather than take a chance on the order of dynamic initialization for objects not in the same translation unit. But actually, "we" (meaning I) prefer not to have globals at all in C++, and when we do have them "we" prefer them to be function-scope statics rather than global-scope statics. So it's a very mild preference indeed which way something is initialized that we don't want to exist in the first place.
Java does use analogues of static initialization for some things: final static integers are turned into compilation constants, even. But since in Java objects are always on the heap, and have user-defined constructors, objects can't be initialized with anything analogous to C++'s static initialization, which is done by the runtime before any user code is executed. Performance isn't a consideration when one of the two options is simply impossible in your language. Whenever a static field is initialized to null in Java, you might say that's analogous to C++ static initialization.
In general, we prefer neither static nor dynamic init. Determining which one is preferred for a particular situation depends on your particular situation.
Who says we do? Honestly it's the first time I hear something like this.. Static initialization is better in some contexts, while dynamic is better in others. The rule of thumb is: if you know at compile time how big / how many then use static (easier, faster to type, no need to use smart pointers / delete, no memory leaks).. Otherwise you have no choice but to use dynamic.
I'm looking at some Java code that are maintained by other parts of the company, incidentally some former C and C++ devs. One thing that is ubiquitous is the use of static integer constants, such as
class Engine {
private static int ENGINE_IDLE = 0;
private static int ENGINE_COLLECTING = 1;
...
}
Besides a lacking 'final' qualifier, I'm a bit bothered by this kind of code. What I would have liked to see, being trained primarily in Java from school, would be something more like
class Engine {
private enum State { Idle, Collecting };
...
}
However, the arguments fail me. Why, if at all, is the latter better than the former?
Why, if at all, is the latter better
than the former?
It is much better because it gives you type safety and is self-documenting. With integer constants, you have to look at the API doc to find out what values are valid, and nothing prevents you from using invalid values (or, perhaps worse, integer constants that are completely unrelated). With Enums, the method signature tells you directly what values are valid (IDE autocompletion will work) and it's impossible to use an invalid value.
The "integer constant enums" pattern is unfortunately very common, even in the Java Standard API (and widely copied from there) because Java did not have Enums prior to Java 5.
An excerpt from the official docs, http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html:
This pattern has many problems, such as:
Not typesafe - Since a season is just an int you can pass in any other int value where a season is required, or add two seasons together (which makes no sense).
No namespace - You must prefix constants of an int enum with a string (in this case SEASON_) to avoid collisions with other int enum types.
Brittleness - Because int enums are compile-time constants, they are compiled into clients that use them. If a new constant is added between two existing constants or the order is changed, clients must be recompiled. If they are not, they will still run, but their behavior will be undefined.
Printed values are uninformative - Because they are just ints, if you print one out all you get is a number, which tells you nothing about what it represents, or even what type it is.
And this just about covers it. A one word argument would be that enums are just more readable and informative.
One more thing is that enums, like classes. can have fields and methods. This gives you the option to encompass some additional information about each type of state in the enum itself.
Because enums provide type safety. In the first case, you can pass any integer and if you use enum you are restricted to Idle and Collecting.
FYI : http://www.javapractices.com/topic/TopicAction.do?Id=1.
By using an int to refer to a constant, you're not forcing someone to actually use that constant. So, for example, you might have a method which takes an engine state, to which someone might happy invoke with:
engine.updateState(1);
Using an enum forces the user to stick with the explanatory label, so it is more legible.
There is one situation when static constance is preferred (rather that the code is legacy with tonne of dependency) and that is when the member of that value are not/may later not be finite.
Imagine if you may later add new state like Collected. The only way to do it with enum is to edit the original code which can be problem if the modification is done when there are already a lot of code manipulating it. Other than this, I personally see no reason why enum is not used.
Just my thought.
Readabiliy - When you use enums and do State.Idle, the reader immediately knows that you are talking about an idle state. Compare this with 4 or 5.
Type Safety - When use enum, even by mistake the user cannot pass a wrong value, as compiler will force him to use one of the pre-declared values in the enum. In case of simple integers, he could even pass -3274.
Maintainability - If you wanted to add a new state Waiting, then it would be very easy to add new state by adding a constant Waiting in your enum State without casuing any confusion.
The reasons from the spec, which Lajcik quotes, are explained in more detail in Josh Bloch's Effective Java, Item 30. If you have access to that book, I'd recommend perusing it. Java Enums are full-fledged classes which is why you get compile-time type safety. You can also give them behavior, giving you better encapsulation.
The former is common in code that started pre-1.5. Actually, another common idiom was to define your constants in an interface, because they didn't have any code.
Enums also give you a great deal of flexibility. Since Enums are essentially classes, you can augment them with useful methods (such as providing an internationalized resource string corresponding to a certain value in the enumeration, converting back and forth between instances of the enum type and other representations that may be required, etc.)
Closed. This question is opinion-based. It is not currently accepting answers.
Closed 9 months ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The same as this question but for java
Update
Based on the comments and responses of a few people, Its clear that Java has very little undefined behaviour.
So I'd like to ask as well what behaviour is not obvious. Please when answering make the distinction between the two :)
Anything to do with threads... :)
Also:
Overriding methods and expecting them to be used in the same way between versions
Assumptions about underlying platform (file separator, for instance)
Details of garbage collection/finalisation
Some details about class initialisation
Whether Integer.valueOf (and the like) return the same objects
Performance, latency and memory usage
There is very, very little undefined behavior in Java, when compared to C/C++, it is a much more well-defined platform. The reason for this is that C/C++ compilers are meant to produce code for very different platforms and therefore were granted rather wide freedoms in order to prevent too stringent requirements that would force a compiler to produce suboptimal code for a given platform.
Java sacrificed some of that by defining almost every behavior in a very exact way and allowing only small degrees of freedom. This of course makes the platform somewhat easier to handle.
The main area where undefined behavior happens is the exact timing and scheduling of multiple threads (as Tom Hawtin already mentioned)..
There are several places where the behavior is not obvious, 'though, so it might look undefined, but isn't (the String comparison examples given by Oscar Reyes are a great example).
And a few places where the behavior is defined to be undefined (for example the order of elements in a HashMap is defined to be implementation dependent and needs not be constant).
I think that Java(TM) Puzzlers: Traps, Pitfalls, and Corner Cases book will be very useful, it explains many hidden points and undefined behaviours of java.
Serialization. It's not undefined, per se (there is a deterministic algorithm). However, it is not at all obvious to the casual observer what will or will not cause a change in the serialVersionUID, thus foiling all your attempts to make use of RMI, JMS and a variety of other acronyms.
So, it is usually a good idea to consider your options when you know that you will need to serialize an object. I'm particularly fond of "always include it as a field" technique:
private static final long serialVersionUID = 1L;
Only change the value of that field when you, the developer know that there has been a compatibility-killing change to your code. Don't let the JDK make that decision for you....
I am not entirely sure what you mean by "undefined behaviors", but as others have pointed out, the core language is very predictable across platforms, and versions of the language and JVM.
This is not true for graphics (Swing, AWT), however, which tend to be unpredictable and not necessarily reproducible across different platforms. I worked on a graphics intensive Java based visualization application and I spent a lot of time "writing once, and debugging everywhere".
Also, Object.clone() has some major problems, and its use is discouraged in most cases. Please see Item 11, from "Effective Java" by Joshua Bloch for a complete answer.
Well defined but not obvious:
Object test for equality:
== is used to test references ( do these two object references point to the same object )
While equals is used to test object equality.
So for instance
new String("test") == new String("test")
Is false, while
new String("test").equals( new String("test") )
Is true
String objects are interned so the following returns true:
String a = "test";
String b = "test";
a == b // returns true
BUT if the string is created somewhere else ( from a database for instance )
String a = "test";
String b = getFromDataBase(); // internally the remote returns "test"
a == b // returns false.
The validation is false.
I've seen this happening in jsp with scriplets, and new programmers don't get why the validation
<%if( param == "continue" ) { %>
Never happens
The one thing I remember is regarding jvm compatibility with jni. We had and application that was developed on jdk1.4 and when installing it on a machine with ibm jvm (jikes I believe), the jni call just puked! That was in 2006 though. I believe this has little to do with java as a language, but more to do with java as a platform.
Add dynamic vs. static binding and how it is applied against overloaded and overridden methods as not obvious.
Not undefined but an unexpected behavior is how doubles are rounded when converted to an integer. 0.6d always rounds down to 0; actually 0.9d also rounds down to 0. But 0.99999999999999995 and greater will round up to 1.
Just an interesting behavior when casting the results of a Math.random() call to beaware of.
There are two undefined behaviors that I know of:
a) Overloading a method with a parameter that is a subclass of the same parameter in the overloaded method. For example:
void doSomething(Object obj);
void doSomething(String str);
There's no way to know which method will be called in doSomething("Hello world!"), since both signatures are valid. Also, this behavior can change from VM to VM, and even from execution to execution.
b) Calling a non-final method of the same class in the constructor. The undefined behavior occurs if this method is overriden in a subclass. Notice that construction occurs from the superclass to the subclass. The case gets specially nasty if the subclass method uses some local subclass attributes. In case of Oracle VM, the local attributes will be constructed, the superclass constructor will finish its execution then, when the constructor of subclass is reached the attributes will be constructed again, overriding previously defined values.