理解使用static import 机制(转)
在Java程序中,是不允许定义独立的函数和常量(当然,准确的说,只是被final修饰、只能赋值一次的变量)的。即使从它们本身的功能来看,完全不需要依附于什么东西,也要找个类或接口作为挂靠单位才行(在类里可以挂靠各种成员,而接口里则只能挂靠常量)。
挂靠的方法,是把它们加上static修饰符,定义为这个类或接口的静态成员。这方面的典型例子是java.lang.Math类——包含了大量的sin、cos这样的“函数”和PI、E这样的“常量”。
传统上,在访问这些挂靠了的函数、变量和常量的时候,需要在前面加上它们挂靠单位的名称。如果只是偶尔访问这些东西一下,这样的写法可以工作得很好;但是如果要频繁访问这些成员的话,这样的写法就显得比较罗嗦了。
J2SE 1.5里引入了“Static Import”机制,借助这一机制,可以用略掉所在的类或接口名的方式,来使用静态成员。
“静态导入”或者“静态成员导入”
Static Import机制常常被直译成“静态导入”。但是从含义上看,“静态成员导入”是更为贴切的译法。不过考虑到“静态导入”这说法比较简短,估计还是会有强大的生命力。
只包括常量定义的接口
有一种省去常量前的挂靠单位的变通做法:将所有的常量都定义到一个接口里面,然后让需要这些常量的类实现这个接口(这样的接口有一个专门的名目,叫作“Constant Interface”)。
这个方法可以工作。但是,因为这样一来,就可以从“一个类实现了哪个接口”推断出“这个类需要使用哪些常量”,有“会暴露实现细节”的问题。
1.精确导入的方式
精确的导入一个静态成员的方法,是在源文件的开头部分(任何类或接口的定义之前),加上类似这样的声明:
import static 包名.类或接口名.静态成员名;
注意尽管这个机制的名目是叫做“Static Import”,但是在这里的次序却是正好相反的“import static”。一经导入之后,在整个源文件的范围内,就可以直接用这个成员的名字来访问它了。
清单1:用精确导入的方式,导入sin和PI
import static java.lang.Math.sin;
import static java.lang.Math.PI;
public class StaticImportSampleA {
public static void main(String[] args) {
System.out.println(sin(PI/2));//输出“1.0”
}
}
游离于包外的类和接口们的特别问题
Java语言并未要求每个类和接口都必须属于某一个包。但是,在J2SE 1.4以后,无论是import语句也好,还是import static语句也好,都要求给一个所在包名出来。换而言之,对于不属于任何包的类和接口,是既不能用import导入它本身,也不能用import static导入它的静态成员的。
2.按需导入的方式
Static Import机制也支持一种不必逐一指出静态成员名称的导入方式。这时,要采用这样的语法:
注意这种方式只是指出遇到来历不明的成员时,可以到这个类或接口里来查找,并不是把这个类或接口里的所有静态成员全部导入。
清单2:用按需导入的方式,导入sin和PI
import static java.lang.Math.*;
public class StaticImportSampleB {
public static void main(String[] args) {
System.out.println(sin(PI/2));//输出“1.0”
}
}
3.可以导入的种种东西
使用import static语句,可以导入一个类里的一切被static修饰的东西,包括变量、常量、方法和内类。
清单3:变量、常量、方法和内部类都可以导入
public class StaticImportee {
public static int one = 1;
public static final int TWO = 2;
public static int three() {
return 3;
}
public static class Four {
public int value() {
return 4;
}
}
}
import static com.example.p3.StaticImportee.*;
public class StaticImporter {
public static void main(String[] args) {
System.out.println(one);
System.out.println(TWO);
System.out.println(three());
System.out.println(new Four());
}
}
不受影响的访问控制
Static Import不能突破Java语言中原有的访问控制机制的限制,不过也并不在这方面增加新的约束。原来有权限访问的静态成员,都可以被导入和使用;而原来无权限访问的静态成员,用了这个方法之后也仍然是访问不能。
4.导入之间的冲突问题
不同的类(接口)可以包括名称相同的静态成员。因此,在进行Static Import的时候,可能会出现“两个语句导入同名的静态成员”的情况。
在这种时候,J2SE 1.5会这样来加以处理:
- 如果两个语句都是精确导入的形式,或者都是按需导入的形式,那么会造成编译错误。
- 如果一个语句采用精确导入的形式,一个采用按需导入的形式,那么采用精确导入的形式的一个有效。
注意,如果两个同名的静态成员一个是属性,而另一个是方法,那么因为使用时的写法有差异,不会造成任何的冲突。
清单4:采用精确导入的形式的一个有效
import static com.example.p4.Importee1.name;
import static com.example.p4.Importee1.*;
import static com.example.p4.Importee2.*;
import static com.example.p4.Importee2.pass;
public class Importer {
public static void main(String[] args) {
System.out.println(name);//输出“Name1”
System.out.println(pass);//输出“Pass2”
}
}
public class Importee1 {
public static String name = "Name1";
public static String pass = "Pass1";
}
public class Importee2 {
public static String name = "Name2";
public static String pass = "Pass2";
}
5.本地和外来的竞争
有时候,导入的东西还可能和本地的东西相冲突,这种情况下的处理规则,是“本地优先”。
清单5:本地的优先于外来的
import static com.example.Zero.*;
public class One {
public static int flag = 1;
public static void main(String[] args) {
System.out.println(flag);//输出“1”
}
}
public class Zero {
public static int flag = 0;
}
6.Static Import的负面影响
在编译期间,所有因Static Import的存在而简化了的名字,都会被编译器打回原型。因此在性能方面,Static Import没有任何影响。但是名字简化却可能造成一些维护方面的问题。
去掉静态成员前面的类型名,固然有助于在频繁调用时显得简洁,但是同时也失去了关于“这个东西在哪里定义”的提示信息,增加了阅读理解的麻烦。如果导入的来源很著名(比如java.lang.Math),或者来源的总数比较少,这个问题并不严重;但是在不属于这两种的情况下,这就不是基本可以忽略的问题了。
7.归纳总结
借助J2SE 1.5里提供的Static Import机制,可以用一种更简单的方式,来访问类和接口的静态成员。不过,使用这一机制并不是没有代价的,在使用不当的时候可能给维护工作带来一定的困扰。因此,在具体使用之前,还要作一些两方面的权衡。
理解使用static import 机制(转)的更多相关文章
- 理解使用static import 机制
J2SE 1.5里引入了“Static Import”机制,借助这一机制,可以用略掉所在的类或接口名的方式,来使用静态成员.本文介绍这一机制的使用方法,以及使用过程中的注意事项. 在Java程序中,是 ...
- 理解Cookie和Session机制
转载: 理解Cookie和Session机制 会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录 ...
- 深入理解Cookie和Session机制
转载理解Cookie和Session机制 目录 Cookie机制什么是CookieCookie的不可跨域名性Unicode编码:保存中文BASE64编码:保存二进制图片设置Cookie的所有属性Coo ...
- 深入理解struts的运行机制
扫码关注公众号,不定期更新干活 在此申明本博文并非原创,原文:http://blog.csdn.net/lenotang/article/details/3336623,本文章是在此文章基础上进行优化 ...
- 【转】深入理解 Java 垃圾回收机制
深入理解 Java 垃圾回收机制 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...
- 深入理解java垃圾回收机制
深入理解java垃圾回收机制---- 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...
- 我理解的Hanlder--android消息传递机制
每一个学习Android的同学都会觉得Handler是一个神奇的东西,我也一样,开始我以为我懂了Handler的机制,后来发现自己是一知半解,昨天想想,我能否自己实现一个Handler,让子线程与Ac ...
- <转>ASP.NET学习笔记之理解MVC底层运行机制
ASP.NET MVC架构与实战系列之一:理解MVC底层运行机制 今天,我将开启一个崭新的话题:ASP.NET MVC框架的探讨.首先,我们回顾一下ASP.NET Web Form技术与ASP.NET ...
- 深入理解 Java 垃圾回收机制
深入理解 Java 垃圾回收机制 一:垃圾回收机制的意义 java 语言中一个显著的特点就是引入了java回收机制,是c++程序员最头疼的内存管理的问题迎刃而解,它使得java程序员 ...
随机推荐
- SAP-Basic:使用SCC1时提示 TA263“集团被集团副本锁定用于输入”
错误信息 消息号TA263 解决方法 Step 1.使用SCC4进入"集团管理"界面. Step 2.双击要维护的集团,例如"010",进入详细配置界面 ...
- 利用d3.js绘制雷达图
利用d3,js将数据可视化,能够做到数据与代码的分离.方便以后改动数据. 这次利用d3.js绘制了一个五维的雷达图.即将多个对象的五种属性在一张图上对照. 数据写入data.csv.数据类型写入typ ...
- [Angular 2] Using Pipes to Filter Data
Pipes allow you to change data inside of templates without having to worry about changing it in the ...
- 在Eclipse中使用JUnit4进行单元測试(0基础篇)
本文绝大部分内容引自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,须要写成千上万个方法或函数,这些函数的功能可能 ...
- Spring中的AOP
什么是AOP? (以下内容来自百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种 ...
- 一行代码实现iOS序列化与反序列化(runtime)
一.变量声明 为便于下文讨论,提前创建父类Biology以及子类Person: Biology: @interface Biology : NSObject { NSInteger *_hairCou ...
- codevs 1242 布局(查分约束+SPFA)
/* 查分约束. 给出的约束既有>= 又有<= 这时统一化成一种 Sb-Sa>=x 建边 a到b 权值为x Sb-Sa<=y => Sa-Sb>=-y 建边 b到a ...
- NPOI从数据库中导出数据到Excel
首先要添加NPOI.dll程序集 https://yunpan.cn/cMeSTELJSXmJJ 访问密码 8d83 把里面的程序集都添加到引用里 下面的代码是从数据库导出到Excel { //pa ...
- java直接输出Excel 页面实现下载
public String excelDomnload() throws Exception{ try{ /* String path = GlobalKeys.getFunctionConfig(& ...
- 【转】 iOS学习之sqlite的创建数据库,表,插入查看数据
原文: http://blog.csdn.net/totogo2010/article/details/7702207 iOS sqlite数据库操作.步骤是: 先加入sqlite开发库libsql ...