【问题标题】:Why is a static local class not allowed in a method? [closed]为什么方法中不允许使用静态本地类? [关闭]
【发布时间】:2016-10-04 17:45:02
【问题描述】:

我一直在刷我的java,我对本地类有一些误解(我最终从未使用过),我很理解静态的概念,但在local classes 的情况下却不是。

1.为什么本地类中不允许使用静态方法?

2。为什么方法中不允许使用静态本地类?

  1. 本地类中不允许使用静态方法:

这里我不明白。对我来说,本地类与静态方法 main 相关联。我只是不明白为什么不能这样做。 main 方法通过 Sequence 类访问,然后由于 sayGoodbye 是静态的,因此应该通过其类访问。但不是。

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. 方法中不允许使用静态本地类:

这无法做到:这有点模棱两可,但我认为这里的静态与非静态具有相同的含义,因为静态类与静态方法相关联。我糊涂了。

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

编辑: 我得到的第一个答案是来自 oracle 的一句话:

本地类是非静态的,因为它们可以访问实例 封闭块的成员。因此,它们不能包含大多数 各种静态声明。

我的回复:

但这并不能真正解释一切。当你有内在 类你不能访问非静态字段,但你可以访问静态 字段。同样应该适用于本地课程,因为没有 静态变量然后就没用了。但是方法呢,比如我的 例子。

好的,我创建了一个架构来更好地解释我如何看待事物。不过这可能是完全错误的,我有点羞于展示它。在此架构中以及静态本地类可访问的场景中,我将在顶部内存块中有一个本地类。每当调用静态方法 2 时,它都会简单地引用它。

【问题讨论】:

  • 您在寻找什么样的答案?这里是对 JLS 的引用 stackoverflow.com/questions/17484834/…
  • 所有这些东西都在一个静态的 main 方法中。但是,如果您的静态方法实例化了一个新的 Sequence 类并将这些对象作为参数传递给同一个类中的一些非静态方法怎么办?您的班级将如何处理范围?
  • 一个原因可能是你不应该在生产代码中使用任何这些
  • @MickMnemonic 我想通过一个 java 证书,并且本地类在要学习的东西列表中。诚然,这不是一个很好的理由,你不觉得吗?
  • @Tunaki 后来,如果它是基于意见的,我想知道他们为什么这样做。我将用我如何看待事物以及为什么它对我没有意义来编辑我的帖子。另外我真的不明白为什么它是基于意见的。

标签: java class oop


【解决方案1】:

Java 中有两种类:顶级类和嵌套类。
嵌套类有两种:静态嵌套和内部。
还有两种特殊的内部类:Local 和 Anonymous。

本地和匿名类是定义内部类,即非静态的。

The Java™ Tutorials - Local Classes Are Similar To Inner Classes:

本地类是非静态的,因为它们可以访问封闭块的实例成员。因此,它们不能包含大多数类型的静态声明。

但是,你已经看到了,所以让我引用JLS §14.3 Local Class Declarations

所有本地类都是内部类 (§8.1.3)。


推理(我的看法)

第一个例子有什么意义?

public static void main(String... args) {
    class EnglishGoodbye {
        public static void sayGoodbye() { // this cannot be done
            System.out.println("Bye bye");
        }
    }
    EnglishGoodbye.sayGoodbye();
}

只需将方法设为主类的private static

public static void main(String... args) {
    sayGoodbye();
}
public static void sayGoodbye() {
    System.out.println("Bye bye");
}

哦,你想从方法中访问变量和参数吗?

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

问题在于static 方法没有实例上下文,那么message 的哪个实例会是?

要指定实例,需要new EnglishGoodbye() 语句,编译器会将隐藏的实例字段添加到EnglishGoodbye 以表示message 的值,这也是message 必须(有效)最终的原因,因为它是复制变量的值。请记住,与 C 不同,您不能通过指针引用变量。

public static void main(String... args) {
    final String message = "Bye bye";
    class EnglishGoodbye {
        public void sayGoodbye() {
            System.out.println(message);
        }
    }
    new EnglishGoodbye().sayGoodbye();
}

第二个例子也是如此。有什么意义?

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

只需将类设为主类的private static

public static void main(String... args) {
    EnglishGoodbye.sayGoodbye();
}
private static class EnglishGoodbye {
    public static void sayGoodbye() {
        System.out.println("Bye bye");
    }
}

如果您打算访问方法变量和参数,则与上述第一个示例的推理相同。该类需要一个实例,以了解要访问的变量/参数的哪个实例。


不是和答案直接相关,而是我做的,所以还是保留吧。

这是作为层次结构的 Java 类型系统(不要与继承/子类型混淆)

【讨论】:

  • 精彩的回答谢谢。所以他们有点禁用它,因为拥有这个功能没有真正的价值。 Imo 应该适用最小特权原则,但我想这只是迂腐。
  • 比我的讲师更好更清晰的解释!顺便说一句,Java 8 本地类可以访问最终封闭块的局部变量。
  • @SouthParker 他们总是能够从实例方法中做到这一点;仍然不能从静态方法中做到这一点,即使在 Java 8 中也是如此。Java 8 中的变化是它们只需要effectively final。他们不必再被声明为final。这样做是为了简化 lambda 表达式的使用。
  • 从你的回答看来,只有三个嵌套类——静态嵌套类、本地类和匿名类。与本地和匿名类不同的非静态嵌套类(通常称为内部类)呢?
  • @SameerSinha “有also 两种特殊 种类的内部类”表示除了常规内部类。
猜你喜欢
  • 2011-12-31
  • 1970-01-01
  • 2021-10-01
  • 2013-11-12
  • 2011-12-11
  • 1970-01-01
  • 2016-09-13
  • 2011-05-10
  • 2016-10-06
相关资源
最近更新 更多