前言:
现时你们对“oracle去掉日期横线”都比较注意,各位老铁们都需要学习一些“oracle去掉日期横线”的相关文章。那么小编也在网络上收集了一些有关“oracle去掉日期横线””的相关资讯,希望小伙伴们能喜欢,同学们一起来了解一下吧!通过本文了解Java8以来这门语言的发展。
作者 | Dávid Csákvári
译者 | 弯月,责编 | 郭芮
出品 | CSDN(ID:CSDNnews)
以下为译文:
当年Java 8引进的Stream和Lambda是一项重大改进,编写函数式编程风格的代码不再需要写大量的样板代码。虽然近期的版本并没有引入如此重大的改进,但Java还是引入了很多小改进。
这篇文章总结了Java 8之后引入的语言改进。如果你想了解新平台背后的JEP,请参考这篇文章:
局部变量类型推断
var关键字可能是Java 8之后最重要的语言改进了。该关键字最初在Java 10引入,在Java 11得到了大幅改进。
有了它,我们就可以在定义局部变量时省略类型定义,减少繁文缛节:
var greetingMessage = "Hello!";
尽管看上去这很像JavaScript的var关键字,但它并不是动态类型。
引用如下JEP的一段话:
我们希望通过减少编写Java代码时的繁文缛节来改善编程的体验,同时维持Java的静态类型安全。
这样定义的变量的类型会在编译时进行推断,上述示例中推断的类型为String。使用var而不是显式指定类型,可以让代码更加简洁,故而可以提高代码的可读性。
下面是类型推断的另一个例子:
MyAwesomeClass awesome = new MyAwesomeClass;
显然,知许多情况下这个特性都可以改进代码质量。但是,有时候还是使用显式类型定义更好。我们来看看一些不宜使用var替换类型定义的情况。
随时考虑可读性
第一种情况就是从源代码中删除类型定义可能会降低可读性的情况。
当然这种情况还可以借助IDE,但在代码审核过程中,或者需要快速阅读代码的情况下,这样做就可能影响可读性。比如工厂模式,你只能去寻找负责生成对象的代码来确定生成的对象类型。
下面是一个小测验。下面的代码使用了Java 8的日期和时间API。猜一猜下面代码中的变量类型:
var date = LocalDate.parse("2019-08-13");var dayOfWeek = date.getDayOfWeek;
var dayOfMonth = date.getDayOfMonth;
做完了?答案如下所示。
第一行很直观,parse方法返回LocalDate对象。但是后两个你必须对API有一定了解才能得出正确答案:dayOfWeek返回java.time.DayOfWeek,而dayOfMonth返回int。
使用var的另一个潜在问题是,阅读者不得不进一步依赖注释。考虑下面的代码:
private void horriblyLongMethod {// ...
// ...
// ...
var dayOfWeek = date.getDayOfWeek;
// ...
// ...
// ...
}
有了上一个例子的经验,我打赌你肯定会猜它是java.time.DayOfWeek。但这次是个整型,因为本例中的date是Joda时间。这是个不同的API,行为也略有不同,但你没有发现,因为这个方法非常长,而你并没有阅读所有代码。
如果这里给出了显式类型定义,那么确定dayOfWeek就非常容易。而使用var时,阅读者首先要找到date变量的类型,并检查其getDayOfWeek的行为。在IDE中很容易理解,但快速阅读代码时就没那么容易了。
注意保留重要的类型信息
第二种情况是,使用var会丧失所有类型信息,甚至导致无法推断。大多数情况下这个问题会被Java编译器捕获。例如,var不能推断lambda或方法引用,因为在这些特性中,编译器依赖左侧的表达式来确定类型。
但是有一些例外。例如,var不能很好地用于菱形操作符。在创建泛型的实例时,菱形操作符可以让表达式右侧不那么繁琐:
Map<String, String> myMap = new HashMap<String, String>; // Pre Java 7Map<String, String> myMap = new HashMap<>; // Using Diamond operator
由于该运算符只处理泛型类型,所以我们依然可以去掉一些冗余。我们可以通过var进一步简化:
var myMap = new HashMap<>;
这个例子是合法的,而且Java 11编译器甚至都不会发出警告。但是,我们没有为泛型类型指定任何类型,导致所有类型都必须推断,所以最后的类型是Map<Object, Object>。
当然,只需去掉菱形运算符就可以解决这个问题:
var myMap = new HashMap<String, String>;
另一个问题是在基本数据类型上使用var:
byte b = 1;short s = 1;
int i = 1;
long l = 1;
float f = 1;
double d = 1;
如果不给出显式类型定义,那么所有变量都会被推断为int。所以,使用基本数据类型时要使用类型字面量(例如1L),或者不要使用var。
务必阅读官方的风格指南
何时使用类型推断、怎样做不会破坏易读性和正确性,这些问题最终都需要你自己判断。经验法则是:遵循优秀的编程实践,比如良好的命名规则、尽力减小局部变量作用域等都会有很大帮助。请务必阅读官方有关var的风格指南()和FAQ()。
虽然var有如此多的陷阱,但很幸运它的引入相当保守,现在只能用于作用域有限的局部变量。
而且,var的引入也十分谨慎,var并不是新的关键字,而是保留类型名。这就意味着,只有当作为类型名使用时才有特殊含义。任何其他位置出现的var依然只是个合法的标识符。
目前,var没有相应的不可修改版本(如val或const)来定义常量并推断类型。希望以后的版本能够添加这个关键字,在那之前我们可以先使用final var。
参考资料:
与Java 10的var的第一次亲密接触()
Java局部变量类型推断详解()
Java 10:局部变量推断()
Project Coin带来的多项改进
Project Coin(JSR 334,)是JDK 7的一部分,它带来了许多方便的语言改进:
菱形运算符
try-with-resources语句
多catch和更精确的重新throw
在switch语句中使用字符串
二进制整形字面量和数值字面量中的下划线
简化的varargs方法调用
Java 9继续做出了许多小改进。
接口支持私有方法
从Java 8起可以给接口添加默认方法。在Java 9中,这些默认方法甚至可以调用私有方法,这样无需公开就可以复用代码。
尽管算不上重大改进,但能够让默认方法中的代码更简洁。
匿名内层类的菱形操作符
Java 7引入了菱形操作符(<>),让编译器推断构造函数的参数类型,来减少繁琐:
List<Integer> numbers = new ArrayList<>;
但是,以前该功能不能用于匿名内层类上。根据项目的邮件列表中的讨论()可知,该功能没有作为菱形运算符的最初特性实现的原因是它需要JVM做出重大变更。
在Java 9中这个边缘情况终于解决了,因此现在的菱形运算符更通用:
List<Integer> numbers = new ArrayList<> {// ...
}
try-with-resources语句中允许使用没有发生实质性改变的变量
Java 7引入的另一项改进就是try-with-resources语句,从此程序员无需再担心释放资源的问题。
我们来演示一下这个功能。首先,在Java 7之前如果想正确关闭资源,需要这样写:
BufferedReader br = new BufferedReader(...);try {
return br.readLine;
} finally {
if (br != ) {
br.close;
}
}
有了try-with-resources语句,资源就可以自动释放,省却了许多繁文缛节:
try (BufferedReader br = new BufferedReader(...)) {return br.readLine;
}
尽管这个功能非常强大,但它有几个缺点(Java 9解决了这些缺点)。
虽然这种方法能处理多个资源,但很容易让代码丧失可读性。像这样在try关键字之后以列表的方式定义变量,看起来非常不符合常见的Java编程习惯:
try (BufferedReader br1 = new BufferedReader(...);BufferedReader br2 = new BufferedReader(...)) {
System.out.println(br1.readLine + br2.readLine);
}
而且,在Java 7之前,如果你想用这种写法来处理已有的变量,就必须定义一个临时变量。(例如JDK-8068948中的例子:。)
为了解决这些问题,Java增强了try-with-resources,现在不仅能够处理新创建的变量,还能够处理局部常量,或者实际上不可变的局部变量:
BufferedReader br1 = new BufferedReader(...);BufferedReader br2 = new BufferedReader(...);
try (br1; br2) {
System.out.println(br1.readLine + br2.readLine);
}
在这个例子中,变量初始化不需要跟try-with-resources的初始化部分写在一起。
不过需要注意的一个陷阱是,现在允许访问已经被try-with-resources释放的资源,绝大部分情况下这种访问都会失败:
BufferedReader br = new BufferedReader(...);try (br) {
System.out.println(br.readLine);
}
br.readLine; // Boom!
下划线不再是有效的标识符
在Java 8中,如果使用下划线作为标识符,编译器就会发出警告。Java 9更进一步,禁止仅使用下划线作为标识符,将其留给未来的特殊语义使用。
int _ = 10; // Compile error
改进的警告
最后,我们提一下新版Java中有关编译器警告的改进。
现在可以用@SafeVarargs给私有方法添加注释,来避免错误的Type safety: Potential heap pollution via varargs parameter警告。(实际上,这个改动是之前提到过的JEP 213: Milling Project Coin中的一部分)。
有关Varargs的更详细内容可以看这里()。组合使用官方文档中提到的这些功能可能会造成泛型()及其潜在问题()。
此外,从Java 9开始,编译器不会再因为导入被弃用的类型的import语句而产生警告。这些警告没有提供有用的信息,而且完全是多余的,因为在实际使用被弃用的类型成员时必然会产生警告。
文本讨论了Java 8之后的版本中这门语言本身的改进。随时关注Java平台很重要,因为现在的发布节奏很快,每六个月就会发布一个新版本,平台和语言也会发生相应的变化。
原文:
作者:Dávid Csákvári,全栈工程师,在Java和Web技术方面有十多年的经验。
【END】
标签: #oracle去掉日期横线