Готовитесь к интервью? Хотите просто вернуться к функциям Java SE 9? Пытаетесь вспомнить или пересмотреть программные конструкции Java SE? Позвольте мне вернуться к тому, что было впервые представлено в Java SE 9? Присоединяйтесь ко мне в этом учебном курсе по Java, поскольку мы все с нетерпением ждем официального выпуска Java SE 14!
Как я и обещал, я вернулся с примерами кода из моей предыдущей статьи Java SE 9 … Что нового? Вы можете обратиться к предыдущей статье, чтобы понять недавно представленные функции на высоком уровне. В этой статье приведены примеры кода для каждой функции.
Вы можете скачать примеры кода для следующих новых функций здесь . (Импортируйте как проект eclipse, установите компилятор / среду как Java 9. Запустите основной класс ‘Java9Application’, чтобы увидеть выходные данные / результаты примеров кода.)
Я планирую начать с повторного посещения функции Java 8, Методы интерфейса по умолчанию.
Вам также могут понравиться: Возможности
SKP Java / Java EE: Java SE 9
Методы интерфейса по умолчанию
Всякий раз, когда существует существующий или унаследованный код, имеющий интерфейсы, требующие добавления новых методов, он нарушает существующие классы, которые наследуют или реализуют из этого интерфейса, если в классах не предусмотрена реализация для каждого из этих добавленных методов. Это не очень понятный код. Хотя для SOLID и других парадигм OO рекомендуется использовать интерфейс без какой-либо реализации, мы должны решить и решить проблему, как указано выше. Это где методы интерфейса по умолчанию входят.
Джава
1
import java.util.List;
2
3
public interface LegacyPublicInterface {
4
5
6
/**
7
Additional Default Method that Can be Invoked on Each Type of Invoice that Implements the LegacyPublicInterface. It can also be over-ridden by the Extending Invoice Types. This is an Example Usage and Benefit of the Java/JDK 8. Default Interface feature.
8
9
@param items
10
*/
11
default void checkStatusOnEachItem (List<String>... items) {
12
13
for(String item : items) {
14
if(item.startsWith("OOS_")) {
15
items.remove(item);
16
}
17
}
18
return;
19
}
20
}
23:
В приведенном выше примере LegacyPublicInterface
уже существующее приложение расширено несколькими типами счетов (например, в системе инвентаризации). Усилия по реинжинирингу требуют, чтобы в каждом из счетов был метод аннулирования или удаления Предмета, помеченного «OOS». Учитывая такую проблему, до Java 8 нам пришлось бы ввести новое объявление метода в интерфейс, а затем потребовать, чтобы каждый из реализующих классов реализовал свою собственную логику для обработки этого. С интерфейсами по умолчанию задача становится очень простой (код теперь более понятен и расширяем и требует меньше усилий для изменения). С введением методов по умолчанию , вот возможности:
- Используйте метод (ы) по умолчанию, не нарушая существующую функциональность (наилучшее использование)
- Реализующий класс может переопределить эти методы по умолчанию
- Абстрактные интерфейсы могут быть предоставлены через интерфейсы для переопределения реализации
Итак, давайте подробнее рассмотрим каждое из этих изменений в Java 9.
Изменения языка Java в JDK 9
Методы частного интерфейса
Интерфейсы в Java 9 могут иметь частные методы. Это было сделано для обеспечения совместного использования кода между неабстрактными методами в Интерфейсе. Все правила, относящиеся к обычным модификаторам Private, применяются к этим методам. Следует отметить, что метод не может быть как частным, так и абстрактным. Это определенно должно иметь тело метода.
Джава
xxxxxxxxxx
1
package com.techilashots.java9.features;
2
3
/**
4
* @author sumith.puri
5
*
6
* prior to java 8, the default scope/visibilty of every method in an interface was same
7
* the attributes were all by default, [public static final] and the methods were [public]
8
* with java 8, [default] interface methods have been introduced but so has been a new scope/visibility
9
* with java 9, interface can have private visibility methods that can be used internally
10
*/
11
public interface Java9PrivateMethodInterface {
12
public void preJava9BusinessMethodOne();
14
public void preJava9BusinessMethodTwo();
16
public default void newJava9BusinessMethodThree() {
18
System.out.println("Interface Methods can call Private Interface Methods!");
19
System.out.println("");
20
java9BusinessMethodThreeHelper();
21
}
22
private void java9BusinessMethodThreeHelper() {
24
System.out.println("Default Methods... Now Private Methods!");
25
System.out.println("Once Upon a Time, I was a Java Developer!");
26
}
27
}
Вы можете наблюдать использование вышеупомянутого частного метода (внутренне новым методом по умолчанию) через следующий код.
Джава
xxxxxxxxxx
1
23
1
//new features of java 9
2
//private interface methods
3
private void privateInterfaceMethod() {
4
5
System.out.println("01. Private Interface Methods");
6
System.out.println("-----------------------------");
7
System.out.println("[Private Interface Method Invoked by Default Interface Method]");
8
Java9PrivateMethodInterface java9PrivateMethodInterface = new Java9PrivateMethodInterface() {
9
10
public void preJava9BusinessMethodTwo() {
11
// TODO Auto-generated method stub
12
}
13
14
public void preJava9BusinessMethodOne() {
15
// TODO Auto-generated method stub
16
}
17
};
18
19
java9PrivateMethodInterface.newJava9BusinessMethodThree();
20
System.out.println("");
21
System.out.println("================================");
22
System.out.println("");
23
}
Джава
xxxxxxxxxx
1
//new features of java 9
2
//private interface methods
3
private void privateInterfaceMethod() {
4
System.out.println("01. Private Interface Methods");
6
System.out.println("-----------------------------");
7
System.out.println("[Private Interface Method Invoked by Default Interface Method]");
8
Java9PrivateMethodInterface java9PrivateMethodInterface = new Java9PrivateMethodInterface() {
9
10
public void preJava9BusinessMethodTwo() {
11
// TODO Auto-generated method stub
12
}
13
14
public void preJava9BusinessMethodOne() {
15
// TODO Auto-generated method stub
16
}
17
};
18
java9PrivateMethodInterface.newJava9BusinessMethodThree();
20
System.out.println("");
21
System.out.println("================================");
22
System.out.println("");
23
}
Подчеркивать как имя переменной больше не является законным
Использование только символа подчеркивания («_») в качестве имени переменной больше недопустимо. Это потому, что он помечен как зарезервированное ключевое слово в Java 1.8 (но вызвало сбой компиляции только в Java 1.9). Это может вызвать некоторые проблемы при компиляции устаревшего исходного кода, особенно с необходимостью обозначить некоторый конкретный ресурс или объект, используя подчеркивание. Возможно, его придется переписать, и у него может быть много связанных последствий.
Джава
xxxxxxxxxx
1
/**
2
* @author sumith.puri
3
*
4
*/
5
public class Java9VariableNaming {
6
// pre-java 9, this was a valid variable name
7
// from java 8, _ was marked as a reserved keyword (compiler warning)
8
// from java 9, the following line of code will cause compilation failure
9
// private String _;
10
private String _socket = null;
11
/**
12
* @param args
13
*/
14
public void notForDemoMethod() {
15
_socket = new String("Network Socket");
16
System.out.println("_ is no Longer a Valid Variable Name!, [Variable Value: " + _socket + "]");
17
}
18
}
Разрешить эффективно использовать конечные переменные в качестве ресурсов в попытках использовать ресурсы
До Java 8 все переменные, которые должны были использоваться в инструкциях Try with Resources, должны были быть объявлены в инструкции try. Только тогда он может быть использован в блоке try. Это ограничение для разработчика. Следовательно, в Java 9 это ограничение было снято, и любая конечная переменная или эффективно конечная (локальная) переменная может использоваться внутри блока try. Все остальные правила, применимые к Try with Resources, продолжаются. Окончательно означает, что переменная не была изменена после ее инициализации.
Джава
xxxxxxxxxx
1
package com.techilashots.java9.features;
2
import java.io.BufferedReader;
4
import java.io.File;
5
import java.io.FileReader;
6
import java.io.IOException;
7
8
/**
9
* @author sumith.puri
10
*/
11
public class EffectivelyFinalTryResources {
12
13
private static File file = new File("try_resources.j9");
14
//with java 9, you need to use either explicitly final or effectively final variables in try/resources
16
public void methodWithAnomaly() throws IOException {
17
file.createNewFile();
19
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
20
21
//prior to java 9, the usage would look like this
22
//try (final BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
23
//this code will not compile before java 9
24
try (bufferedReader) {
25
System.out.println("Can Use Final or Effectively Final in Try with Resources!");
26
} finally {
27
System.out.println("Java 9 Gives More Flexibility to Developers.");
28
}
29
}
30
}
@SafeVarargs разрешен в методах частного экземпляра
Использование в методе параметров аргументов без переопределения может вызвать несколько предупреждений при попытке компилировать код, например:
Джава
xxxxxxxxxx
1
Note: LegacyPublicInterface.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
@SafeVarargs
был введен для подавления таких предупреждений о непроверенных или небезопасных операциях. Используя это, разработчик сообщает компилятору, что он удостоверился, что не будет никакого загрязнения кучи (например, небезопасных
forEach
операций).
До Java 9
@SafeVarargs
допускается использование не переопределяемых методов, таких как статические методы, методы конечных экземпляров и конструкторы. Обратите внимание, что аннотация выдаст ошибку, если она используется в методах фиксированной арности. В Java 9 @SafeVarargs
могут использоваться методы частного экземпляра.Джава
xxxxxxxxxx
1
package com.techilashots.java9.features;
2
/**
4
* @author sumith.puri
5
*/
6
public class SafeVarargsOnPrivateMethod {
7
public void demoSafeVarargsInJava9() {
9
safeVarargsInJava9(24.00f, 03, 19, 82);
10
}
11
13
private void safeVarargsInJava9 (Float a, Integer...b) {
14
System.out.println("Invoked Private Instance Method with " +a+ "," +b[0]+ "," +b[1]+ "," +b[2]);
16
System.out.println("With Java 9, @SafeVarargs is Allowed on Private Instance Methods!");
17
}
18
}
Разрешить алмаз с анонимными классами, если тип аргумента Inferred Type является Denotable
До Java 8 использование операторов Generics и Diamond с анонимными классами было главным образом потому, что компилятор не мог определить, может ли он представлять тип в аргументе, передаваемом оператору Diamond.
JSR 334 может сказать следующее об использовании Diamond с анонимными классами:
«Использование diamond с анонимными внутренними классами не поддерживается, поскольку для этого обычно требуется расширение атрибута подписи файла класса для представления недетонируемых типов, фактическое
изменение JVM ».
Дополнительная информация находится в теме Diamond Operator and Anonymous Classes в списке рассылки Project Coin
:
«Внутренне, компилятор Java работает с более богатым набором типов, чем те, которые могут быть записаны явно в программе Java. Внутренние типы компилятора, которые не могут быть записаны в программе Java, называются
недетонируемыми типами. Это может произойти в результате логического вывода, используемого diamond. Поэтому использование diamond с анонимными внутренними классами не поддерживается, поскольку в целом для этого требуются расширения атрибута подписи файла класса для представления недетонируемых типов, что является фактическим изменением JVM. Вполне возможно, что будущие версии платформ позволят использовать diamond при создании анонимного внутреннего класса, если выводимый тип может быть денотируемым ».
В Java 9 компилятор Java изменил свой алгоритм вывода таким образом, что оператор diamond (generics) теперь может работать одновременно с анонимными классами, пока тип аргумента выведенного типа не подлежит изменению. Важно отметить, что вещи, которые подпадают под денотируемость, это примитивные типы, необработанные типы и неуниверсальные типы. Не денотируемые означают те, которые не могут быть написаны в Java-программе, такие как использование extends и super, наряду с подстановочными типами в обобщениях. Обычно они определяются компилятором. Таким образом, до тех пор, пока компилятор определит, что тип аргумента выведенного типа является денотируемым, вы можете использовать оператор diamond в сочетании с анонимными внутренними классами.
Джава
xxxxxxxxxx
1
package com.techilashots.java9.features;
2
/** * @author sumith.puri */
4
public class DiamondOperatorOnAnonymous {
5
6
public void diamondForInferredDenotable() {
7
8
//prior to java 9, anonymous inner classes were not allowed to use diamond operator
9
10
Java5ToJava8Coder<? extends Number> java9SyntaxGuru = new Java5ToJava8Coder<>() {
11
12
public void java9SyntaxMagic() {
13
System.out.println("Introduced in Java 5, Generics was Intriguing and Complex!");
14
System.out.println("With Java 9, Diamond Operator On Anonymous Classes is Allowed...");
15
System.out.println("As Long as Java 9 Infers the Type (Inferred) to be Denotable.");
16
}
17
};
18
java9SyntaxGuru.java9SyntaxMagic();
19
}
20
}
21
abstract class Java5ToJava8Coder<T extends Number> {
23
public abstract void java9SyntaxMagic();
24
}
Основные изменения библиотеки в Java 9
JEP 102: обрабатывать обновления API
С Java 9 можно получить PID процесса через собственный вызов. Это достижимо через
ProcessHandle
. Кроме того, мы можем получить информацию о текущем запущенном Java-процессе и информацию (внутренний класс
ProcessHandle
) о классе / объекте, который содержит подробную информацию о процессе. Мы также можем подключить или вернуть снимок всех запущенных в данный момент процессов в системе.Джава
xxxxxxxxxx
1
package com.techilashots.java9.features;
2
import java.lang.ProcessHandle.Info;
3
/**
5
* @author sumith.puri
6
*/
7
public class ProcessAPIChanges {
8
9
public void detailedAPIInfo(ProcessHandle processHandle) {
10
11
Info processInfo = processHandle.info();
12
System.out.println("[Java 9 Developers... Check this Out!]");
13
System.out.println("[Detailed Process Info is Provided Below]");
14
System.out.println("[Executable Name] " + processInfo.command().get());
15
System.out.println("[User Name] " + processInfo.user().get());
16
System.out.println("[Start Time] " + processInfo.startInstant().get().toString());
17
System.out.println("+++++");
18
}
19
20
public static void main(String[] args) {
21
22
System.out.println("06. Process API Changes (Core Library) ");
23
System.out.println("--------------------------------------");
24
System.out.println("Check Out the Detailed Process Information in Java 9");
25
26
ProcessAPIChanges processAPIChanges = new ProcessAPIChanges();
27
ProcessHandle processHandle = ProcessHandle.current();
28
29
System.out.println("With Java 9, Process Id is Available");
30
System.out.println("[Current Process Id] " + processHandle.pid());
31
System.out.println("-------------------------------------");
32
33
processAPIChanges.detailedAPIInfo(processHandle);
34
35
System.out.println("-------------------------------------");
36
System.out.println("With Java, You can View all Processes..");
37
System.out.println("That are Visible to the Current Process!");
38
39
ProcessHandle.allProcesses()
40
.filter(ph -> ph.info().command().isPresent())
41
.limit(4)
42
.forEach((process) -> processAPIChanges.detailedAPIInfo(process));
43
44
System.out.println("");
45
System.out.println("================================");
46
System.out.println("");
47
}
48
}
JEP 277: улучшенная амортизация
Принимая во внимание поддерживаемый и более информативный код, определяемый разработчиком устаревший контент теперь позволяет помечать устаревший с помощью дополнительных элементов информации, таких как forRemoval и с тех пор . ForRemoval позволяет пометить, что этот элемент может быть удален в будущих версиях Java, и, поскольку предоставляет информацию о том, когда он был впервые представлен.
Джава
xxxxxxxxxx
1
package com.techilashots.java9.features;
2
3
/**
4
* @author sumith.puri
5
*/
6
public class EnhancedDeprecation {
7
8
forRemoval=true) (
9
public void methodMarkedForRemoval() {
10
System.out.println("Java 9 Allows Enhanced Method Deprecation");
11
System.out.println("Invoked Method is Deprecated and Marked [For Removal]");
12
this.methodDeprecatedSince();
13
}
14
15
since="12.2") (
16
public void methodDeprecatedSince() {
17
System.out.println("Invoked Method is Deprecated and Marked [Since]");
18
}
19
}
JEP 269: методы фабрики удобства для коллекций
Это дополнение позволяет разработчику создавать неизменяемые коллекции из существующих интерфейсов, будь то Set, Map или List. Статический метод фабрики of()
добавлен в Set, Map и List. Важно, чтобы вы понимали следующее (даже если это согласуется с предыдущими версиями Java):
- Они структурно неизменны.
- Они запрещают нулевые элементы или нулевые ключи.
- Они сериализуемы, если все элементы сериализуемы.
- Они отклоняют дубликаты элементов / ключей во время создания.
- Порядок итерации заданных элементов не определен и может быть изменен.
- Они основаны на стоимости. Фабрики могут создавать новые экземпляры или повторно использовать существующие. Поэтому чувствительные к идентичности операции в этих случаях (ссылочное равенство (==), хэш-код идентичности и синхронизация) ненадежны и их следует избегать. Они сериализуются, как указано на странице сериализованной формы.
Джава
xxxxxxxxxx
1
package com.techilashots.java9.features;
2
import java.util.Set;
4
/**
5
* @author sumith.puri
6
*/
7
public class ConvenienceCollections {
8
public void checkItOut() {
9
System.out.println("Java 9 Introduced a Static [of()] Factory Method");
10
System.out.println("This allows Creation of Immutable Collections");
11
Set<String> immutableCountrySet = Set.of("America", "Russia", "China", "India");
12
try {
13
immutableCountrySet.add("England");
14
} catch (Exception e) {
15
System.out.println("Caught Exception, Adding Entry to Immutable Collection!");
16
}
17
}
18
}
Вы можете скачать примеры кода для следующих новых функций здесь . (Импортируйте как проект Eclipse, установите компилятор / среду как Java 9. Убедитесь, что в вашей системе установлена Java 9 / JDK 9. Запустите основной класс, Java9Application
чтобы увидеть выходные данные / результаты примеров кода.)
Проверьте Вывод консоли Eclipse, представленный ниже при запуске Java9Application
(см. Прилагаемые примеры кода). Пожалуйста, обратитесь к отдельным классам, предоставленным для каждой функции, чтобы лучше понять функции. Идите вперед, добавляйте, изменяйте, удаляйте, чтобы экспериментировать со всеми новыми функциями Java 9.
Удачного кодирования с Java 9!
Дальнейшее чтение
Думаете о переходе на JDK 9 в следующем году? Подумай еще раз