Вступление
В этой серии статей рассказывается, как, на мой взгляд, язык Java должен развиваться, чтобы оставаться основным языком выбора. В нем также представлены некоторые функции, иногда уже существующие на другом языке, которые я люблю, но которые не могут (или не должны быть) частью Java, по некоторым причинам, которые я объясню. Я бы очень хотел превратить некоторые из этих идей в JSR.
За последние 15 лет язык Java и JVM были значительно улучшены. JIT-компилятор, появление дженериков, автобокс, скоро (скрестив пальцы) лямбды… Все эти функции способствовали успеху Java. Но что дальше? Как сделать Java лучше?
Благодаря своему опыту, у меня была возможность работать с несколькими языками программирования. Это включает в себя C #, C / C ++, PHP, Javascript, Groovy, ActionScript 3, Scala и некоторые другие … Во многих из этих языков я обнаружил некоторые особенности, которые заставили меня сказать «это чертовски здорово!». Некоторые из этих функций не были применимы к Java (другая парадигма программирования, другое мышление), в то время как другие были полностью применимы. Также в некоторых из этих языков (в основном в PHP…) я видел вещи, которые заставляли меня говорить «О Боже! Это дерьмо! »… Но это другая история!
В каждой части этой серии я представлю одну особенность, которая не существует в Java, и объясню, почему она должна (или нет) быть в Java, возможные проблемы, с которыми нужно иметь дело, и т. Д…
Не стесняйтесь размещать идеи улучшения, даже самые безумные / нереальные! Я не претендую на идеальные решения, я просто пытаюсь открыть дискуссию.
Свойства доступа
В статье представлено, как, на мой взгляд, должен развиваться язык Java, чтобы он оставался лучшим выбором. В нем также представлены некоторые функции, иногда уже существующие на другом языке, которые я люблю, но которые не могут (или не должны быть) частью Java, по некоторым причинам, которые я объясню. Я бы очень хотел превратить некоторые из этих идей в JSR.
Доступ к полям объекта через прозрачный метод доступа — определенно та функция, которую мне не хватает в Java.
Что это такое?
В Java мы используем геттеры и сеттеры, которые позволяют получить доступ к свойству объекта. Я не буду говорить о преимуществах наличия методов получения и установки вместо открытых полей. Я предполагаю, что вы знаете об этом … В других языках (C #, AS3, …) вы можете явно объявить методы получения и установки свойства и используйте их так, как если бы вы использовали публичную собственность. Мой любимый синтаксис — это ActionScript3:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//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
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
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: с точки зрения внешнего класса vue объект теперь действительно имеет открытые методы и свойства, тогда как раньше он был только открытым методом.
- Рефакторинг кода для изменения всех прямых обращений к полям объекта — это просто, просто нужно изменить соответствующий класс, а не все вызовы чтения / записи.
- Больше не нужно иметь соглашения JavaBean для получения и установки. Некоторые библиотеки полагались на тот факт, что средства доступа
myProperty
называются[get|is|set]MyProperty
. Теперь аксессоры определяются не соглашением, а договором. У нас может быть метод классаClass
который извлекает метод доступа (getGetters (), getSetters ()). Еще раз большое улучшение ООП.
Недостатки
- Потребуется изменить соглашение об именах полей объекта, поскольку метод и свойство могут иметь одно и то же имя. Нет сомнений в том, что JVM может позволить, чтобы свойство и метод имели одно и то же имя, это скорее проблема читабельности.
Реализация и проблемы
Реализация этой функции потребует добавления двух новых ключевых слов ( get
и set
) к языку Java. Это плохо для ретро-совместимости, но это не большая проблема. Необходимо будет использовать параметр командной строки «-source», как это было сделано ранее, когда ключевое слово assert было добавлено в Java 1.4.
Это изменение также потребует изменения спецификации JVM и компилятора java для добавления двух новых модификаторов. Эти два новых модификатора необходимы в файле класса, чтобы идентифицировать, используя отражение, методы получения и установки класса.
Я считаю, что эта функция будет отличным улучшением языка Java. Как и все основные улучшения, он требует много работы. Если однажды я почувствую себя достаточно готовым представить JSR, то это точно будет именно этот!
Потокобезопасная проверка компиляции
В этой серии статей рассказывается, как, на мой взгляд, язык Java должен развиваться, чтобы оставаться основным языком выбора. В нем также представлены некоторые функции, иногда уже существующие на другом языке, которые я люблю, но которые не могут (или не должны быть) частью Java, по некоторым причинам, которые я объясню. Я бы очень хотел превратить некоторые из этих идей в JSR.
Проверка компиляции Thread Safe: что это?
Это возможность проверить, что ваша программа не будет иметь проблем из-за многопоточности. Насколько я знаю, ни один язык программирования не обеспечивает такую функциональность (если вы знаете один, пожалуйста, дайте мне знать!).
В чем проблема?
Разработать программу, которая работает в нескольких потоках, легко, разработать что-то, что не будет иметь каких-либо странных ошибок из-за того, что механизм потока намного сложнее.
Почему параллельное программирование сложно?
Потому что, чтобы создать хорошее многопоточное приложение, вы должны быть очень осторожны и прекрасно знать язык Java и API: избегать тупиков, знать, когда использовать ключевое слово volatile , знать, что (или нет) поточно-ориентировано.
Другая трудность заключается в том, что тестирование / отладка многопоточных приложений очень сложны. Вы можете потратить несколько дней на размышления о том, почему в вашей огромной базе данных есть эта строка со странным значением даты… Чтобы окончательно осознать, что ваш со-разработчик (конечно, не вы, так как вы — гава-гуру) ) использовал объект SimpleDateFormat, совместно используемый несколькими потоками… (Кстати, если вы не знали: да, SimpleDateFormat не является потокобезопасным)
Каково решение?
Потокобезопасная проверка компиляции! Это сделало бы разработку намного проще, если бы у вас было предупреждение: «В строке 36: не потокобезопасный код. Использование не потокобезопасного метода SimpleDateFormat.format ».
Почему это невозможно
Использование не поточно-безопасных API
На данный момент единственный способ узнать, являются ли используемые вами библиотеки / API-интерфейсы безопасными для потоков, — это прочитать Javadoc или исходный код. Таким образом, компилятор не может знать, является ли то, что вы называете, потокобезопасным или нет. Благодаря транзитивности, если вы не используете какой-либо механизм синхронизации, он не может узнать, является ли ваш код поточно-ориентированным или нет, поскольку вы используете эти библиотеки.
Одним из решений этой проблемы может быть создание аннотации @ThreadSafe для аннотирования классов и методов. Таким образом, любой элемент, аннотированный @ThreadSafe, будет рассматриваться компилятором как поточно-ориентированный. Конечно, все API, которые вы используете, должны быть правильно аннотированы … Помимо проверки компиляции, я думаю, что такая аннотация была бы хороша, чтобы сделать API более понятными.
Reflection API
Reflection API — другая проблема. Поскольку поток выполнения определяется во время выполнения, компилятор не может знать, какие методы будут вызваны, и поэтому не может определить, является ли то, что будет выполняться, потокобезопасным.
Компилятор должен знать контекст
Компилятор не может знать, будет ли то, что вы разрабатываете, выполняться в поточно-безопасной среде или нет. Например, если вы разрабатываете bean-компонент, который будет внедрен везде вашей любимой платформой CDI, компилятор не может этого знать.
Другими словами, компилятор знает меньше, чем вы, и поэтому не может определить, должно ли то, что вы программируете, быть поточно-ориентированным или нет. Допустим, вы программируете контроллер для своего приложения J2EE; Если вы не аннотируете свой контроллер гипотетической аннотацией @ThreadSafe, компилятор никогда не будет жаловаться. Проблема в том, что ваш контроллер должен быть поточно-ориентированным! Если вы не правильно аннотируете с помощью @ThreadSafe то, что должно быть поточно-ориентированным, у вас будут проблемы …
Механизм разных замков
Если бы единственным способом синхронизации ваших потоков было ключевое слово synchronized, компилятору было бы легче определить, может ли фрагмент кода выполняться одновременно или нет. К сожалению, это не так! У вас есть несколько способов убедиться, что ваш код будет выполняться только в правильном контексте ( ReentrantLock , ReadWriteLock , ручные блокировки с использованием файла, сокета, объекта, счетчика и т. Д.). Для меня эта единственная причина делает невозможной реализацию «проверки компиляции потока». Если компилятор не может определить механизм синхронизации, он ничего не может знать о безопасности потоков!
Вывод
Потокобезопасная проверка компиляции определенно была бы убийственной функцией Но для меня это невозможно реализовать, даже частично, и, вероятно, поэтому я никогда не видел эту функцию ни на каких языках.
Если у вас есть идеи по поводу решения или если вы знаете какой-либо язык, который делает это, даже частично, дайте мне знать!
Справка: Java SE 11: продвижение Java Forward — часть 1: введение , Java SE 11: продвижение Java Forward — часть 2: средство доступа к свойствам , Java SE 11: продвижение Java Forward — часть 3: проверка компиляции потокобезопасности от нашего партнера по JCG Тибо Делора в блоге InvalidCodeException .