One rule-of-thumb: ask yourself "Does it make sense to call this method, even if no object has been constructed yet?" If so, it should definitely be static.
So in a class Car you might have a method:
double convertMpgToKpl(double mpg)
...which would be static, because one might want to know what 35mpg converts to, even if nobody has ever built a Car. But this method (which sets the efficiency of one particular Car):
void setMileage(double mpg)
...can't be static since it's inconceivable to call the method before any Car has been constructed.
(By the way, the converse isn't always true: you might sometimes have a method which involves two Car objects, and still want it to be static. E.g.:
Car theMoreEfficientOf(Car c1, Car c2)
Although this could be converted to a non-static version, some would argue that since there isn't a "privileged" choice of which Car is more important, you shouldn't force a caller to choose one Car as the object you'll invoke the method on. This situation accounts for a fairly small fraction of all static methods, though.
One rule-of-thumb: ask yourself "Does it make sense to call this method, even if no object has been constructed yet?" If so, it should definitely be static.
So in a class Car you might have a method:
double convertMpgToKpl(double mpg)
...which would be static, because one might want to know what 35mpg converts to, even if nobody has ever built a Car. But this method (which sets the efficiency of one particular Car):
void setMileage(double mpg)
...can't be static since it's inconceivable to call the method before any Car has been constructed.
(By the way, the converse isn't always true: you might sometimes have a method which involves two Car objects, and still want it to be static. E.g.:
Car theMoreEfficientOf(Car c1, Car c2)
Although this could be converted to a non-static version, some would argue that since there isn't a "privileged" choice of which Car is more important, you shouldn't force a caller to choose one Car as the object you'll invoke the method on. This situation accounts for a fairly small fraction of all static methods, though.
Define static methods in the following scenarios only:
- If you are writing utility classes and they are not supposed to be changed.
- If the method is not using any instance variable.
- If any operation is not dependent on instance creation.
- If there is some code that can easily be shared by all the instance methods, extract that code into a static method.
- If you are sure that the definition of the method will never be changed or overridden. As static methods can not be overridden.
Are you asking about the reference scope or the existence scope? A public static method can be accessed by any class which can access the method's class, given standard Java package naming/scoping rules. Note that this implies (as part of the rules) that access is only available to classes in the same JVM.
The existence of the data is scoped to the instance of java.lang.Class that represents the class being loaded (I'm sure there's some fancy term for this). At most this is until the end of execution of the JVM, but a class can, under some circumstances, be "unloaded" earlier.
It should also be noted that more than one copy (java.lang.Class instance) of a given class can be loaded in a given JVM at the same time, and each copy of the class would have its own static variables. However, this would be pretty rare.
Let's assume you are talking about whether there is one "instance" of data and the corresponding static method.
What is the scope of a static method in Java?
1) (Eclipse) Project level
No. Source code / build time "project" structure has direct relevance to the runtime behaviour of a Java program. (The project build produces one or more .class files, typically bundled up as JAR or WAR or EAR or whatever archive files. The runtime behaviour depends on how those files are loaded into a JVM.)
2) Application level 3) JVM level
Yes, no, maybe.
The actual "existence scope" (as someone described it) depends on the identity of the class type. Under normal circumstances, a class is loaded into a JVM once. That gives you one class type, and there is one instance of the static variables for that type.
However, if your classloaders are organized in the right way, you can then load the class again. This gives you a new class type (with the same name as the previous one ... but a different classloader), and that class type has its own set of static variable.
An application that is run using the java command via its main method will typically only load the class once. (You'd typically need to create a new classloader at runtime to change this.)
However, applications (e.g. webapps) that are run within frameworks are subject to whatever the framework does. And a typical appserver framework uses a separate classloader for each webapp. So if you include a JAR file in multiple webapps and run them in the same appserver, you are likely to get multiple class types with the same name and different classloaders .... and different static variable sets.
But it doesn't end there, because when you call MyClass.getData() in another class (e.g. OtherClass), the variable that is accessed depends on which MyClass type the OtherClass code has been bound to. And that depends on what the OtherClass type's classloader bound it to ... when it loaded the OtherClass class.
This can all get rather complicated, but normally you don't need to worry about it. The complexity only happens when something is doing "clever classloader stuff", and even, then the clever stuff is usually implementing separation of "apps" that you want to happen.
java - Is there an easy way to start a static function of a class in a few clicks in Eclipse? - Stack Overflow
java - What is the gain from declaring a method as static - Stack Overflow
java - Why is Eclipse suggesting I make my method static - Stack Overflow
java - Eclipse : transform static method invocation to a static import - Stack Overflow
Videos
A static method cannot be run, except of course if this method is the main(String... args) method.
However, consider creating a JUnit test case for this method instead.
Create a JUnit Test Case within Eclipse. In the wizard, you can indicate the class that provides your static method in the Class under test: field. Then Eclipse will give you the ability to create one test method per existing method on the class under test.
Once your JUnit test is created, simply right-click on this Java class and select Run as > JUnit test. The shortcut is Alt+Shift+X, then T.
You can also consider doing some Test Driven Development...
Create a JUnit Test class for your static methods. Once created, it's only one click to test your static methods.
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).
Based on your earlier question, I think may not be fully digging the concept of the local variable. In this method:
public String setOption(String option) throws IOException
{
option = stdin.readLine();
return option;
}
option is a local variable. You pass the initial value for that variable as an argument to the setOption method each time you call it (and you happen to ignore that value), but with that detail out of the way, this is the same as
public String setOption() throws Exception
{
String option = stdin.readLine();
return option;
}
Now, local variables are something completely different from instance or class variables: they are valid only within a method body, and exist only during the time that method is executing. With that in mind, let's look at this code:
static BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in));
public static void main(String[] args) throws IOException
{
Patient.setOption(null);
}
Here you are basically misusing a class variable stdin for something which should have been a local variable:
public static void main(String[] args) throws IOException
{
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
Patient.setOption(null);
}
On to the question of your method call... setOption is currently an instance method, which means it must be called in the context of an instance. You are calling it as-is, with no instances of Patient involved. If you continue down this road, you won't be able to represent more than a single patient, probably not your idea. So you want to keep the method as it is and create an instance of Patient:
Patient p = new Patient();
p.setOption(...);
In your overall design it is not clear what role setOption should play, but it is not a good idea that it uses the static stdin variable (I already made it local above). You want to pass any data read from stdin into the setOption method and thus decouple it from the input reading logic.
You (probably) need to create an object of the Patient class.
Patient myPatient = new Patient();
myPatient.setOption(null);
It's hard to necessarily know what you want to do with such limited information. I don't know what you intend to do with the Patient class, but my best guess? It makes sense to do it this way, given you're trying to call a method with a setter naming convention.
If you don't intend to instantiate an object and go the route of making setOption a static method, then you should probably change the method name.
With a more in-depth explanation of what exactly you're trying to accomplish (not even talking pseudo-code, just a very abstract idea of what you're trying to do), it would be easier to explain more about static here (with your specific example) and what you should be doing, etc.
I'm not sure exactly what the situation is, but if you're looking to execute the static method on a class without knowing the class type (i.e. you don't know it's SomeType, you just have the Class object), if you know the name and parameters of the method you could use reflection and do this:
Class c = getThisClassObjectFromSomewhere();
//myStaticMethod takes a Double and String as an argument
Method m = c.getMethod("myStaticMethod", Double.class, String.class);
Object result = m.invoke(null, 1.5, "foo");
A static method, by definition, is called on a class and not on an instance of that class.
So if you use:
SomeClass.someStaticMethod()
you are instantiating nothing (leave aside the class loading and instantiation of the SomeClass class itself, which the JVM handles and is way out of your scope).
This is opposed to a regular method called on an object, which has already been instantiated:
SomeObject o = someObject; // had to be instantiated *somewhere*
o.someMethod();