介绍
在我看来,这篇文章提出了Java语言应该如何发展以保持其作为首选语言的地位。 它还提供了一些我喜欢但有时(可能永远不会)成为Java一部分的功能,由于我将要解释的某些原因,这些功能有时我已经爱上了。 我真的很想一天将其中一些想法转换为JSR。
在过去的15年中,Java语言和JVM得到了极大的改进。 JIT编译器,泛型的应用,自动装箱,很快(指尖)的lambda……所有这些功能都为Java的成功做出了贡献。 但是接下来呢? 如何使Java更好?
通过我的经验,我有机会使用几种编程语言。 其中包括C#,C / C ++,PHP,Javascript,Groovy,ActionScript 3,Scala等。在许多这些语言中,我发现了一些使我说“真棒!”的功能。 其中一些功能不适用于Java(不同的编程范例,不同的思维方式),而另一些则完全适用。 同样在其中一些语言中(主要是PHP),我看到了让我说“ OMG! 真是胡扯!”……但这是一个不同的故事!
在该系列的每一部分中,我将介绍一个Java中不存在的功能,并解释为什么它应该(或不应该)在Java中,可能要解决的问题,等等。
不要犹豫,发布改进的想法,甚至是最疯狂/不切实际的想法! 我并不假装自己有完美的解决方案,我只是尝试打开讨论。
属性访问器
在我看来,这篇文章提出了Java语言应该如何发展以保持其作为首选语言的地位。 它还提供了一些我喜欢但有时(可能永远不会)成为Java一部分的功能,由于我将要解释的某些原因,这些功能有时我已经爱上了。 我真的很想一天将其中一些想法转换为JSR。
通过透明访问器访问对象的字段绝对是我在Java中缺少的功能。
它是什么?
在Java中,我们使用getter和setter来访问对象的属性。 我不会说拥有getter和setter而不是拥有公共字段的好处,我假设您已经意识到……在其他语言(C#,AS3,…)中,您可以显式声明属性的getter和setter。就像使用公共财产一样使用它们。 我最喜欢的语法是一种ActionScript3:
//Object Declaration
public class MyObject {private var _myProperty:String;public function get myProperty():String {return _myProperty;}public function set myProperty(value:String):void {_myProperty = value;}public function get firstLetter():String {return _myProperty.substr(0,1);}
}//Usage
var o:MyObject = new MyObject();
o.myProperty = 'A value'; //Set the property using the setter
trace(o.myProperty); //Print the value return by the getter
trace(o.firstLetter); //Print 'A'
Java语法建议
由于我认为ActionScript 3语法非常方便,因此我认为Java语法应该非常相似。 这将需要添加新的修饰符 : get
和set
。
public class MyObject
{private String _name;public get String name() {return name;}public set void name(String name) {this.name = name;}
}//Usage
MyObject o = new MyObject();
o.name = 'My name';
System.out.println('print entity : ' + o.name);
好处
- 使用访问器是透明的。 封装是隐式的。 调用者不知道它是在调用公共变量还是访问器。
- 更好的OO风格编程:从外部类的角度来看,一个对象现在确实具有公共方法和属性,而以前只是公共方法。
- 重构代码以更改对对象字段的所有直接访问实在是小菜一碟,您只需要更改相关的类即可,而不必更改所有的读/写调用。
- 不再需要在getter和setter上使用JavaBean约定。 有些库依赖于
myProperty
器称为[get|is|set]MyProperty
的事实。 现在,不再按约定定义承包人,而是按合同定义。 我们可以在Class
上有一个方法来检索访问器(getGetters(),getSetters())。 再次,大大提高了OOP。
缺点
- 由于方法和属性的名称可能相同,因此需要更改对象字段的命名约定。 毫无疑问,JVM可以允许属性和方法具有相同的名称,这更多是可读性问题。
实施与问题
要实现此功能,需要向Java语言添加两个新关键字( get
和set
)。 对于追溯兼容性而言,这是一件坏事,但这并不是一个大问题。 在Java 1.4中添加assert关键字之前,将需要使用“ -source”命令行选项。
此更改还需要修改JVM规范,以及Java编译器,以添加两个新的修饰符。 在类文件中需要使用这两个新的修饰符,以便使用反射来标识类的getter和setter。
我相信此功能将对Java语言做出令人敬畏的改进。 作为所有重大改进,它需要大量工作。 如果有一天我有足够的时间提交JSR,那肯定是这一天!
线程安全编译检查
在我看来,这篇文章提出了Java语言应该如何发展以保持其作为首选语言的地位。 它还提供了一些我喜欢但有时(可能永远不会)成为Java一部分的功能,由于我将要解释的某些原因,这些功能有时我已经爱上了。 我真的很想一天将其中一些想法转换为JSR。
线程安全编译检查:这是什么?
它可以检查您的程序是否不会由于多线程而出现问题。 据我所知,没有一种编程语言提供此功能(如果您知道一种,请告诉我!)。
问题是什么?
开发在多个线程中运行的程序很容易,而开发不会有任何奇怪错误的东西,因为线程机制要困难得多。
为什么并发编程很难?
因为,要制作一个好的多线程应用程序,您必须非常小心并完全了解Java语言和API:避免出现死锁,知道何时使用volatile关键字,知道什么是(或不是)线程安全的。
另一个困难是测试/调试多线程应用程序非常困难。 您可能花了几天的时间想知道为什么在庞大的数据库中,您的行中有一个奇怪的日期值……最终要认识到您的共同开发者(当然不是您,因为您是Java专家 )使用了多个线程共享的SimpleDateFormat对象……(顺便说一句,如果您不知道:是的,SimpleDateFormat不是线程安全的)
解决办法是什么?
线程安全编译检查! 如果有警告告诉您“在第36行:不是线程安全代码”,它将使开发变得更加容易。 使用非线程安全方法SimpleDateFormat.format”。
为什么不可能
非线程安全API的用法
目前,了解所使用的库/ API是否是线程安全的唯一方法是读取Javadoc或源代码。 因此,编译器无法知道您调用的是线程安全的还是不线程安全的。 通过可传递性,如果您不使用任何种类的同步机制,则由于使用这些库,因此无法知道您的代码是否是线程安全的。
解决此问题的一种方法是创建一个@ThreadSafe注释来注释类和方法。 这样,任何用@ThreadSafe注释的元素都将被编译器视为线程安全的。 当然,您使用的所有API都需要正确注释。除了进行编译检查之外,我认为这样的注释对于使API更加清晰非常有用。
反射API
Reflection API是另一个问题。 由于执行流程是在运行时期间确定的,因此编译器无法知道将调用哪些方法,因此无法确定将要执行的内容是否是线程安全的。
编译器需要了解上下文
编译器无法知道您正在开发的内容是否将在线程安全的环境中执行。 例如,如果您正在开发将由您最喜欢的CDI框架注入到各处的bean,则编译器无法知道它。
换句话说,编译器比您了解的少,因此无法确定您正在编程的内容是否需要线程安全。 假设您正在为J2EE应用程序编程控制器; 如果您不使用假设的@ThreadSafe注释对控制器进行注释,则编译器将永远不会抱怨。 问题是您的控制器必须是线程安全的! 如果您没有使用@ThreadSafe正确注释必须是线程安全的内容,那么您将遇到问题...
不同的锁机制
如果同步线程的唯一方法是synced关键字,则对于编译器而言,确定一段代码是否可以同时运行比较容易。 不幸的是,事实并非如此! 您有几种方法可以确保仅在正确的上下文中执行代码( ReentrantLock , ReadWriteLock ,使用文件,套接字,对象,计数器等的手动锁定)。 对我而言,这仅是导致“线程安全编译检查”无法实现的原因。 如果编译器无法发现同步机制,则它对线程安全一无所知!
结论
线程安全编译检查肯定是一个杀手级功能。 但是对我来说,甚至不可能部分实现,这也许就是为什么我从未在任何语言中看到过此功能的原因。
如果您对解决方案有任何想法,或者您知道某种解决方案的语言(甚至是部分语言),请告诉我!
参考: Java SE 11:Java向前推进-第1部分: Java SE 11:Java向前推进-第2部分:属性访问器 , Java SE 11:Java Java向前推进-第3部分:来自我们JCG合作伙伴 Tibo Delor的线程安全编译检查在InvalidCodeException博客上。
翻译自: https://www.javacodegeeks.com/2012/11/java-se-11-moving-java-forward.html