Why Must this method be static(Java)? - java

For some background, I'm currently on chapter 8 in my book, we finished talking about arraylists, arrays, if statements, loops etc. Now this part of the book talks about call by reference,value and some other pretty neat things that seem odd to me at first.I've read What situation to use static and some other SO questions, and learned quite a bit as well.
Consider the following example my book gave (among many examples)
There is another reason why static methods are sometimes necessary. If
a method manipulates a class that you do not own, you cannot add it to
that class. Consider a method that computes the area of a rectangle.
The Rectangle class in the standard library has no such feature, and
we cannot modify that class. A static method solves this problem:
public class Geometry
{
public static double area(Rectangle rect)
{
return rect.getWidth() * rect.getHeight();
}
// More geometry methods can be added here.
}
Now we can tell you why the main method is static. When the program
starts, there aren’t any objects. Therefore, the first method in the
program must be a static method.
Ok, thats pretty cool, up until now I've just been really blindly putting public in front of all my methods, so this is great to know. But the review small problem on the next page caught my attention
The following method computes the average of an array list of numbers:
public static double average(ArrayList<Double> values)
Why must it be a static method?
Here I was like wait a sec. I'm pretty sure I did this without using static before. So I tried doing this again and pretty easily came up with the following
import java.util.ArrayList;
class ArrList
{
private double sum;
public ArrList()
{
sum = 0;
}
public double average(ArrayList <Double> values)
{
for(int i = 0; i < values.size() ; i++)
{
sum+=values.get(i);
}
return sum / values.size();
}
}
public class Average
{
public static void main(String [] args)
{
ArrList arrListObj = new ArrList();
ArrayList<Double> testArrList = new ArrayList<Double>();
testArrList.add(10.0);
testArrList.add(50.0);
testArrList.add(20.0);
testArrList.add(20.0);
System.out.println(arrListObj.average(testArrList));
}
}
TLDR
Why does my book say that public static double average(ArrayList<Double> values) needs to be static?
ATTEMPT AT USING STATIC
public class Average
{
public static void main(String [] args)
{
ArrayList<Double> testArrList = new ArrayList<Double>();
ArrayList<Double> testArrListTwo = new ArrayList<Double>();
testArrList.add(10.0);
testArrList.add(50.0);
testArrList.add(20.0);
testArrList.add(20.0);
testArrListTwo.add(20.0);
testArrListTwo.add(20.0);
testArrListTwo.add(20.0);
System.out.println(ArrList.average(testArrList));
System.out.println(ArrList.average(testArrListTwo)); // we don't get 20, we get 53.3333!
}
}

It doesn't.
The only method which needs to be static is the initial main() method. Anything and everything else is up to you as the programmer to decide what makes sense in your design.
static has nothing to do with public accessors (as you allude to), and it has nothing to do with the technical operation being performed. It has everything to do with the semantics of the operation and the class which holds it.
An instance (non-static) method exists on a particular instance of a class. Semantically it should perform operations related to that specific instance. A static method exists on a class in general and is more conceptual. It doesn't do anything to a particular instance (unless it's provided an instance of something as a method argument of course).
So you really just need to ask yourself about the semantics of the operation. Should you need new instance of an object to perform an operation? Or should the operation be available without an instance? That depends on the operation, on what the objects represent, etc.

If it is not static, then any other class that wants to use this method must first create an instance of this object.
From some other class:
Average.average(new ArrayList<Double>()); // legal only if static
new Average().average(new ArrayList<Double>()); // necessary if not static
// and only makes sense if Average can be instantiated in the first place
It's legal to make it an instance (i.e. not static) variable, but the method is actually harder to understand. If it is static then whoever reads the code knows it does not use any member variables of the class.
// In the class body
int x = 0; // member variable
public static double average() {
x = x + 1; // illegal
}
The less something can do, the easier to understand what it does do.

Static methods like the area, average are usually utility functions. You don't need any object to use an utility function. For example consider Math.pow you don't need to instantiate any object to use the power function, just use Math.pow(10.0, 2.0) to get (10.0)^2
In short :
Static method means class method, that is no instance of that object is needed to invoke.
whereas your average method is an instance method, you need an object to invoke that method.

Related

Does Java support static variables inside a function to keep values between invocations?

https://stackoverflow.com/a/572550/1165790
I want to use this feature in Java because the function that I'm designing is called rarely (but when it is called, it starts a recursive chain) and, therefore, I do not want to make the variable an instance field to waste memory each time the class is instantiated.
I also do not want to create an additional parameter, as I do not want to burden external calls to the function with implementation details.
I tried the static keyword, but Java says it's an illegal modifier. Is there a direct alternative? If not, what workaround is recommended?
I want it to have function scope, not class scope.
I want it to have function scope, not class scope.
Then you are out of luck. Java provides static (class scoped), instance and local variables. There is no Java equivalent to C's function-scoped static variables.
If the variable really needs to be static, then your only choice is to make it class scoped. That's all you've got.
On the other hand, if this is a working variable used in some recursive method call, then making it static is going to mean that your algorithm is not reentrant. For instance, if you try to run it on multiple threads it will fall apart because the threads will all try to use the same static ... and interfere with each other. In my opinion, the correct solution would be either to pass this state using a method parameter. (You could also use a so-called "thread local" variable, but they have some significant down-sides ... if you are worrying about overheads that are of the order of 200 bytes of storage!)
How are you going to keep a value between calls without "wasting memory"? And the memory consumed would be negligible.
If you need to store state, store state: Just use a static field.
Caution is advised when using static variables in multi-threaded applications: Make sure that you synchronise access to the static field, to cater for the method being called simultaneously from different threads. The simplest way is to add the synchronized keyword to a static method and have that method as the only code that uses the field. Given the method would be called infrequently, this approach would be perfectly acceptable.
Static variables are class level variables. If you define it outside of the method, it will behave exactly as you want it to.
See the documentation:
Understanding instance and Class Members
The code from that answer in Java...
public class MyClass {
static int sa = 10;
public static void foo() {
int a = 10;
a += 5;
sa += 5;
System.out.println("a = " + a + " sa = " + sa);
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
foo();
}
}
}
Output:
$ java MyClass
a = 15 sa = 15
a = 15 sa = 20
a = 15 sa = 25
a = 15 sa = 30
a = 15 sa = 35
a = 15 sa = 40
a = 15 sa = 45
a = 15 sa = 50
a = 15 sa = 55
a = 15 sa = 60
sa Only exists once in memory, all the instances of the class have access to it.
Probably you got your problem solved, but here is a little more details on static in Java. There can be static class, function or variable.
class myLoader{
static int x;
void foo(){
// do stuff
}
}
versus
class myLoader{
static void foo(){
int x;
// do stuff
}
}
In the first case, it is acting as a class variable. You do not have to "waste memory" this way. You can access it through myLoader.x
However, in the second case, the method itself is static and hence this itself belongs to the class. One cannot use any non-static members within this method.
Singleton design pattern would use a static keyword for instantiating the class only once.
In case you are using multi-threaded programming, be sure to not generate a race condition if your static variable is being accessed concurrently.
I agree with Bohemian it is unlikely memory will be an issue. Also, duplicate question: How do I create a static local variable in Java?
In response to your concern about adding an additional parameter to the method and exposing implementation details, would like to add that there is a way to achieve this without exposing the additional parameter. Add a separate private function, and have the public function encapsulate the recursive signature. I've seen this several times in functional languages, but it's certainly an option in Java as well.
You can do:
public int getResult(int parameter){
return recursiveImplementation(parameter, <initialState>)
}
private int recursiveImplementation(int parameter, State state){
//implement recursive logic
}
Though that probably won't deal with your concern about memory, since I don't think the java compiler considers tail-recursive optimizations.
The variables set up on the stack in the recursive call will be function (frame) local:
public class foo {
public void visiblefunc(int a, String b) {
set up other things;
return internalFunc(a, b, other things you don't want to expose);
}
private void internalFunc(int a, String b, other things you don't want to expose) {
int x; // a different instance in each call to internalFunc()
String bar; // a different instance in each call to internalFunc()
if(condition) {
internalFunc(a, b, other things);
}
}
}
Sometimes state can be preserved by simply passing it around. If required only internally for recursions, delegate to a private method that has the additional state parameter:
public void f() { // public API is clean
fIntern(0); // delegate to private method
}
private void fIntern(int state) {
...
// here, you can preserve state between
// recursive calls by passing it as argument
fIntern(state);
...
}
How about a small function-like class?
static final class FunctionClass {
private int state1; // whichever state(s) you want.
public void call() {
// do_works...
// modify state
}
public int getState1() {
return state1;
}
}
// usage:
FunctionClass functionObject = new FunctionClass();
functionObject.call(); // call1
int state1AfterCall1 = functionObject.getState1();
functionObject.call(); // call2
int state1AfterCall2 = functionObject.getState1();

Is static bad? How to remove static variables?

I have some code that I am working on. It's basically takes in user input and creates a directed graph. One person can travel one way, the other person the opposite. The output is the overlap of where they can visit.
I have most everything working the way that I want it to, but I am concerned with the use of static that I have. I don't seem to fully understand it and no matter where I look, I can't find out its exact use OR how to get rid of it.
Could someone please help me to understand what static is and why it would be helpful?
Also, would it be better to move most the code from MAIN to helper methods? If I do this I have to move all my variables from main to the top of the class and then they all have to be declared as static?!
The reason everything has to be static is because you aren't creating any objects. If you were to create an object by calling new in your main method, you could use non-static variables on that object. This isn't really a good place to give you a tutorial on why you might want to use object-oriented design; you can find one of those online to read (a commenter above gave a possible reference). But the reason everything has to be static is because it's all just running from the main method, which is always static in java. If you were to call new somewhere, you could use non-static variables.
Static makes a method or a variable accessible to all the instances of a class. It's like a constant, but for classes. To make it more easy to understand some code will do the work:
public class Example {
public static int numero;
}
public class Implementation {
public static void main (String args[]) {
Example ex1 = new Example();
Example ex2 = new Example();
Example.numero=10;
System.out.println("Value for instance 1 is: " + ex1.numero);
System.out.println("Value for instance 2 is: " + ex2.numero);
}
}
Running the follwing code will output:
Value for instance 1 is: 10
Value for instance 2 is: 10
Because you set the static variable numero (number in italian) to 10.
Got it?
It looks like a lot of your static methods (findNodeInList, etc) all take the ArrayList (which represents a map) as their first argument. So instead of having it static, you could have a class Map, which stores a list of nodes and has methods on them. Then the main method would read the input, but not have to manage any nodes directly. e.g:
class Map {
ArrayList<Node> nodes;
public void addNode(Node n) { nodes.add(n); }
public int findNodeInList(String s) { ... }
...
public static void main(String[] args) {
Map peggyMap = new Map();
Map samMap = new Map();
// Read the data
samMap.add(new Node(...));
}
}
This keeps all the stuff to do with nodes/maps well encapsulated and not mixed in with stuff to do with reading the data.
Static is useful if you going to be using the class/method throught out your program and you don't what to create a instance every time you need to use that method.
For ex
public class StaticExample {
public static void reusable() {
//code here
}
}
It means you can use it like this
StaticExample.reusable();
and you don't have to create an instance like this
StaticExample staticExample = new StaticExample();
staticExample.reuseable();
I hope this help you decide whether to use static or not.

What are some best practices and tricks when passing values from a main() to an Array Stack in a different class?

I am trying to pass values from my private static void main(...) into a class that has an array stack initialized in the constructor. I was wondering how to take the values I assign to a variable in the main() and push that value onto the array stack within this innerClass?
I know that the array stack works, I have implemented this class before without a problem, but I was only using the arrayStack() I had created and a main(). The addition of the third class is confusing me.
Without getting too deep in my code, I was hopping someone could explain (or point me to some resources) to me how to pass arguments to a stack that is initialized in a constructor, with arguments from the main() method of a different class (same package)?
Example of where I'm trying to get values to:
package program2;
public class Exec {
public Exec(DStack ds) {
/*I have initilized an arrayStack to hold doubles (i.e. DStack).
* I can use ds.push()/pop()/top() etc.
* I cannot take the value from Calculator.java and push that value
* here, which is what I need help understanding?
* */
ds.push(Calculator.i); //I would expect an error here, or the value stored in
//Calculator.i to be added to the stack. Instead program
//terminates.
}
}
Where I would like to take the values from:
package program2;
public class Calculator {
public static double i;
public static void main(String[] args) {
i=9; //I'm expecting that by using Calculator.i in the Exec class that
//I should be able to push 'i' onto the stack.
}
}
This question goes along with a question and answer I was able to get working yesterday here: Get answer from user input and pass to another class. There are three differences, one, I am no longer selecting an answer from the menu and performing an action. Two, I would like know how to get items on a stack versus comparing the String in a series of if/else statements. Lastly, I would like to know a little more detail about the nuts and bolts of this action.
You seem to completely misunderstand how an application works. When you launch your program, java executes your main method. All its instructions are executed in sequence until the end of the method is reached. If you haven't started any other thread from this method, when the last instruction in the main method has been executed, the program terminates.
In this case, the main method contains only one instruction:
i = 9;
So this instruction is executed, and since it's the last one, the program terminates. You don't even reference the Exec class anywhere, so this class isn't even loaded by the JVM.
If you want to use the Exec class, then you have to do something with is somewhere in the program. For example, you could do
i = 9;
DStack dstack = new DStack();
Exec exec = new Exec(dstack);
Note that storing something in a public static variable in order for some other object to be able to get this value is a very poor form of parameter passing. If an Exec object needs a value to work, then it should be an argument of its constructor:
public Exec(DStack ds, double value) {
ds.push(value);
}
and in the main method, you would use a local variable and not a public static variable:
double i = 9;
DStack dstack = new DStack();
Exec exec = new Exec(dstack, i);
If I understand your question correctly, you should create an instance of the Exec class. You can also create an instance of DStack within your program and pass it the Exec constructor after pushing the double value onto the stack.
package program2;
public class Calculator {
public static double i;
public static void main(String[] args) {
DStack dStack = new DStack();
dStrack.push(i);
Exec exec = new Exec(dStack);
}
}
I think you are confusing the concept of class vs. instance. You don't pass values to classes, you pass values to instances (static fields are sometimes called class variables and can make things confusing, but ignore that for now).
In a nutshell, a class is the code for that class you wrote. An instance is the actual thing that was spawned from that definition of class and actually does stuff. So the number one trick is to "instanciate" your class and create an instance. Then you pass whatever values you want to pass it like below:
class Foo {
public static main(String[] args) {
Bar bar = new Bar(); // <-- now you have an instance called bar
bar.arrayStack.push(args[0]); // <-- Now it's passed!
}
class Bar {
ArrayStack arrayStack;
Bar(){
arrayStack = new ArrayStack();
}
}

What's the difference between calling through and object vs class

What's the difference between calling a method through an object vs a class.
for example the Class Bob
public class SecretNumber() {
public static int secretNumber = 2;
public static void changeSecretNumber(){
secretNumber++;
}
}
What would be the difference if i called it like an object
SecretNumber secretNumber = new SecretNumber();
secretNumber.changeSecretNumber();
vs calling it like this
SecretNumber.changeSecretNumber();
How would one method effect the other?
The result is the same.
You should call it by class name, not through the instance, because no dynamic dispatch happens.
Most compilers will give you a warning, if you do that, too. Some people argue that it should have been made a compile error.
In Java, unless a class method is "static", you can't call it except through an object instance.
Here's an example of a method where it would make sense to declare it "static":
http://www.leepoint.net/notes-java/flow/methods/50static-methods.html
public static double mean(int[] p) {
int sum = 0; // sum of all the elements
for (int i=0; i
http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
The second form isn't valid Java. You can only call methods on a class if they are declared static.
Calling a method through a class is a static method. Unless you declare the method a static method, the compiler will give you a compile error .

Calling a method from outside a class in Java

This seems to be a common question on here but for all the ones I read, they seem to deal with different things.
I'm writing a program with a main class that manages an array of objects of a different class, and I'm having difficulty calling a print() method from this second class, from within the main class.
The Main class attempts to call print(), which is in the Unit class. The Unit class looks something like this:
public class Unit{
static int numOfUnits = 0;
public Unit[] units = new Unit[8];
private int unitID;
//constructors are here
public void print(){
for (int i = 0; i < units.length; i++)
System.out.print(units[i].unitID);
}
public void add(Unit unit){
mobs[numbofUnits] = unit;
numOfUnits++;
}
}
So what I'd like to happen is, through the Main class, I add new Unit objects to the units array. When I'm done adding them (using the call unitToAdd.add(unitToAdd) in the Main class) I would like to call Unit's print() method from within Main.
What I don't know is, whether or not, and where, to use the static modifier, how to refer to the variables in the print() method itself (that is, do I use this.unitID, units[i].unitID, etc) and so on.
What is confusing me is simply the nature of the print() method. I have setters and getters that work just fine since I completely understand that calling specificUnit.setID() is changing a specific variable for that specific object, but I don't know how to get methods like print() to work.
Thanks!
Simple answer - you need a Unit instance to invoke print(). I strongly recommend that you go back to the basics - Learning the Java Language.
You should probably avoid implementing a list of Units in Unit. You can avoid static state altogether by creating a UnitList class to store your list of units, maybe in an ArrayList, and then creating a UnitList instance that is local to your main method.
public static void main(String[] argv) {
UnitList myUnitList = new UnitList();
myUnitList.add(new Unit(...));
myUnitList.print();
}
That separates out the concern of tracking a set of units from the units themselves and avoids global mutable state which is hard to debug and unit test.
To answer your question though, below is the minimal set of changes with some explanation as to why they should be static or not.
public class Unit{
// static here since every unit does not need to have a number of units.
static int numOfUnits = 0;
// static here since every unit does not need to contain other units.
static Unit[] units = new Unit[8];
// no static here since every unit does need its own ID.
private int unitID;
//constructors are here
// static here since every unit does not need to know how
// to print a particular 8 units.
public static void print(){
for (int i = 0; i < numOfUnits; i++)
System.out.print(units[i].unitID);
}
// static here since every unit does not need to know how
// to add to a global list.
public static void add(Unit unit){
mobs[numbofUnits] = unit;
numOfUnits++;
}
}

Categories