为什么java允许导入在同一文件中定义的类?

为什么java允许导入在同一文件中定义的类?,java,Java,我创建了一个名为TestClass.java的java文件,并将其放在一个文件夹testPackage中。在编译时,导入我在同一个文件中定义的同一个类并没有给我任何错误 为什么允许这样做?这背后是否有什么真正的目的,或者仅仅是一个语法错误,因为不好的练习,它的影响太小了?没有人比一个人更在意;在进口声明之后 package testPackage; import testPackage.TestClass; public class TestClass{ public static vo

我创建了一个名为TestClass.java的java文件,并将其放在一个文件夹testPackage中。在编译时,导入我在同一个文件中定义的同一个类并没有给我任何错误

为什么允许这样做?这背后是否有什么真正的目的,或者仅仅是一个语法错误,因为不好的练习,它的影响太小了?没有人比一个人更在意;在进口声明之后

package testPackage;
import testPackage.TestClass;
public class TestClass{
    public static void main(String args[]){
        System.out.println("hello world");

    }
}
我正在使用以下设置:

C:\test>tree /F
Folder PATH listing for volume OS
Volume serial number is 2A49-80E2
C:.
└───testPackage
        TestClass.java

C:\test>javac -version
javac 1.8.0_181

C:\test>java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

C:\test>javac -cp . testPackage\TestClass.java

C:\test>java testPackage.TestClass
hello world

在某些情况下,需要导入在同一文件中定义的类。您的示例肯定不是其中之一,您的导入只是多余的,因为同一个包中的类位于同一名称空间中,这大致意味着同一个包中的类是隐式导入的

但看看这个假设所有代码都在同一个文件中:

package stackoverflow;

import stackoverflow.OtherClass.OtherClassInner;

public class Main {
    public static void main(String[] args) throws Exception {
        OtherClassInner inner = new OtherClassInner();
    }
}

class OtherClass {
    static class OtherClassInner {

    }
}
public class Main {
    public static void main(String[] args) throws Exception {
        OtherClassInner inner = new OtherClassInner();
    }
}

class OtherClass {
    static class OtherClassInner {

    }
}

class YetAnotherClass {
    static class OtherClassInner {

    }
}
在本例中,Main与OtherClassInner不在同一命名空间中,因此它要么完全限定stackoverflow.OtherClass.OtherClassInner,要么通过OtherClass.OtherClassInner引用它。OtherClassInner作为Main,而OtherClass不需要彼此导入,或者按照上面的代码段导入它

并且为了清楚地说明为什么导入是必需的,考虑在同一个文件中有两个其他类内部:

package stackoverflow;

import stackoverflow.OtherClass.OtherClassInner;

public class Main {
    public static void main(String[] args) throws Exception {
        OtherClassInner inner = new OtherClassInner();
    }
}

class OtherClass {
    static class OtherClassInner {

    }
}
public class Main {
    public static void main(String[] args) throws Exception {
        OtherClassInner inner = new OtherClassInner();
    }
}

class OtherClass {
    static class OtherClassInner {

    }
}

class YetAnotherClass {
    static class OtherClassInner {

    }
}

在某些情况下,需要导入在同一文件中定义的类。您的示例肯定不是其中之一,您的导入只是多余的,因为同一个包中的类位于同一名称空间中,这大致意味着同一个包中的类是隐式导入的

但看看这个假设所有代码都在同一个文件中:

package stackoverflow;

import stackoverflow.OtherClass.OtherClassInner;

public class Main {
    public static void main(String[] args) throws Exception {
        OtherClassInner inner = new OtherClassInner();
    }
}

class OtherClass {
    static class OtherClassInner {

    }
}
public class Main {
    public static void main(String[] args) throws Exception {
        OtherClassInner inner = new OtherClassInner();
    }
}

class OtherClass {
    static class OtherClassInner {

    }
}

class YetAnotherClass {
    static class OtherClassInner {

    }
}
在本例中,Main与OtherClassInner不在同一命名空间中,因此它要么完全限定stackoverflow.OtherClass.OtherClassInner,要么通过OtherClass.OtherClassInner引用它。OtherClassInner作为Main,而OtherClass不需要彼此导入,或者按照上面的代码段导入它

并且为了清楚地说明为什么导入是必需的,考虑在同一个文件中有两个其他类内部:

package stackoverflow;

import stackoverflow.OtherClass.OtherClassInner;

public class Main {
    public static void main(String[] args) throws Exception {
        OtherClassInner inner = new OtherClassInner();
    }
}

class OtherClass {
    static class OtherClassInner {

    }
}
public class Main {
    public static void main(String[] args) throws Exception {
        OtherClassInner inner = new OtherClassInner();
    }
}

class OtherClass {
    static class OtherClassInner {

    }
}

class YetAnotherClass {
    static class OtherClassInner {

    }
}

据我所知,编译器配置要编译的类和所有导入的类,并确保多个不同的配置类在给定范围内没有相同的名称。不同的文件不会导入具有相同名称的类的不同文件。多个文件导入同一类或同一文件是非常常见的,因此这种情况在这方面并不错误。在这种情况下,编译器只会注意到它已经读取了一个类,因此下次包含它时,它会意识到它已经读取了该类并使用了现有的概要类。在编译器分析了每个可能预先形成类层次结构的类之后,它将遍历并编译已分析的类

此方法应给出与显式处理给定情况相同的结果,但代码更简单,从而减少了出错的空间,提高了性能,并可能处理其他奇怪的情况,否则可能会由于必须专门针对这些情况而导致错误编译


许多编译器避免了类似瘟疫的情况,因为它们不执行此分析步骤,因此每次发生此类情况时,它们都会冒着导致编译器进入无限循环的风险,因为每次将同一文件视为依赖项时,它们都会不断重新编译该文件,因此必须在编译之前先编译该文件可以编译原始文件和相同的文件。

据我所知,编译器配置要编译的类和所有导入的类,并确保多个不同的配置类在给定范围内没有相同的名称。不同的文件不会导入具有相同名称的类的不同文件。多个文件导入同一类或同一文件是非常常见的,因此这种情况在这方面并不错误。在这种情况下,编译器只会注意到它已经读取了一个类,因此下次包含它时,它会意识到它已经读取了该类并使用了现有的概要类。在编译器分析了每个可能预先形成类层次结构的类之后,它将遍历并编译已分析的类

此方法应给出与显式处理给定情况相同的结果,但代码更简单,从而减少了出错的空间,提高了性能,并可能处理其他奇怪的情况,否则可能会由于必须专门针对这些情况而导致错误编译

许多编译器避免了类似瘟疫的情况,因为它们不执行此分析步骤,因此每次发生此类情况时,它们都会冒着导致编译器进入无限循环的风险,因为每次将同一文件视为依赖项时,它们都会不断重新编译该文件,因此必须在编译之前先编译该文件可以
编译原始文件和相同的文件。

如果我猜的话,我会说它没有实现,原因与我们在java中没有多重继承相同:它会使编译器更加复杂,也就是说,需要再检查一次。为什么不呢?这是个问题吗?是否值得将检查此条件的代码写入编译器?由此解决了什么问题?如果我猜的话,我会说它没有实现的原因与我们在java中没有多重继承的原因相同:它会使编译器更加复杂,也就是说,它需要再检查一次。为什么不呢?这是个问题吗?是否值得将检查此条件的代码写入编译器?这样可以解决什么问题?即使没有那个import语句,这段代码也可以工作。@Turing85:在您的代码中,您编写了新的OtherClass.OtherClassInner。导入允许您在不使用该限定符的情况下执行此操作。这正是进口的目的,没有进口,你可以用一个更完整的名字来做。@Thilo我知道这一点。尽管如此,在某些情况下,需要导入答案中同一文件中定义的类的语句是错误的,我的示例对此进行了演示。@Turing85我明白您的意思,完全限定名并不总是必要的,因为嵌套的静态类可以通过其封闭类型引用,并且已经编辑过。那是我的疏忽。但是直接使用OtherClassInner需要导入,这正是我想在这里展示的。即使没有导入语句,这段代码也可以工作。@Turing85:在您的代码中,您编写了新的OtherClass.OtherClassInner。导入允许您在不使用该限定符的情况下执行此操作。这正是进口的目的,没有进口,你可以用一个更完整的名字来做。@Thilo我知道这一点。尽管如此,在某些情况下,需要导入答案中同一文件中定义的类的语句是错误的,我的示例对此进行了演示。@Turing85我明白您的意思,完全限定名并不总是必要的,因为嵌套的静态类可以通过其封闭类型引用,并且已经编辑过。那是我的疏忽。但是直接使用OtherClassInner需要导入,这就是我想在这里展示的。