Классы для лямбда-выражений не javac
генерируются, а создаются JRE во время выполнения. Их имена совершенно не указаны, и вы не можете полагаться на какую-либо схему именования.
Но очевидно, что текущая JRE Oracle имеет узнаваемый шаблон. Он добавляет $$Lambda$n
к имени определяющего класса, тогда как n
— это возрастающее число, которое отражает порядок создания во время выполнения, а не какое-либо свойство скомпилированного кода.
Вы можете проверить это с помощью следующей программы:
public class Test {
public static void main(String... args) {
if(args.length==0) {
final boolean meFirst = Math.random()<0.5;
if(meFirst) {
Runnable r=Test::main;
System.out.println("first run:\t"+r.getClass());
}
main("second run");
if(!meFirst) {
Runnable r=Test::main;
System.out.println("first run:\t"+r.getClass());
}
}
else {
Runnable r=Test::main;
System.out.println(args[0]+":\t"+r.getClass());
if(args[0].equals("second run")) main("last run");
}
}
}
В зависимости от состояния случайного флага meFirst
он будет печатать либо
first run: class Test$$Lambda$1
second run: class Test$$Lambda$2
last run: class Test$$Lambda$2
or
second run: class Test$$Lambda$1
last run: class Test$$Lambda$1
first run: class Test$$Lambda$2
Он показывает, что первый сгенерированный класс всегда получает номер 1
, независимо от того, является ли он одной из первых двух ссылок на метод, созданных в первом вызове main
, или третьей ссылкой на метод, созданной в первой рекурсии. Кроме того, третье выполнение всегда сталкивается с тем же классом, что и второе, поскольку это одно и то же выражение ссылки на метод (примечание: разные выражения, поскольку цель всех выражений одна и та же), и класс переопределяется. использовал.
В зависимости от версии вы можете увидеть что-то вроде /number
, добавленное к именам, что намекает на то, что имена действительно не имеют значения, поскольку каждый из этих классов имеет другой уникальный идентификатор (это так называемые «анонимные классы», которые вы можете найти через ClassLoader
и имя).
Имена полей, такие как args$n
в этих классах, представляют n-е захваченное значение. Поскольку LambdaMetafactory
ничего не знает относительно реальных имен захваченных переменных, у него нет другого выбора, кроме как генерировать такие имена.
Но, как уже было сказано, это артефакт реализации. Можно поддерживать такой шаблон именования, пока новый класс генерируется для каждого сайта создания в каждом определяющем классе. Но поскольку спецификация допускает произвольное совместное использование/повторное использование классов и экземпляров, представляющих эквивалентные лямбда-выражения (делающие то же самое) и ссылки на методы (нацеленные на один и тот же метод), такой шаблон именования возможен не для каждой стратегии реализации.
person
Holger
schedule
02.06.2016