No Enclosing instance ...的原因和解决方法

Posted katyumarisa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了No Enclosing instance ...的原因和解决方法相关的知识,希望对你有一定的参考价值。

      一个月前刚考研复试完,终于也从一个毫不相关的专业转了码。现在在毕设期间找机会摸鱼学java。由于机试用的C,之前又没有接触过任何OOP语言,对Java的学习一度走了不少弯路。曾经写的沙雕代码也犯了不少错误(现在仍然在每天生产沙雕Java代码)。比如下面这段:

public class Main {
    int a = 1;
    public class Test{
        public void test() {
            System.out.println("Hello World");
        }
    }
    public static void main(String[] args) {
        Test T = new Test();
T.test(); } }

     编译器提示No enclosing instance of type Main is accessible. 也就是说没有Main的实例。查相应的博客,一群人复读“静态类方法无法调用动态实例方法,需要把类修饰符改为static”,但详细的原因却很少有人去说明,这一度让我非常难受,问题也没得到解决,只得暂时搁置。

     直到最近正在读《Java核心技术卷一》,才明白错误原因。下面进行相应的解释:

     为了搞清这个问题,要明白两个方面的知识:

1) public static void main方法

2) 内部类

     先解决第一个问题。首先我们要直到,任何的类都可以自定义一个main方法。在程序运行过程中只会调用唯一一个main方法,具体调用哪个就要看我们要加载哪一个类了。这样我们也可以明白为什么牛客OJ要求把主类名定义为Main,因为OJ仅仅测试Main中的main方法的输出结果,而其他的类中的main方法是不会被加载的。这种设计对于我们进行不同模块的单元测试是十分有利的,只需要把测试代码写到不同类的main方法中,调试时加载相应类即可。

     虽然main方法是属于类的,但当执行main方法的时候,main方法所属的类刚开始并没有被加载到内存中(先不考虑静态类),必须要在代码中new一个Main类,才会把Main的内容加载到内存中。

     这样我们就可以明白为什么错误示例代码中编译器提示没有加载Main实例了。由于没有加载Main实例,自然没有方法生成Test类,更不可能调用Test类中的方法了。因此我们实例化Main类,做以下修改:

public class Main {
    int a = 1;
    public class Test{
        public void test() {
            System.out.println("Hello World");
        }
    }
    public static void main(String[] args) {
        Main m = new Main();
        m.test();
    }
}

      emmmm.......编译器的报错更离谱了,啥都报了。这是因为第二个问题:内部类。

     下面解决第二个问题。内部类是Java的一种语法规则,也就是说,允许在类中定义类(之前写这段demo时不知道这个知识点)。很明显,Test类是在Main类中定义的内部类。而内部类的对象并不是在外部类实例化的时候就完成实例化的,也必须需要在代码中完成内部类的实例化:

        Main M = new Main();
        Main.Test T = M.new Test(); //new关键字在.后面,小心别看错了
        T.test();

    这样我们完成了Main类的实例化和Main类的内部类Test类的实例化,终于可以调用Test类的test()方法了,修改后可运行的代码如下:

public class Main {
    public class Test {
        public int a = 1;
        public void test() {
            System.out.println("Hello World");
        }
    }
    public static void main(String[] args) {
        Main M = new Main();
        Main.Test T = M.new Test();
        T.test();
    }
}

  

      这样问题就解决了。但是显然,内部类并不是我们想要的结果,它看起来太难受了,如何优雅的解决这个问题呢?

      第一种方法,将Test类修饰为static,即将Test类变为静态类也就是大多数人复读的方法在这种情况下,运行main方法时,虽然并没有实例化Test对象,但是Test类的静态方法和静态属性已经加载到内存中了,自然可以直接使用,不会提示No Enclosing XXX的内容。

public class Main {
    public static class Test {
        public int a = 1;
        public void test() {
            System.out.println("Hello World");
        }
    }
    public static void main(String[] args) {
        Test t = new Test();
        t.test();
    }
}

      第二种方法更简单,将算法的实现方法和操纵的类分开定义,将包含算法的main定义在Main类中,将类定义在另一个class中,这样我们直接选择实例化Test类就可以了,相应的修改代码如下:

public class Main { // 在被加载的类Main中定义算法过程
    public static void main(String[] args) {
        Test T = new Test();
        T.test();
    }
}

class Test {   //把使用的类拿到外面定义
    public int a = 1;
    public void test() {
        System.out.println("Hello World");
    }
}

 

 

以上是关于No Enclosing instance ...的原因和解决方法的主要内容,如果未能解决你的问题,请参考以下文章

No Enclosing instance ...的原因和解决方法

No enclosing instance of type E is accessible. Must qualify the allocation with an enclosing

No enclosing instance of type test is accessible. Must qualify the allocation with an enclosing inst

Java中出现No enclosing instance of type XXX is accessible问题

Java变异出现错误:No enclosing instance of type XXX is accessible

Java中报错No enclosing instance of type caiquan is accessible. Must qualify the allocation with an encl