Отражение Java: Как я переопределяю или генерирую методы во времени выполнения?

Это более важный комментарий, и поэтому неявно развернутые необязательные опции могут быть обманчивы, когда дело доходит до отладки nil значений.

Подумайте о следующем коде: он компилируется без ошибок / предупреждений:

c1.address.city = c3.address.city

И все же во время выполнения выдает следующую ошибку: Неустранимая ошибка: неожиданно обнаружен ноль при развертывании необязательного значения

Можете ли вы сказать мне, какой объект nil?

Вы не можете!

Полный код будет:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c3 = BadContact()

        c1.address.city = c3.address.city // compiler hides the truth from you and then you sudden get a crash
    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct BadContact {
    var address : Address!
}

struct Address {
    var city : String
}

Короче говоря, используя var address : Address!, вы скрываете возможность того, что переменная может быть nil от других читателей. И когда он падает, вы говорите: «Что, черт возьми ?! Мой address не является дополнительным, так почему я терплю крах?!.

Следовательно, лучше написать так:

c1.address.city = c2.address!.city  // ERROR:  Fatal error: Unexpectedly found nil while unwrapping an Optional value 

Можете ли вы сказать мне, что это был за nil?

На этот раз код стал более понятным для вас. Вы можете рационализировать и подумать, что вероятно, это был параметр address, который был принудительно развернут.

Полный код был бы:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c2 = GoodContact()

        c1.address.city = c2.address!.city
        c1.address.city = c2.address?.city // not compile-able. No deceiving by the compiler
        c1.address.city = c2.address.city // not compile-able. No deceiving by the compiler
        if let city = c2.address?.city {  // safest approach. But that's not what I'm talking about here. 
            c1.address.city = city
        }

    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct GoodContact {
    var address : Address?
}

struct Address {
    var city : String
}
25
задан ivan_ivanovich_ivanoff 28 June 2009 в 11:56
поделиться

5 ответов

Вы можете использовать что-то вроде cglib для генерации кода на лету

10
ответ дан 28 November 2019 в 21:30
поделиться

In java6 has been added the possibility to transform any already loaded class. Take a look at the changes in the java.lang.instrument package

9
ответ дан 28 November 2019 в 21:30
поделиться

Для интерфейсов существует java.lang.reflect.Proxy .

Для классов вам понадобится сторонняя библиотека или напишите небольшой фрагмент кода. . Обычно динамическое создание классов таким образом заключается в создании имитаций для тестирования.

Существует также инструментальный API, который позволяет изменять классы. Вы также можете изменять классы с помощью специального загрузчика классов или просто файлов классов на диске.

8
ответ дан 28 November 2019 в 21:30
поделиться

Я написал статью для java.net о том, как прозрачно добавлять операторы протоколирования к классу, когда он загружается загрузчиком классов с помощью агента java.

Это использует библиотеку Javassist для управления байтовым кодом, включая использование компилятора Javassist для генерации дополнительного байт-кода, который затем вставляется в соответствующее место, а затем полученный класс предоставляется загрузчику классов.

Уточненная версия доступна с slf4j проект.

8
ответ дан 28 November 2019 в 21:30
поделиться

Если я правильно понял, основная проблема, которая вас беспокоит, заключается в том, как передать делегат статического метода (как в C #) через метод интерфейса экземпляра.

Вы можете проверить эту статью : Программист на Java изучает делегатов C # , где показано, как получить ссылку на ваш статический метод и вызвать его. Затем вы можете создать класс-оболочку, который принимает имя статического метода в своем конструкторе и реализует ваш базовый класс для вызова статического метода из метода экземпляра.

0
ответ дан 28 November 2019 в 21:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: