13

I've been brushing off my java and I've some misunderstanding about local classes (that I ultimately never used), I well understand the concept of static but not in the case of local classes.

1. Why is a static method not allowed in a local classes ?

2. Why is a static local class not allowed in a method ?

  1. A static method not allowed in a local classes:

Here I don't get it. To me the local class is tied to the static method main. I just don't understand why this cannot be done. The method main is accessed through the Sequence class and then since sayGoodbye is static it should be accessed through its class. But no.

public class Sequence {

    public static void main(String... args) {

        class EnglishGoodbye {
            public static void sayGoodbye() { // this cannot be done
                System.out.println("Bye bye");
            }
        }
        EnglishGoodbye.sayGoodbye();
    }
}
  1. A static local class not allowed in a method :

This cannot be done: It's a bit ambiguous but I'd think a static here would have the same meaning as a non static since the static class is tied to a static method. I'm confused.

public class Sequence {

    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();
    }
}

Edit: The first answer I got was a quote from oracle :

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.

and my reply :

That doesn't really explain everything though. When you have an inner class you can't access non static fields but you can access static fields. Same should apply for a local class, and since there is no static variable then it's useless. But what about methods, like in my example.

Okay I made a schema to better explain how I view things. It might be totally erroneous though and I'm a bit ashamed to show it. In this schema and in the scenario where a static local class would be accessible I'd have a local class in the top memory block. Whenever the static method2 would be called it would simply reference to it.

enter image description here

Ced
  • 15,847
  • 14
  • 87
  • 146
  • What kind of answer are you looking for? A reference to JLS is here http://stackoverflow.com/questions/17484834/which-part-of-jls-said-anonymous-classes-cannot-have-public-protected-private-me – Tunaki Jun 04 '16 at 21:10
  • all these things are inside a static main method. But what if your static method instantiate a new Sequence class and pass these objects as parameter do some non-static method in the same class? How your class would deal with the scope? – Leo Jun 04 '16 at 21:12
  • One reason might be that _you should never use any of these in production code_. – Mick Mnemonic Jun 04 '16 at 21:18
  • 1
    @MickMnemonic I wanna pass a java cert, and local class is in the list of things to study. Admitadly that's not a very good reason, don't you think ? – Ced Jun 04 '16 at 21:19
  • How would a `static` method in a nested class work? How would a `static` class in a method work? – Boris the Spider Jun 04 '16 at 21:22
  • Local classes are rarely useful, but [this thread](http://stackoverflow.com/questions/478804/advantage-of-local-classes-java) should cover the subtleties more than enough for your cert exam. – Mick Mnemonic Jun 04 '16 at 21:25
  • Do you want an answer referenced by the Java Specification or do you want to know inherently why it isn't allowed? The latter would be opinion-based. – Tunaki Jun 04 '16 at 21:25
  • 1
    @Tunaki the later, and if it's opinion based I'd like to know why they made it as such. I'm gonna edit my post with how I view things and why it doesn't make sens to me. Also I don't really see why it's opinion based. – Ced Jun 04 '16 at 21:27

1 Answers1

12

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):

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • 1
    Wonderful answer thank you. So they kinda disabled it because there is no real value in having this functionality. Imo the least privilege principle should apply but I guess that's just being pedantic at this point. – Ced Jun 05 '16 at 10:12
  • Better and more clear explanation than my lecturer! BTW from Java 8 local class can access local variables of enclosing block which are final. – mzoz Apr 01 '18 at 07:38
  • 1
    @SouthParker They have always been able to do that, from instance methods; still can't do that from static methods, not even in Java 8. What changed in Java 8 is that they only need to be [*effectively* final](https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html#accessing-members-of-an-enclosing-class). They don't have to be declared `final` any more. This was done to simplify the use from lambda expressions. – Andreas Apr 01 '18 at 08:56
  • It seems from you answer that there are three Nested Class only - Static Nested class, Local class and Anonymous Class. What about the Non Static Nested Class (commonly known as inner class )which is different from local and anonymous classes in the sense that they are not defined inside a block or method ? – sss Dec 23 '18 at 07:20
  • @SameerSinha "There are *also* two *special* kinds of Inner classes" means in *addition* to the *regular* Inner classes. – Andreas Dec 23 '18 at 15:54
  • i dont get it @Andreas. **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.** local classes created from static methods dont have access to instance right, then i should be able to declare static methods inside local classes and call using local class name . the same should be possible for static local class right? please let me know what i am missing. thanks ! – amarnath harish Dec 08 '19 at 14:06
  • @Andreas **Problem with that is that a static method has no instance context, so which instance of message would that be?** it would be message variable from local scope right ? due to shadowing...what is the problem here ? – amarnath harish Dec 08 '19 at 14:16
  • @amarnathharish *"All local classes are inner classes ([§8.1.3](https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3))".* Click that link to §8.1.3 of the **Java Language Specification**, which says: *"It is a compile-time error if an inner class declares a member that is explicitly or implicitly `static`, unless the member is a constant variable."* --- So, ***by definition***, inner classes (and hence local classes too) cannot have static methods. End of story. That's the way it is. – Andreas Dec 08 '19 at 19:27
  • @amarnathharish How would static method `sayGoodbye()` have access to local variable `message`? The variable is declared in method `main()`, so code in `sayGoodbye()` cannot access it. Normally, the compiler fakes it by *copying* the value of the local variable into a hidden instance variable of the `EnglishGoodbye` local class. Because it's a *copy*, the value must be effectively final, to prevent confusion of the programmer. But since the method is static, it doesn't have access to instance variables of `EnglishGoodbye`, so that doesn't work. *That's* the problem. – Andreas Dec 08 '19 at 19:36