阻止从有包名的一个java类引用默认包(未声明包名)的类

来源:互联网 发布:粒子群蝙蝠算法的论文 编辑:程序博客网 时间:2024/05/24 07:20
 有两个java类,源代码如下:

//没指定包名,也就是在默认包中
public class B {
  public void print(){
    System.out.println("Printed By B Class");
  }


package com.unmi;
import B; //引用默认包中的B类
public class A {
  public static void main(String[] args) {
    B b = new B(); //在A中想要引用默认包中的B类
  }
}
 


先不说在IDE中如何编译它们以及会提示什么语法错误,只是用命令javac来编译它们,先是把它们放在同一个目录下,注意的是,虽然A.java有package unmi.com;声明,我们还是先把它放在下B.java同一目录,希望由javac命令来生成相对应的包目录。

执行1.4或5.0或者是6.0的jdk所带的javac命令编译,提示的错误都是一样的

C:/Documents and Settings/unmi/jbproject/test/src>C:/Java/j2sdk1.4.2_10/bin/javac -d ./ A.java
或 C:/Documents and Settings/unmi/jbproject/test/src>C:/Java/jdk1.5.0_06/bin/javac -d ./ A.java
或 C:/Documents and Settings/unmi/jbproject/test/src>C:/Java/jdk1.6.0/bin/javac -d ./ A.java

错误为:

A.java:3: 需要 '.'
import B; //引用默认包中的B类
        ^
1 错误

如果把 A.java的 import B; 这一行注释掉,用上面的三种jdk进行编译也是出现同样的错误

A.java:7: 找不到符号
符号: 类 B
位置: 类 unmi.com.A
    B b = new B();
    ^
A.java:7: 找不到符号
符号: 类 B
位置: 类 unmi.com.A
    B b = new B();
              ^
2 错误

总之是在带有包名的 A类中不知道怎么去引用默认包(没有包声明)中的类B。事情到此为止也就只会提出一个疑问:Java为何不让带包名的类访问不带包名的类呢?到底有何用意,为什么要有这种限制呢?

可是奇怪的事情还在发生,如果我用1.2或1.3的jdk中的javac编译器来编译上面那两个代码,却是可以编译通过的,

C:/Documents and Settings/unmi/jbproject/test/src>D:/Borland/JBuilder7/jdk1.3.1/bin/javac -d ./ A.java

执行后一切正常,编译出了B.class文件在正前目录下,并且在建立的com/unmi目录中生成了A.class文件,用1.2的jdk的javac编译我在SunOS 5.8操作系统下试过,也没问题的。只要能够成功编译,无论在哪种版本的JVM中执行A.class都能得到预期结果,在A.class中调用B的实例方法print()打印出 Printed By B Class。

于是可以看出,这种所谓带包名的类不能访问不带包名的类只是不同版本的java编译器玩的把戏而已。

回到编译器中来说,用JBuilder7能正常编译以上代码,无论工程选择何种版本的jdk(比1.3高);而用JBuilder2005或是Eclipse3.2(其他版本的Eclipse还没有试验过)则不能编译以上代码,会提示以上的语法错误,不管工程选择的是1.2或1.3的jdk也无济于事。当然把以上两代码放在工程中的话需要把A.java放到com/unmi目录中的。看来IDE也有他们自己的独特的行为,大约为启动IDE本身的JVM的版本所决定(我的猜测)。

写下这个东西只要阐明一种现象(这也是我偶然用JBuilder2006打开一个JBuilder7中正常使用的工程出现错误才意识到的,而且不能轻易苟同某些人的坚持说非要用JBuilder7才行,同时他们还忽略了一个问题,生成的类既然需要拿到SunOS 5.8下的jvm1.2中运行,那何不一改JBuilder中该工程的Target JVM属性值为All Java SKDs即可),希望探求一个究竟,当然在平时编码中大可不必(并且是不应该)试图让包中的类去引用默认包中的类,为使每个类都体现出层次上的关系,应置于某一命名包中,除非一种例外,那是一个统领其他类的类,比如说Main,启动主程序的类,可以放在默认包中(不声明包名),因为它也不会被其他包中的类引用。

继续重复留下那样一个问题:新的JDK的编译器为何要试图阻止从有包名的一个java类引用默认包(未声明包名)的类呢?

更多内容请查看我的blog 隔叶黄莺 http://blogcn.com.cn
也是开个新贴回一下 如何在包内import包外的类? http://community.csdn.net/Expert/topic/4970/4970935.xml?temp=.1856043