在 Java 中,关键字 package,包命名模式和关键字 import 给了你对于名称的完全控制权,因此可以轻易地避免名称冲突的问题。

package

package这种方式极大降低了类之间的命名冲突

import

  • 对比 #include

include 会将其指定的java文件的内容全部载入进来,而import 只是让编译器编译这个java文件时把没有全限定类名的类加上权限定类名,并不会把别的文件程序写进来。因此,你开心的话可以不使用import,只要在用到类别的时候,使用它的权限定类名即可,当然这样会变得比较麻烦。

  • 注意

当前包或java.lang包是不需要手动导入的,因为当前包的成员本身就在作用域内,而java.lang包是自动导入的。

单类导入

single-type-import
例:import java.util.ArrayList;
在生产环境中尽量使用单类导入

按需导入

type-import-on-demand)
例:import java.util.;
使用按需导入声明是否会降低Java代码的执行效率? *绝对不会!
因为static import的精准导入以及按需导入编译之后都会变成import的单类型导入。但在生产环境中还是推荐使用单类导入,因为按需导入有如下劣势:

  1. 编译速度:在一个很大的项目中,它们会极大的影响编译速度.但在小型项目中使用在编译时间上可以忽略不计。
  2. 命名冲突:解决避免命名冲突问题的答案就是使用全名。而按需导入恰恰就是使用导入声明初衷的否定。
  3. 说明问题:毕竟高级语言的代码是给人看的,按需导入看不出使用到的具体类型。
  4. 无名包问题:如果在编译单元的顶部没有包声明,Java编译器首选会从无名包中搜索一个类型,然后才是按需类型声明。如果有命名冲突就会产生问题。

static import

import导入的是类或接口类型,而static import导入的是静态成员。
通过static import去掉静态成员前面的类型名,固然有助于在频繁调用时显得简洁,但是同时也失去了关于“这个东西在哪里定义”的提示信息,降低了代码的可读性,增加了维护成本。

访问控制

private default protected public
本类 ✔️ ✔️ ✔️ ✔️
同包类 ✔️ ✔️ ✔️
不同包子类 ✔️ ✔️
不同包非子类 ✔️

注意:此处的同包是严格意义上的同包,即使在子包中也不能算访问。

  • Why:
    • 不同包子类的访问权限中,子类实例,可以访问其从不同包基类继承而来的protected成员,而不能访问该基类实例的protected方法。
      • 产生这个问题的主要是我们把在包内访问的方式理解强加到了包外。为什么跨包访问某个类的protected方法必须通过继承呢?其实我们又可以转换问题为什么跨包访问某个类的protected方法必须通过继承呢?答案很简单,通过继承呢,子类就可以获得了父类方法的地址信息并把这些信息保存到自己的方法区,这样就可以通过子类对象访问自己的方法区从而间接的访问父类的方法(重写的话,就直接访问子类自己重写后的方法)。
      • 出自 《Java in a nutshell》的一段话:类B继承了类A,包括protected成员区域,所以能通过B对象来调用这个区域访问该方法。而在类B是无法查看对象A的protected成员区域的,是因为类B并没有继承对象A的protected成员区域,类B只是继承了类A的protected成员区域。
      • 通过上面的分析也很好解释了protected的静态方法能访问!
  • 访问控制的两个主要作用
    • 使用户不要接触他们不该接触的部分,提高代码的可读性
    • 让类库设计者更改类内部的工作方式,而不用担心会影响到客户端程序员,实现消费者和提供者解耦