Цена за 48 часов в ленте | 9850,00 |
Цена за 1 час закрепления | N/A |
Взаимопиар | Нет |
Дополнительные условия рекламы | Отсутствуют |
invokedynamic
, и использование java.lang.invoke.MethodHandle
и java.lang.invoke.LambdaMetafactory
. Runnable
, Callable
, Comparator
, и интерфейсы из пакета java.util.function
(Function
, Predicate
, Consumer
, Supplier
).invokedynamic
— это инструкция байт-кода, введенная в Java 7, которая позволяет динамически связывать вызовы методов во время выполнения. В случае лямбда-выражений, invokedynamic
используется для создания инстанции функционального интерфейса.MethodHandle
— это легковесный, типобезопасный способ описания подлежащих вызову методов, конструкторов и полей. LambdaMetafactory
— это утилита, используемая JVM для создания реализации функционального интерфейса на основе лямбда-выражения. При выполнении инструкции invokedynamic
JVM вызывает LambdaMetafactory
для создания экземпляра функционального интерфейса.Listnames = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
invokedynamic
. Инструкция invokedynamic
указывает на метод-обработчик (MethodHandle) для метода System.out.println(name)
.invokedynamic
JVM вызывает LambdaMetafactory
для создания инстанции функционального интерфейса Consumer
. LambdaMetafactory
создает реализацию интерфейса Consumer
с методом accept
, который вызывает System.out.println(name)
.// Лямбда-выражение
Consumerconsumer = name -> System.out.println(name);
// Компилируется в байт-код, который использует invokedynamic
Consumerconsumer = (Consumer ) LambdaMetafactory.metafactory(
caller,
"accept",
MethodType.methodType(Consumer.class),
MethodType.methodType(void.class, Object.class),
MethodHandles.lookup().findVirtual(System.out.getClass(), "println", MethodType.methodType(void.class, String.class)),
MethodType.methodType(void.class, String.class)
).getTarget().invoke();
invokedynamic
и LambdaMetafactory
позволяет JVM генерировать высокоэффективный байт-код для лямбда-выражений.forEach
позволяет компактно и удобно итерировать по элементам коллекций. Listnames = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
Listnames = Arrays.asList("Alice", "Bob", "Charlie", "David");
ListfilteredNames = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
filteredNames.forEach(System.out::println); // Вывод: Alice
sort
. Listnames = Arrays.asList("Alice", "Bob", "Charlie");
names.sort((name1, name2) -> name1.compareTo(name2));
names.forEach(System.out::println);
Predicate
, Function
, Consumer
и Supplier
. // Predicate
PredicatestartsWithA = s -> s.startsWith("A");
boolean result = startsWithA.test("Alice"); // true
// Function
FunctionlengthFunction = s -> s.length();
int length = lengthFunction.apply("Hello"); // 5
// Consumer
ConsumerprintConsumer = s -> System.out.println(s);
printConsumer.accept("Hello, World!"); // Вывод: Hello, World!
// Supplier
SupplierstringSupplier = () -> "Hello, Supplier!";
String suppliedString = stringSupplier.get();
System.out.println(suppliedString); // Вывод: Hello, Supplier!
Listnumbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream()
.mapToInt(Integer::intValue)
.sum();
System.out.println("Sum: " + sum); // Вывод: Sum: 15
import java.util.*;
import java.util.stream.Collectors;
class Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Employee{name='" + name + "', age=" + age + '}';
}
}
public class LambdaExample {
public static void main(String[] args) {
Listemployees = Arrays.asList(
new Employee("Alice", 30),
new Employee("Bob", 25),
new Employee("Charlie", 35),
new Employee("David", 28)
);
// Фильтрация и сортировка сотрудников по имени
ListfilteredAndSorted = employees.stream()
.filter(e -> e.getAge() > 27)
.sorted(Comparator.comparing(Employee::getName))
.collect(Collectors.toList());
filteredAndSorted.forEach(System.out::println);
}
}
Runnable
, Callable
, Comparator
, и интерфейсы из пакета java.util.function
(Function
, Predicate
, Consumer
, Supplier
).invokedynamic
для создания инстанций функциональных интерфейсов. Этот механизм позволяет JVM динамически генерировать реализацию функционального интерфейса, используя метод-обработчик (MethodHandle).invokedynamic
инструкцию. Это позволяет JVM динамически создать реализацию функционального интерфейса при первом вызове лямбда-выражения.Listnames = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
invokedynamic
. Инструкция invokedynamic
указывает на метафабрику (LambdaMetafactory
), которая отвечает за создание инстанции функционального интерфейса. Метафабрика создает реализацию функционального интерфейса, используя метод-обработчик (MethodHandle) для метода, определенного в лямбда-выражении.name -> System.out.println(name)
соответствует методу функционального интерфейса Consumer
. В байт-коде создается invokedynamic
инструкция, которая ссылается на LambdaMetafactory
для создания инстанции Consumer
."java/lang/Object"
, "java/lang/String"
).public class StringPoolDemo {
public static void main(String[] args) {
// Проверка стандартных строк, которые могут быть в пуле строк
String str1 = "java";
String str2 = "lang";
String str3 = "Object";
// Вывод строк
System.out.println("str1: " + str1);
System.out.println("str2: " + str2);
System.out.println("str3: " + str3);
// Проверка строк в пуле строк
System.out.println("Is 'java' in pool: " + (str1 == "java"));
System.out.println("Is 'lang' in pool: " + (str2 == "lang"));
System.out.println("Is 'Object' in pool: " + (str3 == "Object"));
}
}
java.lang.Object
, java.lang.String
, java.lang.System
, и другие. Строковые литералы, используемые в этих классах, добавляются в пул строк.String.intern()
.String.intern()
можно использовать для добавления строки в пул строк вручную. Если строка уже существует в пуле, возвращается ссылка на существующую строку; если нет, строка добавляется в пул и возвращается ссылка на нее.public class StringPoolExample {
public static void main(String[] args) {
// Строковые литералы автоматически добавляются в пул строк
String str1 = "Hello";
String str2 = "Hello";
// Проверка, что str1 и str2 ссылаются на один и тот же объект
System.out.println(str1 == str2); // true
// Создание новой строки (не литерала)
String str3 = new String("Hello");
// Проверка, что str3 и str1 ссылаются на разные объекты
System.out.println(str1 == str3); // false
// Использование метода intern()
String str4 = str3.intern();
// Проверка, что str4 и str1 теперь ссылаются на один и тот же объект
System.out.println(str1 == str4); // true
}
}
public class Example {
String str = "Hello"; // Литерал добавляется в пул строк при загрузке класса
}
intern()
позволяет явно добавить строку в пул строк или получить существующую строку из пула. Это полезно, когда строки создаются динамически и нужно обеспечить, чтобы они находились в пуле строк. String dynamicStr = new String("Dynamic");
String pooledStr = dynamicStr.intern(); // Добавляет строку в пул, если её там еще нет
intern()
проверяет, находится ли строка в пуле строк. Если да, он возвращает ссылку на существующую строку. Если нет, строка добавляется в пул строк, и возвращается ссылка на неё.String s1 = new String("Java");
String s2 = s1.intern(); // s2 теперь указывает на строку в пуле строк
public class Example {
public static void main(String[] args) {
String password = "secretPassword123"; // Строка хранится в пуле строк
System.out.println("Password is set.");
}
}
char[]
), так как их содержимое можно обнулить после использования. char[] password = new char[] {'s', 'e', 'c', 'r', 'e', 't'};
// Очистка массива после использования
java.util.Arrays.fill(password, '\0');