Why does static have different meanings depending on the context? [duplicate] - java

This question already has answers here:
In laymans terms, what does 'static' mean in Java? [duplicate]
(6 answers)
Closed 7 years ago.
As I understand it:
A static class only applies to nested classes, and it means that the nested class doesn't have references to the outer class.
A static field is kind of like a global variable, in that there is only one instance of it, and it is shared by other members of the same class.
A static method means that it can be called even if the object hasn't been instantiated yet.
I am taking an introduction to Java course and am trying to cement my knowledge, as well as trying to figure out why different keywords weren't used to signify different meanings.

Your examples are all correct, however, they all share a common feature. The word static means that an enclosing instance is not necessary.
Only a static inner class can exist without an enclosing instance. For example, if you have a class Foo and a non-static inner class Bar then you cannot create an instance of Bar outside an instance of Foo.
A static method means you do not need an instance of the class to call the method. You can call String.format without an actual String instance for example.
A static field will exist even without an instance of the class. If your Foo class has a counter field that is static you can access it without ever instantiating an instance of the Foo class.
Consider, as a clarifying point, that an interface can have static classes, static fields, and static methods. However, it cannot have the non-static version of any of those things (ignoring default methods which are sort of ad-hoc'd into the concept). This is because you can never create an instance of an interface so there could never be an enclosing instance.
You can also declare inner interfaces, annotations, and enums to be static although the keyword in that case is entirely redundant (e.g. similar to declaring an interface method abstract). Interfaces, annotations, and enums have no relationship to an enclosing class to begin with so static can't really take that away.
One last byzantine point. If you do a static import (import static pack.age.Foo.*) you will be able to make unqualified references to any static items in a class (including interfaces, annotations, and enums regardless of whether or not they are redundantly marked static).

Why does static have different meanings depending on the context? Why
didn't aren't different key words used?
It doesn't really have different meanings.
You can take the static keyword to indicate the following wherever it may be encountered:
"without regard or relationship to any particular instance"
A static field is one which belongs to the class rather than to any particular instance.
A static method is defined on the class and has no notion whatsoever of this. Such a method can access no instance fields in any particular instance, except when an instance is passed to it.
A static member class is a nested class that has no notion of its enclosing class and has no relationship to any particular instance of its enclosing class unless such an instance is passed to it (such as an argument to its constructor).

From Core Java by Cay Horstmann:
The term “static” has a curious history. At first, the keyword static was introduced in C to
denote local variables that don’t go away when a block is exited. In that context, the term
“static” makes sense: The variable stays around and is still there when the block is entered
again. Then static got a second meaning in C, to denote global variables and functions
that cannot be accessed from other files. The keyword static was simply reused, to avoid
introducing a new keyword. Finally, C++ reused the keyword for a third, unrelated,
interpretation—to denote variables and functions that belong to a class but not to any
particular object of the class. That is the same meaning the keyword has in Java.

Java inherits from C++ and C. In those languages, static has two additional meanings. A local variable (function scope) qualified as static has meaning somewhat similar to that of a static field in a class. Java however does not support this context of "static". Qualifying a variable or function as static in C or C++ at file scope means "Ssh! Don't tell the linker!". Java does not support this mean of static, either.
In English, the same word can have multiple meanings, depending on context. Look up any commonly-used word in the dictionary and you will find multiple definitions of that word. Some words not only have multiple meanings, they have multiple parts of speech. "Counter", for example, can be a noun, a verb, an adjective, or an adverb, depending on context. Other words can have contradictory meanings, depending on context. "Apology" can mean "I'm so sorry!" or it can mean "I am not sorry at all!" A premier example of the latter is "A Mathematician's Apology" by G. H. Hardy. English is not at all unique in this regard; the same applies to any language humans use to communicate with one another. As humans, we are quite used to words having different meanings depending on context.
There's an inherent conflict between having too few keywords and too many in a computer language. Lisp, forth, and smalltalk are very beautiful languages with very few, if any, keywords. They have a few special characters, e.g., open and close parentheses in lisp. (Full disclosure: I've programmed in all three of those languages, and I loved it.) There's a problem here: Good luck reading the code you yourself wrote six months after the fact. Even better luck turning that code over to someone else. As a result, these languages also have a rather limited number of adherents. Other languages go over the top and reserve a huge number of words as "keywords." (Full disclosure: I've been forced to program in those languages as well, and I hated it.)
Too few or too many keywords in a computer language results in cognitive dissonance. Having the same keyword have different contexts in different does not, because as humans, we are quite used to that.

Java Tutorial says
As with class methods and variables, a static nested class is
associated with its outer class. And like static class methods, a
static nested class cannot refer directly to instance variables or
methods defined in its enclosing class: it can use them only through
an object reference.
Basically "static" means that the entity marked with it is divorced from the instances of a class. Static method doesn't have an instance associated with it. Static field is shared between all instances (essentially exist in the Class, not in the instance).
static nested classes are divorced from the enclosing instance. You are right that it is a bit confusing because you can have an instance of a static nested class with non-static methods and fields inside of it.
Think of the word static as saying "I am declaring an entity, a field, a method or an inner class, which is going to have no relationship to the enclosing instance"

All the mentioned uses of static have some commonality as I see it - in all cases they mean that the class/field/method is less tied to the class instance than would be the case without static. Certainly the equivalence between static fields and static methods in particular should be clear: they are the way to declare singleton (per-classloader) fields and methods that work on those fields, in a similar way to global objects in other languages.
Perhaps then the use of static for nested classes isn't as obviously in the same spirit, but it does share the aspect that you don't need an instance of the containing class to use this construct.
So I don't see these as being particularly inconsistent.
One answer to the more general question of why keywords are re-used for apparently different purposes in a programming language is that often features are introduced as a language evolves - but it is difficult to add new keywords since often break existing programs that may have used that as an identifier. Java, for example, actually reserves the keyword const even though it is unused in the language, perhaps to allow for future expansion!
This reluctance to add new keywords often leads to overloading old ones.

Related

Why are static methods allowed inside a non-static inner class in Java 16?

We know that a non-static inner class can be accessed using the instance of the outer class, so a static method is less meaningful inside a non-static class. But from Java 16 static methods are allowed inside a non-static inner class.
Why did this restriction exist in the first place? Why is this allowed in the newer version?
public class OuterClass {
class InnerClass {
static void printMe() {
System.out.println("Inside inner class");
}
}
public static void main(String[] args) {
InnerClass.printMe();
}
}
You're asking for reasoning of a change in Java 16, so you should start by checking the Release Notes to see if it has anything to say. It does:
JEP 395: Records (JDK-8246771)
tools/javac
Records have been added to the Java language. Records are a new kind of class in the Java language. They act as transparent carriers for immutable data with less ceremony than normal classes.
Since nested classes were first introduced to Java, with the exception of static final fields initialized by constant expressions, nested class declarations that are inner have been prohibited from declaring static members. This restriction applies to non-static member classes, local classes, and anonymous classes.
JEP 384: Records (Second Preview) added support for local interfaces, enum classes, and record classes, all of which are static definitions. This was a well-received enhancement, permitting coding styles that reduce the scope of certain declarations to local contexts.
While JEP 384 allowed for static local classes and interfaces, it did not relax the restriction on static member classes and interfaces of inner classes. An inner class could declare a static interface inside one of its method bodies, but not as a class member.
As a natural next step, JEP 395 further relaxes nesting restrictions, and permits static classes, methods, fields, etc., to be declared within inner classes.
For further details, see JEP 395.
The specific reasoning is given in JEP 395
Static members of inner classes
It is currently specified to be a compile-time error if an inner class declares a member that is explicitly or implicitly static, unless the member is a constant variable. This means that, for example, an inner class cannot declare a record class member, since nested record classes are implicitly static.
We relax this restriction in order to allow an inner class to declare members that are either explicitly or implicitly static. In particular, this allows an inner class to declare a static member that is a record class.
In other words, it was necessary to remove the restriction on static members of inner classes for a particular case; i.e. to allow record classes to be declared in inner classes. But they decided to take the opportunity to remove the restriction in all cases.
This implies that the designers have concluded that the original restriction as a whole was neither necessary for technical reasons or desirable.
why did this restriction exist in the first place?
That is a more difficult question. The decision to make that restriction would have been made in 1996 or early 1997 when Java 1.1 was being designed. It is unlikely that anyone can still accurately remember the reasons behind original decision. So unless someone can find a contemporaneous written source, we will never know for sure.
(Brian Goetz commented above: "... at the time nested was added (Java 1.1), there were multiple possible interpretations of static within another class, so the question was deferred.". That certainly makes sense, but this could be (just) one person's recollection of something that happened ~25 years ago. If it was me, I wouldn't be confident in my memory from that far back. Unless I had contemporaneous minutes, notes, etc to refer to.)
There is some speculation about the rationale for the original restriction here:
Why does Java prohibit static fields in inner classes?

Why is a static method considered a method?

I'm writing an explanation for some code for a course, and have been accidentally using the words method and function interchangeably. I decided to go back over and fix the wording, but ran into a hole in my understanding.
From what I understand, a subroutine is a function if it doesn't act on an instance of a class (its effect is restricted to its explicit input/output), and is a method if it operates on an instance of a class (it may carry out side effects on the instance that make it impure).
There's a good discussion here on the topic. Note that by the accepted answer's definitions, a static method should actually be a function because an instance is never implicitly passed, and it doesn't have access to any instance's members.
With this is mind though, shouldn't static methods actually be functions?
By their definition they don't act on particular instances of a class; they're only "tied" to the class because of relation. I've seen a few good looking sites that refer to static subroutines as "methods" though (Oracle, Fredosaurus, ProgrammingSimplified), so either they're all overlooking the terminology, or I'm missing something (my guess is the latter).
I'd like to make sure I am using the correct wording.
Can anybody clear this up?
This quote from 8.4.3.2 may help:
A method that is declared static is called a class method.
A method that is not declared static is called an instance method [...].
Class methods: associated with a class.
Instance methods: associated with an instance.
Java just wants you to "think object-oriented". Also, static methods have access to a surrounding scope which may include state. In a way, the class is like an object itself.
The simple answer is that when Java decided to call everything a "method", they didn't care about the distinction between a function and a method in theoretical computer science.
Static methods are not exactly functions, the difference is subtle, but important.
A static method using only given input parameters is essentially a function.
But static methods may access static variables and other static functions (also using static variables) so static methods may have a state which is fundamentally different to a function which are by definition stateless.
(ADDENDUM: While programmers are often not so strict with using "function" as definition, a strict function in computer science can access only input parameters). So defining this case of accessing static fields it is not valid to say that static methods are always functions.
Another difference which justifies the usage of "static method" is that you can define in C derivates global functions and global variables which can be accessed everywhere. If you cannot access the class which contain static methods, the methods are inaccessible, too. So "static methods" are limited in their scope by design in contrast to global functions.
In Java, a user-defined class is actually an instance of a subclass of java.lang.Class.
In this sense, static methods are attached to an instance of a conceptual class: they are attached to an instance of a subclass of java.lang.Class.
With this in mind, the term "class method" (an alternate name for Java's static methods) begins to make sense. And the term "class method" can be found in many places: Objective C, Smalltalk, and the JLS -- to name just a few.
In computer science function clearly maps to a static method. But "method" of a class is a bit generic, like "member" (field member, method member). There are wordings like
Data members and method members have two separate name spaces: .x and .x() can coexist.
So the reason is, that as the philosoph Ludwig Wittgenstein said, Language is a tool with different contexts. "Method" is a nice moniker in the citation above to categorize a "member".
Your thinking is right and it makes sense. It's just not established terminology in the Java community. Let me explain some internals that can help understand why the terminology subsists.
Java is a class based object oriented language. A method is always member of a class or instance (This is a general statement valid for other programming languages too). We think of class and instance being both objects.
Instance method (dynamic)
You cannot invoke this method from a class directly, you have to create an instance. Each instance references that method. You can overwrite a method definition with the exact same method signature (when subclassing), i.e. the reference points to a different method (which has the same signature, but can have a different method body). The method is dynamic.
Class method (static)
You only can invoke this method from the class directly, i.e. you don't need to create an instance of that class. There is only one global definition of that method in the whole program. You cannot overwrite the exact same method signature when the method is declared static, because there is only one definition valid for the whole program. Note that the method is member of the class object itself, the instances have all the same unique (and fix) reference to that method.
Here is another take on the terminology, using Scala as a mnemonic:
In Scala you have objects, which are singleton instances of an implicitly defined class 1.
Per your definition, we can call these subroutines belonging to the object methods, as they operate on a single instance of the class.
Additionally the object will also define class A, and create all of the methods in object A as static methods on class A (for interfacing with Java) [2].
Therefore we can say that the static methods of Java class A access the same members as the Scala singleton instance, which per your definition then deserve to be called (static) methods of class A.
Of course, the main difference is - method can use static fields, not only method parameters.
But there is additional one - polymorphism!
Results of evaluation Class A.doTheSameStaticMethod() and ClassB.doTheSameStaticMehod() will be depends of class. In this case function is impotent.
Each class has an object to represent it that is an instance of a subclass of the Class class. Static methods are really instance methods on these objects that are instances of a subclass of Class. They have access to state in the form of static fields, so they are not restricted to being just (stateless) functions. They are methods.

What exactly are and when are static methods/variables used? [duplicate]

This question already has answers here:
What does the 'static' keyword do in a class?
(22 answers)
Closed 8 years ago.
I'm quite new to Java and I'm trying to understand static variables and methods. Could someone give me a brief explanation of why I'd use the static method over the instance method and also what would be the ideal situation to use static variables? I know that static variables and methods are part of the class and not an instance of said class but I'm having trouble understanding when I'd use it.
Thanks!
These are the main differences
1.Static variables take memory only 1 time during the lifetime of program.
2.You can call static variables or methods. without creating the object of that class by classname only.
3.Static variables can be called in static and non-static context.
Mainly static variables are used to save memory because every object takes memory .
Static members relate to a type not a concrete instance. So instance methods and variables concern the identity of the instance, e.g. an instance method can alter the state of the object.
To some extend this is a religious question. Some people prefer to create static methods in a class when they do not access any instance variable. Other people do not like this approach. Another usual usage is creating factory methods, able to create an instance of an object while itself being called statically.
Often there are utility classes that contain static methods to serve clients with some functionality that is not bound to any type context. But all too often these utility classes get abused by using them as a trash bin for all sorts of methods a programmer did not find a fitting class for. This may be a result of poor design.
A popular use of static variables is the definition of an logger instance (e.g. SLF4J) for a class because loggers are thread safe and can be used by all instances and static methods alike. One advantage is (see a comparison) that only one instance has to be created for all instances of the containing class.
For static variable or method, you can think of that there is only one copy of the variable or method during the whole life time of the program.
So if you there is variable whose value should be shared across all the processes or thread, you can declare a static variable. For example, when you want to use a singleton pattern, you will need a static variable to indicate if there is instance of the class already.
For static methods, I would use them when state of the class is not important. I think the best example is java.lang.Math, they are all static methods, and returns the expected values to you no matter what you called before.

When to use static method and field?

I know what static is, but just not sure when to use it.
static variable:
I only used it for constant fields. Sometimes there are tens of constants in a class, so using static constants can save lots of memory. Is there any other typical use cases?
static method:
I use it when I make a class about algorithms. For example, a class which provides different sorting algorithms. Is it against OOP design? I think it is better to maintain this way rather than implementing sorting algorithms inside each class that needs to use them. Am I wrong? What are some good use cases?
Also, are there any performance difference between using static and non-static fields/methods?
You are describing cases where you've used static, but this doesn't quite explain fundamentally why you would use static vs non-static - they are more than just keywords for constants and utility methods.
When something is not static (instance), it means that there is an instance of it for each instance of the class. Each one can change independently.
When something is static, it means there is only one copy of it for all instances of the class, so changing it from any location affects all others.
Static variables/methods typically use less memory because there is only one copy of them, regardless of how many instances of the class you have. Statics, when used appropriately, are perfectly fine in object oriented design.
If you have a method/variable that you only need one instance of (e.g. a constant or a utility method), then just make it static. Understand though that making a method static means it cannot be overridden. So if you have a method you want to override in a subclass, then don't make it static.
The general rule of thumb is - if you need only one copy of it, make it static. If you need a copy per instance, then make it non static.
Is there any other typical use cases?
Global Variables
Is it against OOP design?
Not exaclty, the point is that static methods are stateless since you don't need a particular instance of a class. My favorite approach is for utility methods (like Apache Commons). But you may be aware that some methods may be better placed as class members instead of static.
Also static methods can make class testability harder once you can't override these methods or replace by mock implementation.
Performance difference ?
There's a performance Android recommendation from Google that says "prefer static over virtual":
http://developer.android.com/training/articles/perf-tips.html#PreferStatic
I'm not sure it's true for JVM since Android uses a different VM, but it makes sense given the reasons the link points out:
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."
My personal rule of thumb is that static things are "just hanging out there". They are things that (disclaimer, not entirely true) are global, but make sense to include with this one particular class.
Static fields are good if you find yourself loading some heavyweight objects repeatedly. For instance, the project I'm working on now has a toggle between two images. These are static fields that are loaded with the application and kept in memory, rather than reloading them every time and letting GC take care of the mess.
Apart from very specific situations, I use static (and final) variables for constants only. It's a totally valid to use them, of course.
I tend to avoid static utility methods, because they make it harder to write unit tests for the code (mocking the results of the method invocation). When you start developing Test Driven way, this issue becomes quite apparent. I prefer using dependency injection and singleton beans (though it depends on your needs and situation).
Static variables belong to a class, hence shared by all the objects, so memory usage is less if you really want the varible to be shared. If you declare the variable as public and static, then it is globally available for everyone.
Static methods are generally the utility methods, depending on the access modifier, those can be used within a class or across the classes. Static utility class will help to reduce the memory usage again because you need not to create the object to call those methods.
The static field has one value among all objects and they call it Class member also because it's related to the class.
You can use static filed as a utility.
an example just Assume we need to know how many instances we have :
class Counter
public class Counter {
public static int instanceCount ;
public Counter()
{
instanceCount++;
}
public int getInstanceCount()
{
return instanceCount;
}
}
After creating two instances of Counter Class. But they share the same instanceCount field because it's a static field so the value of instanceCount will become the same in firstCounter and secondCounter .
Class main
Counter firstCounter = new Counter();
// will print 1
System.out.println(co.getInstanceCount());
// will print 2
Counter secondCounter = new Counter();
System.out.println(co1.getInstanceCount());

Java - about using classes with static members vs. not

So I have a question regarding best practices. Basically I'm doing the following to make accessing members of different classes easier:
class myClass1 {
public static int var1;
public static String var2;
//...
public static void method1() {
//...
}
}
And then in other classes I can just access myClass1 members with myClass1.var1, myClass1.var2, myClass1.method1(). Another design pattern I see is to not use static at all and just do myClass1 instance = new myClass1(); and then do instance.method1(); or whatever.
I remember hearing something somewhere about static being bad... relating to global objects or whatever. But it's been a while since intro to computer science, heh.
Anyways, beginner Java programmer just looking to get some insight into best practices. Thanks.
The semantics of static vs. non-static member variables and methods are completely different. Non-static variables are members of instances of the class; each instance has its own copy. Static variables are members of the class itself; they're not tied to any particular instance.
Similarly, non-static methods operate on instances of the class, static methods aren't tied to a particular instance.
You should use static/non-static as the problem requires. This isn't a question of best practices.
In general having all the members fields/methods public static is considered bad practice for Object Oriented Programming paradigm. It takes all the notions of object encapsulation and data security. Any client of your class is free to tamper your data any time. This kind of practice is very similar to defining global variables and functions in procedural languages like C.
There are several reasons why this is a bad idea:
Public field. Using public fields makes it practically impossible to write thread-safe code. It also makes it hard to maintain or modify your code. On a theoretical level it violates encapsulation, which is one of the basic ideas of OO with all its consequences. For example if you have complex state, where not every combination of field values is valid, you're in trouble.
Static field. Although static fields have their legitimate uses, it should be kept to a minimum. They aren't inherited, which can easily lead to confusion and at the best of times it's a ticking time bomb.
All in all: don't use static fields unless it is necessary, and even then they should be private.
The notable exception is obviously static and final fields (aka. constants) which can be declared public without too many dangers.
Generally speaking one never makes static variables except for static final variables which are then like constants. The primary reason is that more than one thread can then change the state of the global variable at the same time leading to unpredictable state of every object instance of that class.
As per Object oriented fundamental concerns :
Variable should not be accessible outside the class. So they should be private not public except interface case. This is applicable to Static variable as well.
You want to access the variable use public method. In case of static variable you will static public method.
It depends entirely what you are doing. If your class just holds stateless utility functions then this may be OK. If you are trying to any kind of real OOP design, then this doesn't make sense.
If you use instances of classes to model objects in the 'real world', then they will need instance variables, and should have instance methods to act upon that data. Each instance encapsulates that data and provides suitable behaviour.

Categories

Resources