Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 344|回复: 0

[Java基础知识]逐渐挖掘Static Import

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-2 01:11:38 | 显示全部楼层 |阅读模式
    J2SE 1.5里引入了“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
       
         //精确的导入Math.sin和Math.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机制也支持一种不必逐一指出静态成员名称的导入方式。这时,要采用这样的语法:
       
         import static 包名.类或接口名.*;
         

         
        注意这种方式只是指出遇到来历不明的成员时,可以到这个类或接口里来查找,并不是把这个类或接口里的所有静态成员全部导入。
        清单2:用按需导入的方式,导入sin和PI
       
         //声明遇到来历不明的成员时到java.lang.Math中去寻找
         
    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:变量、常量、方法和内部类都可以导入
       
         package com.example.p3;
         

         
    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;
         
             }
         
         }
         
    }
         

         
       
         package com.example.p3;
         
    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:采用精确导入的形式的一个有效
       
         package com.example.p4;
         
    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”
         
         }
         
    }
         

         
       
         package com.example.p4;
         

         
    public class Importee1 {
         
         public static String name = "Name1";
         
         public static String pass = "Pass1";
         
    }
         

         
       
         package com.example.p4;
         

         
    public class Importee2 {
         
         public static String name = "Name2";
         
         public static String pass = "Pass2";
         
    }
         

         
        5.本地和外来的竞争
        有时候,导入的东西还可能和本地的东西相冲突,这种情况下的处理规则,是“本地优先”。
        清单5:本地的优先于外来的
       
         package com.example.p5;
         
    import static com.example.Zero.*;
         

         
    public class One {
         
         public static int flag = 1;
         
         public static void main(String[] args) {
         
             System.out.println(flag);//输出“1”
         
         }
         
    }
         

         
       
         package com.example.p5;
         

         
    public class Zero {
         
         public static int flag = 0;
         
    }
         

         
        6.Static Import的负面影响
        在编译期间,所有因Static Import的存在而简化了的名字,都会被编译器打回原型。因此在性能方面,Static Import没有任何影响。但是名字简化却可能造成一些维护方面的问题。
        去掉静态成员前面的类型名,固然有助于在频繁调用时显得简洁,但是同时也失去了关于“这个东西在哪里定义”的提示信息,增加了阅读理解的麻烦。如果导入的来源很著名(比如java.lang.Math),或者来源的总数比较少,这个问题并不严重;但是在不属于这两种的情况下,这就不是基本可以忽略的问题了。
        7.归纳总结
              借助J2SE 1.5里提供的Static Import机制,可以用一种更简单的方式,来访问类和接口的静态成员。不过,使用这一机制并不是没有代价的,在使用不当的时候可能给维护工作带来一定的困扰。因此,在具体使用之前,还要作一些两方面的权衡。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-20 03:13 , Processed in 0.387741 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表