There are two kinds of classes in Java: Top-Level and Nested.
There are two kinds of Nested classes: Static Nested and Inner.
There are also two special kinds of Inner classes: Local and Anonymous.
Local and Anonymous classes are by definition Inner classes, i.e. non-static.
See The Java™ Tutorials - Local Classes Are Similar To Inner Classes:
Local classes are non-static because they have access to instance members of the enclosing block. Consequently, they cannot contain most kinds of static declarations.
But, you already saw that, so let me quote JLS §14.3 Local Class Declarations:
All local classes are inner classes (§8.1.3).
Reasoning (my opinion)
What is the point of the first example?
public static void main(String... args) {
class EnglishGoodbye {
public static void sayGoodbye() { // this cannot be done
System.out.println("Bye bye");
}
}
EnglishGoodbye.sayGoodbye();
}
Just make the method a private static
of the main class:
public static void main(String... args) {
sayGoodbye();
}
public static void sayGoodbye() {
System.out.println("Bye bye");
}
Oh, did you want to access variables and parameters from the method?
public static void main(String... args) {
final String message = "Bye bye";
class EnglishGoodbye {
public static void sayGoodbye() { // this cannot be done
System.out.println(message);
}
}
EnglishGoodbye.sayGoodbye();
}
Problem with that is that a static
method has no instance context, so which instance of message
would that be?
To specify instance, a new EnglishGoodbye()
statement is needed, and the compiler will add hidden instance fields to EnglishGoodbye
to represent the value of message
, which is also why message
has to be (effectively) final, since it is copying the value of the variable. Remember, unlike C, you cannot reference a variable by pointer.
public static void main(String... args) {
final String message = "Bye bye";
class EnglishGoodbye {
public void sayGoodbye() {
System.out.println(message);
}
}
new EnglishGoodbye().sayGoodbye();
}
Same goes for the second example. What is the point?
public static void main(String... args) {
static class EnglishGoodbye { //static local classes not allowed
public static void sayGoodbye() {
System.out.println("Bye bye");
}
}
EnglishGoodbye.sayGoodbye();
}
Just make the class a private static
of the main class:
public static void main(String... args) {
EnglishGoodbye.sayGoodbye();
}
private static class EnglishGoodbye {
public static void sayGoodbye() {
System.out.println("Bye bye");
}
}
Same reasoning as above for first example, if you has intended to access method variables and parameters. The class needs an instance, to know which instance of the variables/parameters to access.
Not that it's directly related to answer, but I made this, so might as well keep it.
Here is the Java type system as a hierarchy (not to be confused with inheritance/subtypes):
- Type (§4)
- Primitive type (§4.2)
boolean
, byte
, short
, int
, long
, char
, float
, double
- Reference type (§4.3)
null
type (§4.1)
- Type variable (§4.4),
- Array type (§10.1)
- Interface (§9.1)
- Annotation type (§9.6)
- Normal interface
- Top-level interface (§7.6)
- Nested interface (§8.5, §9.5)
- Class (§8.1)
- Enum type (§8.9)
- Normal class
- Top-Level class (§7.6)
- Nested class (§8.5, §9.5)
- Static Nested class
- Inner class (§8.1.3)
- Local class (§14.3)
- Anonymous class (§15.9.5)