静态导入

Java支持扩展的关键字import的用法,通过在import后面跟关键字static,import语句就可以用来导入类或接口的静态成员.这称为静态导入.使用静态导入时,可以直接通过静态成员的名称来引用他们,而不必使用其类名来限定他们.这样做简化并且缩短了使用静态成员的语法.
为了理解静态导入的用处,下面先介绍一个不使用他的示例.下面的程序求解一个二次方程,公式如下所示:
ax² + bx + c = 0
该程序使用两个来自Java内置数学类Math的静态方法,Math类属于java.lang.第一个静态方法是Math.pow(),他返回指定幂的值.第二个静态方法是Math.sqrt(),他返回实参的平方根.
    public static void main(String args[])
    {
     double a,b,c,x;
     
     a = 4;
     b = 1;
     c = -3;
     
     x = (-b + Math.sqrt(Math.pow(b, 2) - 4 * a *  c)) / (2 * a);
     System.out.println("First solution: "+x);
     
     x = (-b - Math.sqrt(Math.pow(b, 2) - 4 * a *  c)) / (2 * a);
     System.out.println("Second solution: "+x);
    }
由于pow()和sqrt()是静态方法,因此必须通过使用其类名Math来调用,这导致一长串的表达式:
x = (-b + Math.sqrt(Math.pow(b, 2) - 4 * a * c))  / (2 * a);
而且,每一次调用pow()或sqrt(),或者其他的数学方法,如sin(),cos()和tan()时都指定类名会很繁琐.
通过使用静态导入就可以消除这种指定类名的繁琐,下面是上述程序的新版本:
import static java.lang.Math.sqrt;
import static java.lang.Math.pow;
public class test2
{
    // @param args
    public static void main(String args[])
    {
     double a,b,c,x;
     
     a = 4;
     b = 1;
     c = -3;
     
     x = (-b + sqrt(pow(b, 2) - 4 * a * c)) / (2  * a);
     System.out.println("First solution: "+x);
     
     x = (-b - sqrt(pow(b, 2) - 4 * a * c)) / (2  * a);
     System.out.println("Second solution: "+x);
    }
}
该程序中,名称sqrt和pow使用如下静态导入语句声明:
import static java.lang.Math.sqrt;
import static java.lang.Math.pow;
在这两条语句之后,不再需要使用类名来限定sqrt()和pow(),因此,表达式会变得比较简洁,如下所示:
x = (-b + sqrt(pow(b, 2) - 4 * a * c)) / (2 *  a);
可以看到,这种形式要简短许多,也易读许多.
有两种基本形式的import static语句,第一种形式是前面的示例采用的,声明了单个名称,其基本形式如下所示:
import static pkg.type-name.static-member-name;
其中,type-name是包含所需静态成员的类或接口的名称.完整的包名由pkg指定.成员名称由static-member-name指定.
第二种形式导入所有的静态成员.其基本形式如下所示:
import static pkg.type-name;
在使用类定义的许多静态方法或域时,这种形式允许使用他们而不必逐个指定.因此,前面的程序也可以使用这一单条import语句来指定pow()和sqrt()(以及Match的其他所有静态成员):
import static java.lang.Math.*;
当然,静态导入不只局限于Math类或者局限于方法.例如,下面的语句引入了静态域System.out:
import static java,lang.System.out;
在该语句之后,可以向控制台进行输出而不必使用System来限定out,如下所示:
put.println("aaa");
是否像这样来导入System.out还值得考虑.尽管他简化了语句,但是他不再能够让所有人都清晰的看出被引用的out就是System.out.
尽管静态导入会代码便利,但是也不能滥用,别忘了,Java把库组织到包中就是为了避免名称空间的冲入,当导入静态成员时,会把这些成员提升到全局名称空间.因此,会增加潜在的名称空间冲突的可能性,并且可能会在无意中隐藏其他名称.如果在程序中只使用静态成员一两次,最好不用导入他.另外,某些静态名称如(System.out)组织的很大,不需要导入.静态导入用于需要重复使用的静态成员(例如执行一系列数据计算)的情况,总之,要善用而不是滥用该功能.
问:可以使用静态导入功能来导入自己创建的类的静态成员吗?
答:可以,可以使用静态导入功能来导入自己创建的类或接口的静态成员.当定义了多个需要在一个大型程序中频繁使用的静态成员时,这样做会很方便.例如,如果一个类定义了许多static final常量,这些常量定义了各种限制,那么使用静态导入会给你省去许多繁琐的键入工作.