What does a static method mean, conceptually?

I know how to use a static method, I know when to use a static method, I know generally what it means (I can use it without instantiating an object of the class, i.e., it exists at runtime independently of the corresponding object). What I don’t get is what a static method actually is. For a variable it’s pretty obvious, it’s loaded into memory at launch time (or at the very least, as soon as it’s referenced if you want to conserve memory), and pointed to by reference whenever you access it, but what is a static method? Is it a “partial class,” meaning the class is already instantiated to some degree with those methods?

I assume I’m overthinking the abstraction, my hunch is that since numbers are numbers no matter what, and it’s petty much handled exactly like a static variable, but I still can’t figure some things out (is the method copied onto the stack? Is the program counter set to a special block of memory that contains the method?)

I tend to work in Java, if it matters, but I’m interested in a more general answer, since I assume the basic concept is pretty platform independent.

A static method is sort of similar to a static variable, except that a static variable contains data, the contents of which have absolutely no meaning to the processor, whereas a static method contains actual code that can be executed by the processor. Also, in most modern environments, code is almost always read-only, whereas data may either be read-write or read-only.

When a method is loaded, the environment simply maps the executable instructions in that method into executable memory, so that they will be available when someone tries to call the method. The code of a static method, just like any other methods, is never allocated on the stack; however, the stack will be available to a static method (also just like any other methods) to hold any local variables as needed.

Hope this helps and I haven’t confused you further…

Static methods are used mostly as a subroutine would be in pre-OOP languages. It is a method that can be called from other classes, and is not associated with other members of it’s class. If you wanted to create a set of math functions, you would make them static methods so they could be called from any other class without instantiating an object, and they wouldn’t require any of the non-static methods or properties of the class to funtion since all the arguments are passed explicitly.

So what is it? Basically it’s a method, which is code, and it is not passed a reference to any ‘this’ object when it is called. This construct is used by some languages to implement a ‘new’ method, since you can’t instantiate an object which doesn’t exist yet.

I think by your description of the question you are talking about something that is language/implementation dependent.

As a point of comparison, in Ruby everything is an object. When you create a class, it’s an object (of class “Class”). Now that object can have methods, just the way any other object can have them. It’s fairly simple, but that doesn’t mean it’s done that way in other languages. To be accurate I think you could say there’s no exact translation of Java’s static methods because of the different approach of the languages.

Here’s a bit more on the details, highlighting a few of the differences.

No, Waffle Decider, that cleared things up immensely. TriPolar’s continuation of it not having to be passed a “this” would have confused me, had I not seen function defs in python before, but it actually cleared things up further given that. Thanks a lot guys!

Panama, yeah, I think it is implementation dependent, but static is a sort of general concept as “does not need to be instantiated” so I figured that it was probably at least similar ENOUGH between languages, maybe that was a bad assumption. Obviously I’m not asking about languages that do not contain a notion of static. With Ruby, this stuck out and made a lot of sense, however:

Which is actually pretty in line with “does not require a this object” as well as it being available in executable memory by default (well, “default”). So they’re not necessarily the same, but they’re pretty similar, even if the high level details show a large difference.

This really helped, thanks guys.

Conceptually speaking, normal methods are bound to an object, i.e. an instance of a class. Static methods are bound to the class itself.

Well, yes, I understood that. I was asking at more of lower/memory level. I understand how the accessors of the method work, it was just easy to grok “static variable = always in memory/only one instance” and harder to understand exactly how this translated to executable code, instead of raw data.

Carrying this a bit further, instance (non-static) methods are NOT actually connected to an object instance. If we have a class MyClass which implements some method MyMethod(), and we have instantiated 20 instances of MyClass-type objects, there are NOT 20 copies of the MyMethod code out there in RAM.

What there really is is a single copy of all the methods of MyClass (both static and non-static). When you call SomeInstanceOfMyClass.MyMethod(), what really happens down in the bowels is a call is made to a generated static overload of MyMethod() which takes a parameter of a reference to an object of type MyClass.

In other words, down in the bowels of MyClass’s RAM image is a declaration like
static MyMethod(ref MyClass instanceToOperateOn);
and your instance call to SomeInstanceOfMyClass.MyMethod();
is translated to the static call
MyClass.HiddenMyMethodOverload(SomeInstanceOfMyClass);

So in fact down in the bowels there are ONLY static methods. Instance methods are really just a syntactic convenience which helps folks understand & accept encapsulation better.
The meat of *why *there are static methods exposed at the dev level is really about making it easier to implement patterns like factories or complex constructors. It’s also handy for things like math function libraries, but that’s not the deep motivator.

Programmer here. A static method cannot depend on state-specific information about any specific instance of a class.

For example, if you have a class “Employee” that includes a property “EmployeeID”, and a method “GetSalary()”, then what GetSalary() returns depends somehow on EmployeeID and/or a Salary property being set. However, a static method can only depend on things related to the Employee class as a whole, not any specific instance (e.g. a specific employee). Any variables it referenced would have to be static/singleton themselves. In C#, your class won’t compile if you reference an illegal dependency. For example, you could have a static method float GetSalaryByEmployeeID(int EmployeeID) that doesn’t reference the EmployeeID of the current instance, but goes to a database and looks up the salary and returns it. You could have a dynamic method reference a static one, but not the other way around.

e.g. (C# example)

public class Employee : Person
{
public int EmployeeID {get;set;}
public float GetSalary()
{
return GetSalary(EmployeeID);
}
public static float GetSalary(int EmployeeID)
{
Globals.Database.RunQuery(“GetSalary”, new Parameter(“EmployeeID”, EmployeeID));
}
}
}

Right.

That’s one way of looking at it (and it might be the way Java implements it, I’m not that knowledgeable of Java internals).

Conceptually, you can look at (and implement) it the other way around. In a prototype-based architecture, all methods really are instance properties, just like java instance properties. (in Java, an instance method can be seen as a function/method property of its corresponding class object).

In other words, usually, instance methods in class based systems are one level up in the hierarchy compared to instance properties. But in prototype-based systems, you can insert methods on an object-by-object basis, just like normal properties and there’s a chain of “inheritance” between objects, and any class-like behaviour is built on top of that.

If you look at it that way, Java’s instance methods are properties of the instance’s class (which is just another object), and class methods (static methods) are properties of the “class” of that class (usually called a meta class), and every method receives the object on which it was invoked as an additional parameter (the class for meta-class methods/static methods, and the object instance for “instance” methods (which are in the class) and “object-by-object” methods if you have those in the language).

Strictly class-based systems tend to enforce a view that somewhat obscures the details here, especially when you try to deal with classes as “normal objects”.

At a low level (ie, the actual instructions executed by the processor), there isn’t a difference between a static method and a normal member method.

It’s not like you make a new copy of each normal method whenever you make a new copy of the class. There’s only one copy of the instructions in memory. The difference is that a non-static method takes an implicit object reference of a specified type and can act on it, while static methods do not. But, of course, you could achieve the exact same behavior (and almost the same code) by just passing in an explicit reference to the object in question.

All methods are executed by branching the pc to a particular address and executing instructions until the pc returns to the calling point. Higher-level concepts like static aren’t a part of those operations. Those are used by the compiler when compiling the code, but they’re not present at the low level, which is just moving bits around. There are, generally, some translation layers used when calling a virtual function, but I don’t think that’s really the core of your question.

Virtual functions go through “dynamic dispatch”, but then virtual and static, while they are mutually exclusive, are not collectively exhaustive. You can have a method that is neither virtual nor static. In C#, a method that is not marked with abstract, virtual, or override (virtual method), or static (static method) is neither. By default, non-static methods in Java are inherently virtual, and have to be marked “final” to be treated as non-virtual. But then, this is just a language convention - the concept is the same.

With dynamic dispatch, the system must determine the actual type of the object and figure out which override to use, rather than take the type that the object is being addressed as (i.e. through which interface or base class). This is what “polymorphism” in OOP is about.