A tricky question of simple Java: variable scope - java

I am not new to java and C#. I thought I understand the concept of variable scope until recently I was asked this question in an interview:
public class Q{ //starting y scope
static int x = 11;
private int y = 33; // Just added a “private” modifier to make it clearer.
public static void main(String args[]){
Q q = new Q();
q.call(5);
}
public void call(int x){
Q q = new Q();
this.x = 22;
y = 44;
System.out.println("Output: " + Q.x);
System.out.println("Output: " + q.x);
System.out.println("Output: " + q.y);
}
} //ending y scope
Define the output of this program.
I answered the question during the interview that the output would be a runtime exception. To my understanding, y is declared private, and the instance method call() is trying to access the instance private variable y of another instance of class Q. How could that happen at all!? However answering this question wrongly didn't affect my interview too much because this is the kind of "tricky basic" question. But, answering wrongly means my years' Java experience needs rehab, that's terrible!
Could someone help me on this matter? I would be so much appreciated!

You can access private members of your own class, even from a different instance of the class.

private just means it can't be accessed by objects of another class, not any other objects. So one Q object can access the private members of another Q object.
[Note that if this were illegal, this would trigger a compiler error, not a runtime exception.]

Private variables are accessible within the program text of the declaring class. It doesn't matter if one instance tries to access variables in another instance, so long as the code is within the same class.
From the JLS section 6.6:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

private means that classes outside of this class cannot see the variable. Within this class definition, all methods and variables can be accessed.

Access restrictions should be enforced compile time not in run time, so the compiler should prevent compiling the code if it was wrong.
But an access modifier is applied on class level, so you can always access a private member from the class it self.
When you clone an object this is often useful since you can just set a bunch of values in the clone directly, which might have been hard to access otherwise. Also when comparing objects with an Equals method it can be quite handy that it is the class not the instance that defines the access restrictions.

As it was already pointed out, private members of the other instances are accessible from the class. Also, you were incorrect about the runtime exception: there will be no runtime exception even if you modify the code so that you try to access a private member of another class, the code will just fail to compile.

I think there will be a compilation problem because the attribute static int x = 11 is declared static and in the method call, the variable x is accessed by a this. You cannot make a this to a static variable in a class.
There is no problem with the private member y.

The correct "interview" answer is that whoever wrote code like this should be fired! Lousy class name, useless comments about y scope; non-standard use of "this" which should really only be used for instance variables, not class variables; re-using 'q' in the main and call methods.
It reminds me of the obfuscated C++ contests, exactly the sort of nonsense Java was designed to avoid.
Worse than this, though, is that it's very difficult to tell from the comments and the answers what the output of the program should be. Do I go by the '6' on the comment by Kevin?
I wish an admin would refactor all this. And I would tell an interviewer (if this really is an interview question, which I doubt) that we should run the code, get the answers, and then create a simple test to confirm that the answers don't change when we refactor the code to conform to standard usage.

Related

Local variable log defined in an enclosing scope must be final or effectively final

I'm new to lambda and Java8. I'm facing following error.
Local variable log defined in an enclosing scope must be final or
effectively final
public JavaRDD<String> modify(JavaRDD<String> filteredRdd) {
filteredRdd.map(log -> {
placeHolder.forEach(text -> {
//error comes here
log = log.replace(text, ",");
});
return log;
});
return null;
}
The message says exactly what the problem is: your variable log must be final (that is: carry the keyword final) or be effectively final (that is: you only assign a value to it once outside of the lambda). Otherwise, you can't use that variable within your lambda statement.
But of course, that conflicts with your usage of log. The point is: you can't write to something external from within the lambda ... so you have to step back and look for other ways for whatever you intend to do.
In that sense: just believe the compiler.
Beyond that, there is one core point to understand: you can not use a local variable that you can write to. Local variables are "copied" into the context of the lambda at runtime, and in order to achieve deterministic behavior, they can only be read, and should be constants.
If your use case is to write to some object, then it should be a field of your enclosing class for example!
So, long story short:
local variables used (read) inside a lambda must act like a constant
you can not write to local variables!
or the other way round: if you need something to write to, you have to use a field of your surrounding class for example (or provide a call back method)
The reason for this limitation is the same as the reason for the Java language feature that local variables accessed from within (anonymous) inner classes must be (effectively) final.
This answer by rgettman gets into the details of it. rgettman explains the limitations in clear detail and I link to that answer because the behavior of lambda expressions should be same as that of anonymous inner classes. Note that such limitation does not exist for class or instance variables, however. The main reason for this is slightly complicated and I couldn't explain it better than what Roedy Green does it here. Copying here only so it is at one place:
The rule is anonymous inner classes may only access final local
variables of the enclosing method. Why? Because the inner class’s
methods may be invoked later, long after the method that spawned it
has terminated, e.g. by an AWT (Advanced Windowing Toolkit) event. The
local variables are long gone. The anonymous class then must work with
flash frozen copies of just the ones it needs squirreled away covertly
by the compiler in the anonymous inner class object. You might ask,
why do the local variables have to be final? Could not the compiler
just as well take a copy of non-final local variables, much the way it
does for a non-final parameters? If it did so, you would have two
copies of the variable. Each could change independently, much like
caller and callee’s copy of a parameter, however you would use the
same syntax to access either copy. This would be confusing. So Sun
insisted the local be final. This makes irrelevant that there are
actually two copies of it.
The ability for an anonymous class to access the caller’s final local
variables is really just syntactic sugar for automatically passing in
some local variables as extra constructor parameters. The whole thing
smells to me of diluted eau de kludge.
Remember method inner classes can`t modify any value from their surrounding method. Your second lambda expression in forecach is trying to access its surrounding method variable (log).
To solve this you can avoid using lambda in for each and so a simple for each and re-palace all the values in log.
filteredRdd.map(log -> {
for (String text:placeHolder){
log = log.replace(text,",");
}
return log;
});
In some use cases there can be a work around. The following code complains about the startTime variable not being effectively final:
List<Report> reportsBeforeTime = reports.stream()
.filter(r->r.getTime().isAfter(startTime))
.collect(Collectors.toList());
So, just copy the value to a final variable before passing it to lambda:
final LocalTime finalStartTime = startTime;
List<Report> reportsBeforeTime = reports.stream()
.filter(r->r.getTime().isAfter(finalStartTime))
.collect(Collectors.toList());
However, If you need to change a local variable inside a lambda function, that won't work.
If you do not want to create your own object wrapper, you can use AtomicReference, for example:
AtomicReference<String> data = new AtomicReference<>();
Test.lamdaTest(()-> {
//data = ans.get(); <--- can't do this, so we do as below
data.set("to change local variable");
});
return data.get();
One solution is to encapsulate the code in an enclosing (inner class). You can define this:
public abstract class ValueContext<T> {
public T value;
public abstract void run();
}
And then use it like this (example of a String value):
final ValueContext<String> context = new ValueContext<String>(myString) {
#Override
public void run() {
// Your code here; lambda or other enclosing classes that want to work on myString,
// but use 'value' instead of 'myString'
value = doSomethingWithMyString(value);
}};
context.run();
myString = context.value;

Accessing local variables in the main method via reflection

Just having a play around with Java reflection and I think I'm getting the hang of it for the most part. I understand from this question/answer that, for the most part, I'm limited to static variables. If I have an instance of the class though, I can access non-static variables, which does make sense, I get that much.
Say I have the following two classes:
public class A
{
private static int _staticInt;
public static void main(String[] args)
{
B instanceOfB = new B();
}
}
public class B
{
private int _nonStaticInt;
public Game() {}
}
I understand how to access _staticInt, that's not an issue.
My understanding is that I can get the Field for _nonStaticInt in the same way (i.e. Field f = B.class.getDeclaredField("_nonStaticInt");). From other research (javadocs, trails, etc) I have gathered that I need an instance of B in order to get the value of _nonStaticInt.
So my question; Since main is static, is it possible to access instanceOfB in order to access the value of _nonStaticInt? I don't think it is possible, but I thought it's always best to consult people that are more knowledgable than myself before giving up on the idea.
Since main is static, is it possible to access instanceOfB in order to access the value of _nonStaticInt?
"No." Local variables (being in a static method or not) cannot be accessed with the Java Reflection API. Reflection only works at the type level, not the byte-code level2.
The stated understanding of the linked question is correct; reflection access of a non-static (instance) field logically requires an instance. That is, the issue then isn't about reflecting on the B type, the issue is about obtaining the B instance (which is assigned to a local variable) to reflect upon.
To do this the B instance has to be "bled" somehow - e.g. assigned to a static field or passed as an argument to a method/constructor from main1 - so that it can be used with reflection later as the object who's instance members are to be accessed.
The cleanest approach would probably be to pass the B instance down through the appropriate context (or "DI"), perhaps with the aide of IoC .. and maybe changing the type to avoid the use of reflection entirely.
1 Another possible way to "bleed" the B instance is to attach a debugger and inspect/use the local variable within the main methods executing frame - but this sounds like trying to swat a fly with a club.
2 Even tooling like BCEL/ASM wouldn't immediately help during the execution of the main method. Rather it would be used to deconstruct the method, add in the required hooks/code to "bleed" or use the instance created, and then construct a modified method to execute.
Yes, you can get the value of _nonStaticInt in that same way:
B instanceOfB = new B();
Field f = B.class.getDeclaredField("_nonStaticInt");
// Because the variable is private you need this:
f.setAccessible(true);
Object content = f.get(instanceOfB);
System.out.println(content);
The value will be 0, that is the default value for an int.

Declaring variable as final makes to code more efficient? [duplicate]

I've found a couple of references (for example) that suggest using final as much as possible and I'm wondering how important that is. This is mainly in the the context of method parameters and local variables, not final methods or classes. For constants, it makes obvious sense.
On one hand, the compiler can make some optimizations and it makes the programmer's intent clearer. On the other hand, it adds verbosity and the optimizations may be trivial.
Is it something I should make an effort to remember?
Obsess over:
Final fields - Marking fields as final forces them to be set by end of construction, making that field reference immutable. This allows safe publication of fields and can avoid the need for synchronization on later reads. (Note that for an object reference, only the field reference is immutable - things that object reference refers to can still change and that affects the immutability.)
Final static fields - Although I use enums now for many of the cases where I used to use static final fields.
Consider but use judiciously:
Final classes - Framework/API design is the only case where I consider it.
Final methods - Basically same as final classes. If you're using template method patterns like crazy and marking stuff final, you're probably relying too much on inheritance and not enough on delegation.
Ignore unless feeling anal:
Method parameters and local variables - I RARELY do this largely because I'm lazy and I find it clutters the code. I will fully admit that marking parameters and local variables that I'm not going to modify is "righter". I wish it was the default. But it isn't and I find the code more difficult to understand with finals all over. If I'm in someone else's code, I'm not going to pull them out but if I'm writing new code I won't put them in. One exception is the case where you have to mark something final so you can access it from within an anonymous inner class.
Edit: note that one use case where final local variables are actually very useful as mentioned by #adam-gent is when value gets assigned to the var in the if/else branches.
Is it something I should make an effort to remember to do?
No, if you are using Eclipse, because you can configure a Save Action to automatically add these final modifiers for you. Then you get the benefits for less effort.
I use final all the time to make Java more expression based. See Java's conditions (if,else,switch) are not expression based which I have always hated especially if your used to functional programming (ie ML, Scala or Lisp).
Thus you should try to always (IMHO) use final variables when using conditions.
Let me give you an example:
final String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
break;
case JOB_POSTING_IMPORT:
name = "Blah";
break;
default:
throw new IllegalStateException();
}
Now If add another case statement and do not set name the compiler will fail. The compiler will also fail if you do not break on every case (that you set the variable). This allows you to make Java very similar to Lisp's let expressions and makes it so your code is not massively indented (because of lexical scoping variables).
And as #Recurse noted (but apparently -1 me) you can do the preceding with out making String name final to get the compiler error (which I never said you couldn't) but you could easily make the compiler error go away setting name after the switch statement which throws away the expression semantics or worse forgetting to break which you cannot cause an error (despite what #Recurse says) without using final:
String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
//break; whoops forgot break..
//this will cause a compile error for final ;P #Recurse
case JOB_POSTING_IMPORT:
name = "Blah";
break;
}
// code, code, code
// Below is not possible with final
name = "Whoops bug";
Because of the bug setting name (besides forgetting to break which also another bug) I can now accidentally do this:
String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
break;
//should have handled all the cases for pluginType
}
// code, code, code
// Below is not possible with final
name = "Whoops bug";
The final variable forces a single evaluation of what name should be. Similar to how a function that has a return value must always return a value (ignoring exceptions) the name switch block will have to resolve name and thus bound to that switch block which makes refactoring chunks of code easier (ie Eclipe refactor: extract method).
The above in OCaml:
type plugin = CandidateExport | JobPostingImport
let p = CandidateExport
let name = match p with
| CandidateExport -> "Candidate Stuff"
| JobPostingImport -> "Blah" ;;
The match ... with ... evaluates like a function ie expression. Notice how it looks like our switch statement.
Here is an example in Scheme (Racket or Chicken):
(define name
(match b
['CandidateExport "Candidate Stuff"]
['JobPostingImport "Blah"]))
The development-time benefits of "final" are at least as significant as the run-time benefits. It tells future editors of the code something about your intentions.
Marking a class "final" indicates that you've not made an effort during design or implementation of the class to handle extension gracefully. If the readers can make changes to the class, and want to remove the "final" modifier, they can do so at their own risk. It's up to them to make sure the class will handle extension well.
Marking a variable "final" (and assigning it in the constructor) is useful with dependency injection. It indicates the "collaborator" nature of the variable.
Marking a method "final" is useful in abstract classes. It clearly delineates where the extension points are.
Well, this all depends on your style... if you LIKE seeing the final when you won't be modifying the variable, then use it. If you DON'T LIKE seeing it... then leave it out.
I personally like as little verbosity as possible, so I tend to avoid using extra keywords that aren't really necessary.
I prefer dynamic languages though, so it's probably no surprise I like to avoid verbosity.
So, I would say just pick the direction you are leaning towards and just go with it (whatever the case, try to be consistent).
As a side note, I have worked on projects that both use and don't use such a pattern, and I have seen no difference in the amount of bugs or errors... I don't think it is a pattern that will hugely improve your bug count or anything, but again it is style, and if you like expressing the intent that you won't modify it, then go ahead and use it.
I've found marking method parameters and locals as final is useful as a refactoring aid when the method in question is an incomprehensible mess several pages long. Sprinkle final liberally, see what "cannot assign to final variable" errors the compiler (or your IDE) throws up, and you just might discover why the variable called "data" ends up null even though several (out of date) comments swear that can't happen.
Then you can fix some of the errors by replacing the reused variables with new variables declared closer to the point of use. Then you find you can wrap whole parts of the method in scoping braces, and suddenly you're one IDE keypress away from "Extract Method" and your monster just got more comprehensible.
If your method is not already an unmaintainable wreck, I guess there might be value in making stuff final to discourage people from turning it into said wreck; but if it's a short method (see: not unmaintainable) then you risk adding a lot of verbosity. In particular, Java function signatures are hard enough to fit into 80 characters as it is without adding six more per argument!
It is useful in parameters to avoid change the parameter value by accident and introduce a subtle bug. I use to ignore this recommendation but after spending some 4 hrs. in a horrible method ( with hundreds of lines of code and multiple fors, nested ifs and all sort of bad practices ) I would recommend you to do it.
public int processSomethingCritical( final int x, final int y ){
// hundreds of lines here
// for loop here...
int x2 = 0;
x++; // bug aarrgg...
// hundreds of lines there
// if( x == 0 ) { ...
}
Of course in a perfect world this wouldn't happen, but.. well.. sometimes you have to support others code. :(
If you are writing a application that someone will have to read the code after, say, 1 year, then yes, use final on variable that should not be modified all the time. By doing this, your code will be more "self-documenting" and you also reduce the chance for other developers to do silly things like using a local constant as a local temporary variable.
If you're writing some throwaway code, then, nah, don't bother to identify all the constant and make them final.
I will use final as much as I can. Doing so will flag if you unintentionally change the field. I also set Method parameters to final. Doing so I have caught several bug from code I have taken over when they try to 'set' a parameter forgetting Java passes by value.
It's not clear from the question whether this is obvious, but making a method parameter final affects only the body of the method. It does NOT convey any interesting information about the method's intentions to the invoker. The object being passed in can still be mutated within the method (finals are not consts), and the scope of the variable is within the method.
To answer your precise question, I wouldn't bother making an instance or local variable (including method parameters) final unless the code required it (e.g. the variable is referenced from an inner class), or to clarify some really complicated logic.
For instance variables, I would make them final if they are logically constants.
There are many uses for the variable final. Here are just a few
Final Constants
public static class CircleToolsBetter {
public final static double PI = 3.141;
public double getCircleArea(final double radius) {
return (Math.pow(radius, 2) * PI);
}
}
This can be used then for other parts of your codes, or accessed by other classes, that way if you would ever change the value you wouldn't have to change them one by one.
Final Variables
public static String someMethod(final String environmentKey) {
final String key = "env." + environmentKey;
System.out.println("Key is: " + key);
return (System.getProperty(key));
}
}
In this class, you build a scoped final variable that adds a prefix to the parameter environmentKey. In this case, the final variable is final only within the execution scope, which is different at each execution of the method. Each time the method is entered, the final is reconstructed. As soon as it is constructed, it cannot be changed during the scope of the method execution. This allows you to fix a variable in a method for the duration of the method. see below:
public class FinalVariables {
public final static void main(final String[] args) {
System.out.println("Note how the key variable is changed.");
someMethod("JAVA_HOME");
someMethod("ANT_HOME");
}
}
Final Constants
public double equation2Better(final double inputValue) {
final double K = 1.414;
final double X = 45.0;
double result = (((Math.pow(inputValue, 3.0d) * K) + X) * M);
double powInputValue = 0;
if (result > 360) {
powInputValue = X * Math.sin(result);
} else {
inputValue = K * Math.sin(result); // <= Compiler error
}
These are especially useful when you have really long lines of codes, and it will generate compiler error so you don't run in to logic/business error when someone accidentally changes variables that shouldn't be changed.
Final Collections
Different case when we are talking about Collections, you need to set them as an unmodifiable.
public final static Set VALID_COLORS;
static {
Set temp = new HashSet( );
temp.add(Color.red);
temp.add(Color.orange);
temp.add(Color.yellow);
temp.add(Color.green);
temp.add(Color.blue);
temp.add(Color.decode("#4B0082")); // indigo
temp.add(Color.decode("#8A2BE2")); // violet
VALID_COLORS = Collections.unmodifiableSet(temp);
}
otherwise, if you don't set it as unmodifiable:
Set colors = Rainbow.VALID_COLORS;
colors.add(Color.black); // <= logic error but allowed by compiler
Final Classes and Final Methods cannot be extended or overwritten respectively.
EDIT:TO ADDRESS THE FINAL CLASS PROBLEM REGARDING ENCAPSULATION:
There are two ways to make a class final. The first is to use the keyword final in the class declaration:
public final class SomeClass {
// . . . Class contents
}
The second way to make a class final is to declare all of its constructors as private:
public class SomeClass {
public final static SOME_INSTANCE = new SomeClass(5);
private SomeClass(final int value) {
}
Marking it final saves you the trouble if finding out that it is actual a final, to demonstrate look at this Test class. looks public at first glance.
public class Test{
private Test(Class beanClass, Class stopClass, int flags)
throws Exception{
// . . . snip . . .
}
}
Unfortunately, since the only constructor of the class is private, it is impossible to extend this class. In the case of the Test class, there is no reason that the class should be final. The Test class is a good example of how implicit final classes can cause problems.
So you should mark it final when you implicitly make a class final by making it's constructor private.
Somewhat of a trade-off as you mention, but I prefer explicit use of something over implicit use. This will help remove some ambiguity for future maintainers of code - even if it is just you.
If you have inner (anonymous) classes, and the method needs to access variable of the containing method, you need to have that variable as final.
Other than that, what you've said is right.
Use final keyword for a variable if you are making that variable as immutable
By declaring the variable as final, it aids developers to rule out possible modification issues of variables in highly multi-threaded environment.
With java 8 release, we have one more concept called "effectively final variable". A non-final variable can heave as final variable.
local variables referenced from a lambda expression must be final or effectively final
A variable is considered effective final if it is not modified after initialization in the local block. This means you can now use the local variable without final keyword inside an anonymous class or lambda expression, provided they must be effectively final.
Till Java 7, you cannot use a non-final local variable inside an anonymous class, but from Java 8 you can
Have a look at this article
First of all, the final keyword is used to make a variable constant. Constant means it does not change. For example:
final int CM_PER_INCH = 2.54;
You would declare the variable final because a centimeter per inch does not change.
If you try to override a final value, the variable is what it was declared first. For example:
final String helloworld = "Hello World";
helloworld = "A String"; //helloworld still equals "Hello World"
There is a compile error that is something like:
local variable is accessed from inner class, must be declared final
If your variable cannot be declared final or if you don't want to declare it final try this:
final String[] helloworld = new String[1];
helloworld[0] = "Hello World!";
System.out.println(helloworld[0]);
helloworld[0] = "A String";
System.out.println(helloworld[0]);
This will print:
Hello World!
A String

the static concept in java

I can't seem to understand the static key word (java) so I googled it up and viewed a thread in this website, though I'm sure the answer was conclusive and clear -it always is over here- I didn't seem to understand it for two reasons; I'm not a native English speaker and the language was a bit vague for me, and it lacked exemples of use in classes, instance of classes, interfaces (if possible), instance of interfaces and variables, lists and arrays ect.
I would really appreciate any help and please keep the English as simple as possible ;)
Thank you
Aditsan
Note from editor: Please note that the original poster is asking for examples, and is not a native English speaker as you provide answers. From the comments, it appears that OP doesn't understand the concept well enough to ask about the parts that don't make sense yet, so examples would be awesome! It may take extra details and multiple different explanations to find the combination of answers that works best.
I think it helps to understand what non-static means, i.e. field/methods/... that are declared without the keyword static.
Every field declared without the keyword static exists as part of an object. If you have two objects, each of these two objects has a field with possibly different contents:
class X {
int f;
}
X x1 = new X();
X x2 = new X();
x1.f = 5;
x2.f = 10;
// x1.f still is 5
However, static fields exist not per object, but per class. So in the following example, there is only one field g no matter how many (if any!) objects of class Y you have:
class Y {
static int g;
}
Y y1 = new Y();
Y y2 = new Y();
y1.g = 5;
y2.g = 10;
// y1.g is 10, because y1.g and y2.g mean the exact same thing
I personally think accesses to static fields should be made using the class (Y.g) instead of mentioning object instances (y1.g), so that the existence without any object instance is more explicit.
For methods the difference is that non-static methods are associated to an object instance, which can be accesses using this inside the method. When invoking a method declared with void m() you can access non-static (and static) fields of the object it is invoked on (so for x1.m() from the example above you can get to the field containing 5, for x2.m() you can access the field containing 10.
Static methods, however, can be invoked without having a (corresponding?) object around. If the declaration is static void n() inside class Y, you can call this method using Y.n() or y1.n() (if y1 is an instanceof Y, as above). Here, too, I prefer the first way of writing it down. Because in static methods you do not have a reference to the object instance (which is named this in non-static methods), you cannot access specific non-static fields from inside a static method - simply because there is no clear association to a specific object.
Regarding static and class definitions: This is rather advanced. You can declare a class inside another class. If the inner class is not static, every object instance of the inner class also has a reference to an instance of the outer class (which also means that you only can create an instance of the inner class if you have an instance of the outer class). This is not always what you want. By declaring the inner class static it just exists and can be used, more or less, like a class defined in its own file.
Basically, static implies/provides two things:
1) Only one instance of an "item" exists in the whole system (JVM)
2) Static "items" are also context/state free
To explain (1) above: Suppose you have a Meal Token issuer. No matter how many users/processes are there in the system, all tokens must be issued by a single "thing". You would develop that "thing" as static. You would then decide what that "thing" is. It could be a class that does a complex operation and implements a complex business rule. Then you would have a single static class issuing tokens in "a single uniform way" for the whole system. Some times, all that matters is that the token should be "static" but how it is issued could be non-static. Then you would simply implement a "Static" token counter.
To explain (2) : Going by what is said for (1) above, you can easily see why it is important that the static "things" operate in a context-free manner. That is, they do not know who calls them or for what purpose. When they are called, they do not borrow anything from the past, they need all inputs from the current caller, and they just do their job, and remember nothing for the future.

What is the gain from declaring a method as static

I've recently been looking through my warnings in Eclipse and come across this one:
It will give a compiler warning if the method can be declared as static.
[edit] Exact quote within the Eclipse help, with stress on private and final:
When enabled, the compiler will issue an error or a warning for
methods which are private or final and which refer only to static
members.
Yes I know I can turn it off, but I want to know the reason for turning it on?
Why would it be a good thing to declare every method possible as static?
Will this give any performance benefits? (in a mobile domain)
Pointing out a method as static, I suppose is showing that you don't use any instance variables therefore could be moved to a utils style class?
At the end of the day should I just turn this off 'ignore' or should I fix the 100+ warnings it has given me?
Do you think this is just extra keywords that dirty the code, as the compiler will just inlines these methods anyway? (kind of like you don't declare every variable you can final but you could).
Whenever you write a method, you fulfill a contract in a given scope. The narrower the scope is, the smaller the chance is that you write a bug.
When a method is static, you can't access non-static members; hence, your scope is narrower. So, if you don't need and will never need (even in subclasses) non-static members to fulfill your contract, why give access to these fields to your method? Declaring the method static in this case will let the compiler check that you don't use members that you do not intend to use.
And moreover, it will help people reading your code understand the nature of the contract.
That's why it's considered good to declare a method static when it's actually implementing a static contract.
In some cases, your method only means something relative to an instance of your class, and it happens that its implementation doesn't actually use any non-static field or instance. In such cases, you would not mark the method static.
Examples of where you would not use the static keyword:
An extension hook which does nothing (but could do something with instance data in a subclass)
A very simple default behavior meant to be customisable in a subclass.
Event handler implementation: implementation will vary with the class of the event handler but will not use any property of the event handler instance.
There is no concept with optimization here.
A static method is static because you explicitly declare that method doesn't rely on any instance the enclosing class just because it doesn't need to. So that Eclipse warning, as stated in documentation:
When enabled, the compiler will issue an error or a warning for methods which are private or final and which refer only to static members.
If you don't need any instance variable and your method is private (can't be called from outside) or final (can't be overriden) then there is no reason to let it be a normal method instead that a static one. A static method is inherently safer even just because you are allowed to do less things with it (it doesn't need any instance, you don't have any implicit this object).
I've no info on the performance, I suppose it is marginally better at most, since the code does not need to do dynamic dispatch based on the type.
However, a much stronger argument against refactoring into static methods is that currently using static is considered bad practice. Static methods / variables do not integrate well into an object oriented language and also, hard to test properly. This is the reason why some newer languages forego the concept of static methods/variables altogether, or try to internalize it into the language in a way that plays better with OO (eg Objects in Scala).
Most of the time, you need static methods to implement functions that are only using parameters as an input and producing an output using that (eg utility/helper functions) In modern languages, there is a first class Function concept that allows that, so static is not needed. Java 8 will have lambda expressions integrated, so we are moving into this direction already.
1. Declaring method static gives slight performance benefit, but what is more useful, it allows using it without having an object instance at hand (think of for example about factory method or getting a singleton). It also serves the documentational purpose of telling the nature of the method. This documentational purpose should not be ignored, as it gives immediate hint about the nature of the method to the readers of the code and users of the API and also serves as a tool of thinking for the original programmer - being explicit about the intended meaning helps you also think straight and produce better quality code (I think based on my personal experience, but people are different). For example, it is logical and hence desirable to distinguish between methods operating on a type and methods acting on an instance of the type (as pointed out by Jon Skeet in his comment to a C# question).
Yet another use case for static methods is to mimic procedural programming interface. Think of java.lang.System.println() class and the methods and attributes therein. The class java.lang.System is used like a grouping name space rather than an instantiable object.
2. How can Eclipse (or any other programmed or other kind of - biocomposable or non-biocomposable - entity) know for sure which method could be declared as static? Even if a base class is not accessing instance variables or calling non-static methods, by the mechanism of inheritance the things can change. Only if the method cannot be overridden by inheriting subclass, can we claim with 100% certainty that the method really can be declared static. Overriding a method is impossible exactly in the two cases of being
private (no subclass can use it directly and does not even in principle know about it), or
final (even if accessible by the subclass, there is no way to change the method to refer to instance data or functions).
Hence the logic of the Eclipse option.
3. The original poster also asks: "Pointing out a method as static, I suppose is showing that you don't use any instance variables therefore could be moved to a utils style class?" This is a very good point. Sometimes this kind of design change is indicated by the warning.
It is very useful an option, which I would personally make sure to enable, were I to use Eclipse and were I to program in Java.
See Samuel's answer on how the scope of the method changes.
I guess, this is the main aspect of making a method static.
You also asked about performance:
There might be a tiny performance gain, because a call to a static method
does not need the implicit "this" reference as parameter.
However, this performance impact is really tiny. Therefore, it's all about the scope.
From the Android Performance guidelines:
Prefer Static Over Virtual If you don't need to access an object's
fields, make your method static. Invocations will be about 15%-20%
faster. It's also good practice, because you can tell from the method
signature that calling the method can't alter the object's state.
http://developer.android.com/training/articles/perf-tips.html#PreferStatic
Well, the Eclipse documentation says about the warning in question:
Method can be static
When enabled, the compiler will issue an error or a warning for
methods which are private or final and which refer only to static
members
I think it pretty much says it all. If the method is private and final and only refers to static members, the method in question might just as well be declared static and by this, make evident that we only intend to access static content from it.
I honestly don't think there is any other mysterious reason behind it.
I was missing some numbers for the speed differences. So I tried to benchmark them which turned out to be not so easy: Java loop gets slower after some runs / JIT's fault?
I finally used Caliper and the results are the same as running my tests by hand:
There is no measurable difference for static/dynamic calls. At least not for Linux/AMD64/Java7.
The Caliper Results are here: https://microbenchmarks.appspot.com/runs/1426eac9-36ca-48f0-980f-0106af064e8f#r:scenario.benchmarkSpec.methodName,scenario.vmSpec.options.CMSLargeCoalSurplusPercent,scenario.vmSpec.options.CMSLargeSplitSurplusPercent,scenario.vmSpec.options.CMSSmallCoalSurplusPercent,scenario.vmSpec.options.CMSSmallSplitSurplusPercent,scenario.vmSpec.options.FLSLargestBlockCoalesceProximity,scenario.vmSpec.options.G1ConcMarkStepDurationMillis
and my own results are:
Static: 352 ms
Dynamic: 353 ms
Static: 348 ms
Dynamic: 349 ms
Static: 349 ms
Dynamic: 348 ms
Static: 349 ms
Dynamic: 344 ms
The Caliper Test class was:
public class TestPerfomanceOfStaticMethodsCaliper extends Benchmark {
public static void main( String [] args ){
CaliperMain.main( TestPerfomanceOfStaticMethodsCaliper.class, args );
}
public int timeAddDynamic( long reps ){
int r=0;
for( int i = 0; i < reps; i++ ) {
r |= addDynamic( 1, i );
}
return r;
}
public int timeAddStatic( long reps ){
int r=0;
for( int i = 0; i < reps; i++ ) {
r |= addStatic( 1, i );
}
return r;
}
public int addDynamic( int a, int b ){
return a+b;
}
private static int addStatic( int a, int b ){
return a+b;
}
}
And my own Test class was:
public class TestPerformanceOfStaticVsDynamicCalls {
private static final int RUNS = 1_000_000_000;
public static void main( String [] args ) throws Exception{
new TestPerformanceOfStaticVsDynamicCalls().run();
}
private void run(){
int r=0;
long start, end;
for( int loop = 0; loop<10; loop++ ){
// Benchmark
start = System.currentTimeMillis();
for( int i = 0; i < RUNS; i++ ) {
r += addStatic( 1, i );
}
end = System.currentTimeMillis();
System.out.println( "Static: " + ( end - start ) + " ms" );
start = System.currentTimeMillis();
for( int i = 0; i < RUNS; i++ ) {
r += addDynamic( 1, i );
}
end = System.currentTimeMillis();
System.out.println( "Dynamic: " + ( end - start ) + " ms" );
// Do something with r to keep compiler happy
System.out.println( r );
}
}
private int addDynamic( int a, int b ){
return a+b;
}
private static int addStatic( int a, int b ){
return a+b;
}
}
The methods you can declare as static are the ones that don't require instantiation, such as
public class MyClass
{
public static string InvertText(string text)
{
return text.Invert();
}
}
Which you can then in return call out in any other class without instanciating that class.
public class MyClassTwo
{
public void DoSomething()
{
var text = "hello world";
Console.Write(MyClass.InvertText(text));
}
}
... But that's something you probably already know. It doesn't give you any real benefits per se, other than making it more clear that the method doesn't use any instance variables.
In other words, you can most safely just turn it off completely. If you know you will never use a method in other classes (in which case it should just be private), you don't need it to be static at all.

Categories