个人理解——java中的import

顺便复习一下类加载器,java中的双亲委派模型如下:


启动类加载器:负责加载存放在JDK\jre\lib下或是Xbootclasspath参数指定的路径中能被JVM识别的类(不会加载不识别的类),无法在java程序中引用该加载器。

扩展类加载器:负责加载存放在JDK\jre\lib\ext下或是由java.ext.dirs系统变量指定的路径中的所有类库,可被java程序引用。

应用程序加载器:负责加载用户指定的类路径classpath上的类,可被java代码引用(使用ClassLoader.getSystemClassLoader()),如果没有定义自定义加载器,则该加载器默认为自定义加载器。

自定义类加载器:由程序员自己实现的类加载器。


双亲委派模型的工作方式:当一个类加载器接收到加载类请求时,会先将请求上传给自己的父加载器,父加载器又上交给自己的父加载器,最终传递给启动类加载器,当父加载器在自己的搜索范围没有找到对应类时,子类加载器才会开始尝试加载。


顺带提一下,我们常用的java.lang包存储在JDK\jre\lib中的rt.jar包下,利用jd_gui反编译后如下图:




那么类加载器通过什么来找到想要加载的类呢?通过类的全限定名,即包名+类名,例如java.lang.String,在class文件中会变为java\lang\String,其实,java和lang都是一个文件名,String是一个class文件,利用全限定名来加载类有很多好处,拿java.lang.String来说,当类加载请求传递给启动类加载器时,启动类加载器首先会在搜索范围内查找名为java的文件,若找到,会接着找名lang的文件,最后查找名为String的class文件,若没找到名为java的文件,启动类加载器会将加载请求丢给扩展类加载器,减少搜索时间,和子网一个道理,另外,使用全限定名加载类,意味着不同的包可以有名称相同的类。


那么class文件中的全限定名是怎么来的呢?

编译器编译时加上的。

那么编译器如何知道类的全限定名呢?

由import提供,import的主要作用就是为编译器提供全限定名。


import有两种语法:

A、import 包名.类名;

B、import 包名.*;


两者有什么区别呢?记得java老师是这么说的,语法B会加载所有的类,语法A会加载对应类,现在看来貌似不是,JVM只在运行时动态加载所需要的类。两者的区别我觉得主要体现在编译期。


下面进行一个实验,项目结构如下:



newclass0.deal.java代码如下:

package newclass0;  
public class deal  
{  
  public void output()  
  {  
    System.out.println("这是newclass0");  
  }  
}  


newclass1.deal.java代码如下:

package newclass1;  
public class deal  
{  
  public void output()  
  {  
    System.out.println("这是newclass1");  
  }  
}  


图一:


首先,java不允许import相同类名,为什么?

我们想使用import的原因之一是为了在引用同一个项目不同包中的类时,可以直接使用类名,若图一允许的话,我们想使用deal类,还是要加上包名来指出我们想引用哪个包的deal类。import毫无作用,所以java语法直接不允许这么使用。


图二:


从上图可以看到,当我们使用语法A时,编译器首先会查找newclass1包,查找到后在查找deal4类,没有查找到,所以报错


图三:


注意出错的位置,不在import,说明编译器在编译import语句时只会查找是否有newclass1包和newclass0包,不会具体查找里面的类,在出错位置,编译器在newclass0中发现类deal后并没有停止搜索,会在newclass1中继续搜索,运用语法B,则编译器会把所有运用语法B导入的包中的类都查一遍,以确保类的全限定名具有唯一性,若我们把

deal x=new deal();

改为:

newclass0.deal x=new newclass0.deal(); 

编译后通过,因为我们直接给出了类的全限定名,此时import语句无效(import就是为了提供全限定名的,但全限定名已经给出)


图四:


从上图可以看出,提供全限定名来说,优先级为语法A>语法B,若语法A满足全限定名,不会在去查找语法Bimport的包。


总结:在编译import语句时,编译器会查找项目中是否有对应的包或类,import编译通过后,下文中用到的import语句导入的类,编译器会根据import语句自动将其转换为包名\类名的全限定名,import主要是为了提供全限定名。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值