Sådan udtrækker du metodenavne i Java med dette smarte trick
Sådan henter du metode-navne i Java: Den smarte SerializedLambda-trick
Når du arbejder med CSV-læsere, ORM-værktøjer eller REST-klienter i Java, støder du ofte på det samme irritationsmoment: Du har brug for et feltnavn som en tekststreng. Men at skrive "author" eller getTitle direkte føles forkert. Det er skrøbeligt, bryder refactoring, og pludselig leder du efter mystiske strenge overalt i koden.
Hvad hvis du i stedet kunne gøre dette?
String author = csvContents.get(nameOf(Book::getAuthor));
String title = csvContents.get(nameOf(Book::title));
Bare send metode-referencen direkte – så finder Java selv navnet. Lad os se, hvordan det virker.
Udfordringen
Java giver dig ikke en indbygget måde at hente et metodenavn fra en metode-reference. Når du skriver Book::getAuthor, får du et Function<Book, String> objekt. Men der er ingen API til at spørge: "Hvad hedder den originale metode egentlig?"
Refleksion virker intuitivt:
Method[] methods = Book.class.getMethods();
String name = methods[0].getName(); // Virker – men hvilken metode?
Problemet er, at du allerede skal vide, hvilken metode du leder efter. Det fjerner hele formålet.
Hemmeligheden bag SerializedLambda
Her bliver det interessant. Når Java serialiserer en lambda eller metode-reference, gemmer den ikke bare bytecode. Den opretter et SerializedLambda objekt med metadata om den oprindelige metode – inklusive navnet.
Tricket er at gribe fat i denne serialiseringsproces, før den slutter, og kapre SerializedLambda objektet.
Her er kernen i implementeringen:
public static <T, R> String nameOf(final Getter<T, R> methodRef) {
return toSerializedLambda(methodRef).getImplMethodName();
}
private static <T, R> SerializedLambda toSerializedLambda(final Object methodRef) {
try {
try (CustomObjectOutputStream stream = new CustomObjectOutputStream()) {
stream.writeObject(methodRef);
return (SerializedLambda) stream.interceptedObject;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Vi opretter en brugerdefineret ObjectOutputStream, der opsnapper replaceObject callbacken. Når Java prøver at serialisere metode-referencen, kalder den replaceObject med SerializedLambda – og vi griber det lige der.
Hvorfor det betyder noget
Denne teknik åbner for nogle virkelig praktiske mønstre:
Typesikker konfiguration til databehandling:
// I stedet for:
dataMapper.map(book, "title", "author");
// Kan du skrive:
dataMapper.map(book, nameOf(Book::title), nameOf(Book::getAuthor));
Compile-time sikkerhed for API-kald:
// Database-forespørgsler der refaktorerer sikkert
List<Book> results = bookRepository.findBy(nameOf(Book::getAuthor), "Shakespeare");
Hvis du omdøber getAuthor() metoden, vil compileren markere alle nameOf(Book::getAuthor) kald, der skal opdateres. Ingen jagt på hardcodede strenge mere.
Ud over simple getters
Det grundlæggende mønster fungerer fint for metoder uden parametre. Men hvad med metoder, der har parametre? Du kan udvide tilgangen med ekstra serialiserbare funktionelle interfaces:
public interface BiFunction2<T1, T2, R> extends Serializable {
R apply(T1 t1, T2 t2);
}
public <T1, T2, R> String nameOf(final BiFunction2<T1, T2, R> methodRef) {
return toSerializedLambda(methodRef).getImplMethodName();
}
Det lader dig håndtere metoder som BookService::findByTitleAndAuthor eller Repository::save.
Et par forbehold
Teknikken er kraftfuld, men husk disse overvejelser:
- Performance: Serialisering har overhead. Undgå at kalde
nameOf()i hot loops – kald det én gang under initialisering og cache resultatet. - Serializable-krav: Dine funktionelle interfaces skal udvide
Serializable. - Ikke universelt: Dette virker for metode-referencer, der er tildelbare til funktionelle interfaces. Direkte refleksion er stadig nødvendig for vilkårlige metoder.
Biblioteker til redning
Hvis implementeringen føles som for meget boilerplate, er der godt nyt: arbejdet er allerede gjort. Biblioteket Safety Mirror leverer robuste implementeringer og udvider endda konceptet til at udtrække java.lang.reflect.Method objekter direkte – fuld refleksionskraft med typesikkerhed.
Konklusionen
Javas metode-referencer er kraftfulde, men de skjuler metodenavne med vilje. Nogle gange har du brug for den metadata tilbage. SerializedLambda tricket tilbyder en ren, typesikker måde at bygge bro – så du kan skrive udtryksfuld, refaktoreringsvenlig kode uden at drukne i magiske strenge.
Uanset om du bygger en databehandlingspipeline, en fleksibel API-klient, eller bare er træt af at lede efter "getAuthor" i din kodebase, kan denne teknik være lige det, du har brug for.