InvocationHandler in Kotlin



我在读Head First: Design Patterns (2nd edition)我遵循代码示例,但我没有使用Java,而是使用Kotlin。目前,我正在处理代理保护模式的一章,并且很难在Kotlin中运行它。请参阅下面的代码和异常。

interface Person {
fun getName(): String
fun setName(name: String)
}
class PersonImpl : Person {
private var _name: String = ""
override fun getName(): String = _name
override fun setName(name: String) {
_name = name
}
}
class OwnerInvocationHandler(private val person: Person) : InvocationHandler {
override fun invoke(proxy: Any?, method: Method, args: Array<Any>?): Any? {
try {
val methodName = method.name
if (methodName.isNullOrEmpty())
return null
if (methodName.startsWith("get")) {
//              return method.invoke(proxy, *(args ?: arrayOfNulls<Any>(0))) // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, *(args ?: emptyArray()))         // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, *args.orEmpty())                 // << Encountered "EXCEPTION B" below
return method.invoke(proxy, args)                            // << From the code sample, encountered "EXCEPTION A" below
} else if (methodName.startsWith("set")) {
return method.invoke(person, args)
}
} catch (e: InvocationTargetException) {
e.printStackTrace()
}
return null
}
}
// main.kt
val listOfPeople = arrayListOf<Person>()
fun main(array: Array<String>) {
initializeDatabase()
val joe = getPersonFromDatabase("Joe Javabean") ?: return
val ownerProxy = getOwnerProxy(joe)
println("Name is ${ownerProxy.getName()}")
}
fun initializeDatabase() {
val p1 = PersonImpl()
p1.setName("Joe Javabean")
listOfPeople.add(p1)
}
fun getOwnerProxy(person: Person): Person {
return Proxy.newProxyInstance(
person.javaClass.classLoader,
person.javaClass.interfaces,
OwnerInvocationHandler(person)
) as Person
}
fun getPersonFromDatabase(name: String): Person? {
return listOfPeople.firstOrNull { p -> name.contentEquals(p.getName()) }
}

异常

异常

/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10a5ef4e0). One of the two will be used. Which one is undefined.
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
at com.sun.proxy.$Proxy0.getName(Unknown Source)
at com.helloworld.app.MainKt.main(main.kt:12)

异常B

objc[64094]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/bin/java (0x109e744c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x109eee4e0). One of the two will be used. Which one is undefined.
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
java.lang.reflect.InvocationTargetExceptionjava.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
at com.sun.proxy.$Proxy0.getName(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
at com.sun.proxy.$Proxy0.getName(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
at com.sun.proxy.$Proxy0.getName(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
at com.sun.proxy.$Proxy0.getName(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
...

我找到了下面的链接,但没有解决我的问题。

Kotlin:传递Array作为变量形参时实参类型不匹配

这只是一个用户错误(尴尬)。正如@broot指出的:

代码示例

class OwnerInvocationHandler(private val person: Person) : InvocationHandler {
override fun invoke(proxy: Any?, method: Method, args: Array<Any>?): Any? {
try {
val methodName = method.name
if (methodName.isNullOrEmpty())
return null
if (methodName.startsWith("get")) {
//              return method.invoke(proxy, *(args ?: arrayOfNulls<Any>(0))) // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, *(args ?: emptyArray()))         // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, *args.orEmpty())                 // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, args)                            // << From the code sample, encountered "EXCEPTION A" below
// `person` should be used not `proxy`
return method.invoke(person, *args.orEmpty())
} else if (methodName.startsWith("set")) {
return method.invoke(person, args)
}
} catch (e: InvocationTargetException) {
e.printStackTrace()
}
return null
}
}

最新更新