前言

欢迎大家来到院长的博客,记录一下工作中的琐事。本文主要内容白话(说一下)import 导入 应不应该加上static关键字。

时间,今天下午。同事最近在做代码优化,准备将代码合并到Dev分支。我耳朵比较敏锐听到了,也想了解一下他优化了什么内容。于是上gitlab上看了一圈,发现代码中貌似有一些不妥的地方,并针对import static 导入方式做了一下面对面讨论。

下面将我个人想法和建议做一下梳理。希望能帮助到有需要的同学。如果哪里说的不对,欢迎大家指出。

java 不使用ffpmeg安装工具_开发语言

代码展示

下面代码,模拟一下今天下午的真实场景。XXXUtil代码中大约有20多个常量类 都是采用如下静态import导入的形式。

import static com.package.framework.cmd.Constants.LOGINSUCCESS;
import static com.package.framework.cmd.Constants.LOGINFAIL;
import static com.package.framework.cmd.Constants.LOGINCANCEL;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.;

public class XXXUtil {//类名
      switch (cmd) {
       case LOGINSUCCESS:
       	//执行具体的逻辑
         break;
      }
}

下列展示的是我认为这样写比较好的代码,不需要大量静态导入,同样达到一样的效果,直观清晰明了。虽然从编译结果、业务逻辑角度来说,上面写的代码你也不能说错或者有问题。但是总感觉很别扭,通过接下来说明和小例子。来阐述我得观点。

public class XXXXXUtil {//类名
      switch (cmd) {
       case  Constants.LOGINSUCCESS:
       	//执行具体的逻辑
         break;
      }
}



JAVA 知识了解

在 Java 中,静态导入的概念在 1.5 版本中引入。借助静态导入,我们可以直接访问类的静态成员,无需类名或任何对象。例如:我们可以通过使用 Math 类即Math.sqrt()来使用 Math 类的 sqrt() 方法,但是通过使用静态导入,我们可以直接访问 sqrt() 方法。

据SUN公司称,静态导入将提高代码可读性并增强编码。但是一些编程大佬们不认可这样的说法,认为它会导致程序混乱并且不利于编程。给到的建议是:如果没有特殊要求,尽量不要使用静态导入。为什么呢?文末会给出答案。

正常improt 导入

class HelloWorld{
	public static void main(String[] args){
		System.out.println(Math.sqrt(4));
		System.out.println(Math.pow(2, 2));
		System.out.println(Math.abs(6.3));
	}
}

输出:

2.0

4.0

6.3



静态导入

静态导入的方式,可以观察到下面的代码省略了Math。输出的结果也是一致的

import static java.lang.Math.*;

public class HelloWorld{
	public static void main(String[] args){
		System.out.println(sqrt(4));
		System.out.println(pow(2, 2));
		System.out.println(abs(6.3));
	}
}

输出:

2.0

4.0

6.3

静态导入升级版

静态导入的方式,可以观察到下面的代码省略了Math和System。输出的结果也是一致的

import static java.lang.Math.*;
import static java.lang.System.*;
public class HelloWorld{
	public static void main(String[] args){
		out.println(sqrt(4));
		out.println(pow(2, 2));
		out.println(abs(6.3));
	}
}

输出:

2.0

4.0

6.3

注意: System 是 java.lang 包中的一个类,out 是 System 类中的静态变量。通过静态导入的方式,我们可以不用类名去调用它。

静态导入带来的歧义点:
如果从多个不同的类中导入两个同名的静态成员,编译器会抛出错误,因为在没有类名限定的情况下,它将无法确定使用哪个成员。 代码和错误截图如下所示。

import static java.lang.Integer.*;
import static java.lang.Byte.*;
public class HelloWorld{
	public static void main(String[] args){
		out.println(MAX_VALUE);
	}
}

java 不使用ffpmeg安装工具_java_02

Error:Reference to MAX_VALUE is ambigious //错误:对 MAX_VALUE 的引用不明确

说明:在上面的代码中,我们试图访问 MAX_VALUE 变量,但是每个原始数据类型都包含 MAX_VALUE 变量,该变量在 Wrapper 类中预先声明。这里我们同时导入 Integer 和 Byte 类并尝试访问静态变量 MAX_VALUE。

但编译器会因为看到两个导入语句而感到懵逼,因为 Integer 和 Byte 类都包含一个静态变量 MAX_VALUE。因此这里编译器抛出一个错误,说Reference to MAX_VALUE is ambiguous。

正常import 导入和静态import 导入的区别

在正常import 导包中,我们能够访问任何包中存在的类和接口。但是使用静态导入,我们可以直接访问类的所有静态成员(变量和方法),而无需显式调用类名。

静态导入的优缺点:

  • 静态导入的优点:如果经常访问类的任何静态成员,则需要较少的代码。
  • 静态导入的缺点:过度使用静态导入功能,它会使程序不可读和不可维护。
  • 假如同时导入的两个类中又有重命名的静态成员,会出现报错。例如Integer类和Long类的MAX_VALUE。

总结:两个包中包含两个同名的类/接口是非常少见的。因此,正常导入我们很少会出现问题(歧义)。但是有可能两个类包含相同的变量,所以在静态导入会出现引用不明确报错。这就是为什么上面提到,如果没有这样特殊要求不建议使用静态引用的原因。