2016-02-24 5 views
1

Я хочу добавить метод к существующему классу, в котором я не контролирую, например. имеют метод toList() в классе Stream Java8. Вопрос в том, можно ли это сделать с помощью ASM. Полагаю, что так.Можно добавить метод к существующему классу Java с использованием ASM?

Более конкретный вопрос заключается в том, могу ли я создать нечто вроде банку, содержащего метод расширения (например, для класса Stream). Затем я могу добавить jar в свой проект, и метод toList() станет видимым в классе Java8 Stream. Из того, что я понимаю, метод расширения можно было только соткать во время выполнения или когда у меня есть среда выполнения, которая может это сделать (например, Groovy, Kotlin, Scala). Я знаю, что есть проект Lombok, но он имеет только плагин для eclipse, который поддерживает соответствующую функцию. Плагин для IntelliJ не поддерживает эту специфическую функцию.

+0

, чтобы добавить метод ... очевидным способом было бы расширить класс и добавить этот метод в дочерний класс – Stultuske

+0

Да, это правильно. Я хочу, однако, что-то вроде метода расширения (класс подкласса String не поможет), как в Groovy, Kotlin, Scala, Smalltalk, C# и других языках без необходимости возвращаться к любому из этих языков. – OlliP

+0

Вы не можете подклассифицировать строку, потому что это неизменный класс. Однако вы можете создать составной объект – Stultuske

ответ

0

Я пытаюсь ответить на вопрос в следующем порядке:

Q1: Я хочу, чтобы добавить метод к существующему классу я не имею контроль Да. Вы можете добавить новый метод/удалить существующий метод в существующий класс, независимо от исходного класса. Простой пример кода с ASM является добавление

ClassReader cr = new ClassReader(is);//'is' is inputstream to some bytecode. 
ClassWriter cw = new SomeClassWriter(ClassWriter.COMPUTE_FRAMES) 
cr.accept(cw, 0); 

class SomeClassWriter extends ClassVisitor{ 
    .... 
    @Override 
    public MethodVisitor visitEnd(){ 
     MethodVisitor mv = cw.visitMethod(...); 
     toListMethodNode.accept(mv). 
     super.visitEnd(). 
    } 

}

Q2: могу ли я создать что-то вроде кувшина, который содержит метод расширения (например, для класса Stream)

Чтобы включить новый сгенерированный байт-код, вам нужно загрузить байт-код через загрузчик aclass. Это не связано с тем, является ли пакет его банком или нет, а новый сгенерированный байт-код бесполезен, если он не загружен загрузчиком классов. Дело в том, что обычный загрузчик классов не позволяет дважды загружать байт-код с тем же символьным именем. Поэтому новый класс байт-кода (с методом toList()) имеет одно и то же имя класса, его необходимо загрузить в другой классLoader. Исключение составляет Unsafe.defineAnonymousClass(), который я не думаю, что вы будете использовать.

Смежные вопросы