Java import的作用

可是现在问题来了,因為很多package的名称非常的长,在编程时,要使用一个类要将多个包名.类名完全写出,会让代码变得冗长,减低了简洁度。例如

显得非常麻烦,于是Sun公司就引入了import。

import就是在java文件开头的地方,先说明会用到那些类别。
接着我们就能在代码中只用类名指定某个类,也就是只称呼名字,不称呼他的姓。

但是如果一个java文件里面有多个同个”姓”,即包名相同的类(例如上面的InputStream,InputStreamReader,BufferedReader都是java.io中的类),

我们一一写出显得比较繁杂,所以Sun就让我们可以使用

表示文件里面说到的类不是java.lang包的就是java.io包的。编译器会帮我们选择与类名对应的包。

那我们可不可以再懒一点直接写成下面声明呢?

历史告诉我们,这样是不行的。因為那些类别是姓 java.io 而不是姓 java。就像姓『诸葛』的人应该不会喜欢你称他為『诸』 先生吧。这样写的话只会将java包下的类声明,而不不会声明子包的任何类。

这里注意,java.lang包里面的类实在是太常太常太常用到了,几乎没有类不用它的, 所以不管你有没有写 import java.lang,编译器都会自动帮你补上,也就是说编译器只要看到没有姓的类别,它就会自动去lang包里面查找。所以我们就不用特别去 import java.lang了。

一开始说 import 跟 #include 不同,是因为import 的功能到此為止, 它不像#include 一样,会将其他java文件的内容载入进来。import 只是让编译器编译这个java文件时把没有姓的类别加上姓,并不会把别的文件程序写进来。你开心的话可以不使用import,只要在用到类别的时候,用它的全部姓名来称呼它就行了(就像例子一开始那样),这样跟使用import功能完全一样。

import的两种导入声明
单类型导入(single-type-import)
(例:import java.util.ArrayList; )
按需类型导入(type-import-on-demand)
(例:import java.util.*;)
有如下属性:

java以这样两种方式导入包中的 任何一个public的类和接口(只有public类和接口才能被导入)

上面说到导入声明 仅导入声明目录下面的类而不导入子包,这也是为什么称它们为类型导入声明的原因。

导入的类或接口的简名(simple name)具有编译单元作用域。这表示该类型简名可以在导入语句所在的编译单元的任何地方使用.这并不意味着你可以使用该类型所有成员的简名,而只能使用类型自身的简名。
例如: java.lang包中的public类都是自动导入的,包括Math和System类.但是,你不能使用它们的成员的简名PI()和gc(),而必须使用Math.PI()和System.gc().你不需要键入的是java.lang.Math.PI()和java.lang.System.gc()。

程序员有时会导入当前包或java.lang包,这是不需要的,因为当前包的成员本身就在作用域内,而java.lang包是自动导入的。java编译器会忽略这些冗余导入声明(redundant import declarations)。即使像这样
import java.util.ArrayList;
import java.util.*;
多次导入,也可编译通过。编译器会将冗余导入声明忽略.

Java程序中,是不允许定义独立的函数和常量的。即什么属性或者方法的使用必须依附于什么东西,例如使用类或接口作为挂靠单位才行(在类里可以挂靠各种成员,而接口里则只能挂靠常量)。

如果想要直接在程序里面不写出其他类或接口的成员的挂靠单元,有一种变通的做法 :
将所有的常量都定义到一个接口里面,然后让需要这些常量的类实现这个接口(这样的接口有一个专门的名称,叫(“Constant Interface”)。这个方法可以工作。但是,因为这样一来,就可以从”一个类实现了哪个接口”推断出”这个类需要使用哪些常量”,有”会暴露实现细节”的问题。

于是J2SE 1.5里引入了”Static Import”机制,借助这一机制,可以用略掉所在的类或接口名的方式,来使用静态成员。static import和import其中一个不一致的地方就是static import导入的是静态成员,而import导入的是类或接口类型。

如下是一个有静态变量和静态方法的类

平时我们使用这些静态成员是用类名.静态成员的形式使用,即staticFieldsClass.staticField或者staticFieldsClass.staticFunction()。

现在用static import的方式:

这里有几个问题需要弄清楚:

Static Import无权改变无法使用本来就不能使用的静态成员的约束,上面例子的StaticTest和staticFieldsClass不是在同一个包下,所以StaticTest只能访问到staticFieldsClass中public的变量。使用了Static Import也同样如此。

导入的静态成员和本地的静态成员名字相同起了冲突,这种情况下的处理规则,是”本地优先。

不同的类(接口)可以包括名称相同的静态成员。例如在进行Static Import的时候,出现了”两个导入语句导入同名的静态成员”的情况。在这种时候,J2SE 1.5会这样来加以处理:

如果两个语句都是精确导入的形式,或者都是按需导入的形式,那么会造成编译错误。
如果一个语句采用精确导入的形式,一个采用按需导入的形式,那么采用精确导入的形式的一个有效。

static import这么叼那它 有什么负面影响吗?

答案是肯定的,去掉静态成员前面的类型名, 固然有助于在频繁调用时显得简洁,但是同时也失去了关于”这个东西在哪里定义”的提示信息 ,理解或维护代码就呵呵了。
但是如果导入的来源很著名(比如java.lang.Math),这个问题就不那么严重了。

按需导入机制
使用按需导入声明是否会降低Java代码的执行效率?

绝对不会!

一、import的按需导入

编译之后的class文件 :

二、static import的按需导入

上面StaticNeedImportTest 类编译之后 :

这是否意味着你总是可以使用按需导入声明?

是,也不是!

在类似Demo的非正式开发中使用按需导入声明显得很有用。

然而,有这四个理由让你可以放弃这种声明:

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

Sun的工程师一般不使用按需类型导入声明.这你可以在他们的代码中找到:
在java.util.Properties类中的导入声明:

可以看到他们用单类型导入详细的列出了需要的java.io包中的具体类型。

Original: https://www.cnblogs.com/lukelook/p/12834940.html
Author: Rooker
Title: Java import的作用

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/537283/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【设计】springboot rabbitmq重试达到失败次数 进入死信队列

    代码示例: @Slf4j @Service @RabbitListener(queues = {"${spring.events.[event.product.produ…

    Java 2023年5月29日
    072
  • 优秀体现在细微处

    上面是团队内小王同学整理的需求评审计划,我们看最后一列的细节之处,即,加上了与这个需求相关的资料。 希望我们都能像上面的小王同学一样。 我们的信息,从不同角度来看,总会分散在不同的…

    Java 2023年6月15日
    074
  • 从餐厅服务员到一线互联网电商程序员(上)

    本系列文章分三部分: 上: 餐厅、洗浴会所打工经历。中: 大学求学创业经历。下: 互联网从业经历。 本文为第一部分,关注微信公众号 “真香号”,及时阅读 中…

    Java 2023年6月7日
    0119
  • md-resume-demo

    小明 概况: 6年工作经验 | 男 | 26岁(1990年5月16日)…

    Java 2023年6月5日
    0340
  • MySQL 数据库性能优化之索引优化

    Original: https://www.cnblogs.com/wxweven/archive/2012/04/18/2454984.htmlAuthor: wxwevenTi…

    Java 2023年6月9日
    0145
  • leetcode 110. Balanced Binary Tree 平衡二叉树(简单)

    一、题目大意 给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1: 输入…

    Java 2023年6月13日
    069
  • Java监控工具介绍,VisualVm ,JProfiler,Perfino,Yourkit,Perf4J,JProbe,Java微基准测试

    本文是本人前一段时间做一个简单Java监控工具调研总结,主要包括 VisualVm , JProfiler, Perfino, Yourkit, Perf4J, JProbe,以及…

    Java 2023年5月29日
    085
  • 如何成为一名JAVAEE软件工程师?(前言)

    笔者将会整理出一整套成为一个JAVAEE工程师的学习路线和资料。欢迎同行和网友们订阅或指正。不定期更新。 笔者在软件工作做了7年java开发,开发过ERP,CRM等应用系统并担任过…

    Java 2023年6月9日
    077
  • Java之异常

    Java 异常类层次结构图概览 : Exception 和 Error 有什么区别? 在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 Throwable…

    Java 2023年6月7日
    095
  • 商贸型企业 Java 收货 + 入库 + 生成付款单

    java;gutter:true; package cn.hybn.erp.modular.system.service.impl;</p> <p>impo…

    Java 2023年6月9日
    073
  • java宝典笔记(一)

    第四章java 基础知识 4.1 基本概念 一、java 优点 1.面向对象(封装、继承、多态) 2.可移植性。平台无关,一次编译,到处运行。Windows ,Linux ,mac…

    Java 2023年6月7日
    076
  • nginx 基本操作

    nginx 是什么 nginx 是轻量、高性能的网页服务器,相较 Apache 占有内存小。 下载 https://nginx.org/en/download.html 默认根目录…

    Java 2023年5月30日
    081
  • CMS前世今生

    CMS一直是面试中的常考点,今天我们用通俗易懂的语言简单介绍下。 垃圾回收器为什么要分区分代? 如上图:JVM虚拟机将堆内存区域分代了,先生代是朝生夕死的区域,老年代是老不死的区域…

    Java 2023年6月8日
    085
  • php判断远程文件是否存在

    php判断本地文件是否存在可以简单的使用is_file就可以实现。但是在部分情况下会检测远程文件是否存在,实现方式如下 1、可以使用fsocketopen,通过返回的状态码判断 2…

    Java 2023年6月8日
    084
  • VMware虚拟机中安装Linux操作系统(ubuntu)

    一、准备工作: 1、下载VMware虚拟机 下载地址:https://www.vmware.com/cn/products/workstation-pro/workstation-…

    Java 2023年6月9日
    075
  • MSSQL中UPDATE与 INNER JOIN联用的语法结构

    | 0.16分钟 | 267.2字符 | 1、引言&背景 2、解决方案 3、声明与参考资料 | SCscHero | 2022/4/30 PM9:36 | 系列 | 已完成…

    Java 2023年6月5日
    087
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球