我对Kotlin的思考有一个有趣的错误。
因此,即时通讯使用argTypes方法获取args的所有参数类型。
private fun argTypes(vararg args: Any): Array<Class<*>> {
val argTypes = ArrayList<Class<*>>()
args.forEach { argTypes.add(it::class.java) }
return argTypes.toTypedArray()
}
我这样使用它:
fun <T> newInstance(clazz: Class<*>, argTypes: Array<Class<*>>, vararg args: Any): T {
return clazz.getDeclaredConstructor(*argTypes).newInstance(*args) as T
}
最后:
ReflectionUtil.instance.newInstance<IBossBar>(
PacketBossBar1_13_R2::class.java,
TextComponent("asd"),Color.BLUE,Style.PROGRESS,100F)
我使用的是float参数'100F'。
当我使用该方法时,类型将为java.lang.Float,但是我的'PacketBossBar1_13_R2'构造函数具有如下所示的float参数:
constructor(
message: TextComponent,
color: Color,
style: Style,
progress: Float
): this(ComponentSerializer.toString(message), color, style, progress)
当我将构造函数作为手册时,它的返回结果
public io.github.utsukushihito.utsutil.nms.v1_13_R2.PacketBossBar1_13_R2(net.md_5.bungee.api.chat.TextComponent,io.github.utsukushihito.utsutil.api.bossbar.enums.Color,io.github.utsukushihito.utsutil.api.bossbar.enums.Style,float)
当我使用自动方式时,它会像这样返回NoSucMethodException:
java.lang.NoSuchMethodException: io.github.utsukushihito.utsutil.nms.v1_13_R2.PacketBossBar1_13_R2.<init>(net.md_5.bungee.api.chat.TextComponent, io.github.utsukushihito.utsutil.api.bossbar.enums.Color, io.github.utsukushihito.utsutil.api.bossbar.enums.Style, java.lang.Float)
还有我的ReflectionUtil和PackateBossBar类:
package io.github.utsukushihito.utsutil.api.misc
import org.bukkit.Bukkit
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.util.*
import java.util.stream.Collectors
class ReflectionUtil {
private val nmsVersion: String
get() = nms().split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[3]
val craftBukkitVersion: String
get() = cb().split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[3]
private fun nms(): String {
return exec<Any>(Bukkit.getServer(), "getServer").javaClass.getPackage().name
}
private fun cb(): String {
return Bukkit.getServer().javaClass.getPackage().name
}
fun getPackageName(nmsObject: Any): String {
return nmsObject.javaClass.getPackage().name
}
fun getBukkitClass(craftObject: Any): Class<*> {
var clazz: Class<*> = craftObject.javaClass
while (clazz.canonicalName.contains(".craftbukkit.")) {
clazz = clazz.superclass
}
return clazz
}
fun getCustomBukkitClass(className: String): Class<*> {
return Class.forName("org.bukkit.craftbukkit.$nmsVersion.$className")
}
fun getNMSClass(name: String): Class<*> {
return Class.forName("net.minecraft.server.$nmsVersion.$name")
}
fun <T> execStatic(clazz: Class<*>, methodName: String, vararg args: Any): T {
val method = getMethod(clazz, methodName, *argTypes(*args))
val wasAccessible = method.isAccessible
method.isAccessible = true
try {
return method.invoke(null, *args) as T
} finally {
method.isAccessible = wasAccessible
}
}
fun <T> execStatic(clazz: Class<*>, methodName: String, argTypes: Array<Class<*>>, vararg args: Any): T {
val method = getMethod(clazz, methodName, *argTypes)
val wasAccessible = method.isAccessible
method.isAccessible = true
try {
return method.invoke(null, *args) as T
} finally {
method.isAccessible = wasAccessible
}
}
fun <T> exec(obj: Any, methodName: String, argTypes: Array<Class<*>>, vararg args: Any): T {
val aClass = obj.javaClass
val method = getMethod(aClass, methodName, *argTypes)
val wasAccessible = method.isAccessible
method.isAccessible = true
try {
return method.invoke(obj, *args) as T
} finally {
method.isAccessible = wasAccessible
}
}
fun getMethod(aClass: Class<*>, methodName: String, vararg argTypes: Class<*>): Method {
return aClass.getDeclaredMethod(methodName, *argTypes)
}
fun findMethod(aClass: Class<*>, returnType: Class<*>, vararg argTypes: Class<*>): Method {
return findMethods(aClass, returnType, *argTypes)[0]
}
fun findMethods(aClass: Class<*>, returnType: Class<*>, vararg argTypes: Class<*>): List<Method> {
val methods = ArrayList<Method>()
for (m in aClass.declaredMethods) {
if (m.returnType == returnType && m.parameterTypes.size == argTypes.size) {
val mLookup = aClass.getMethod(m.name, *argTypes)
if (mLookup != null) methods.add(mLookup)
}
}
return methods
}
fun <T> exec(obj: Any, methodName: String, vararg args: Any): T {
return exec(obj, methodName, argTypes(*args), *args) as T
}
fun <T> getField(clazz: Class<*>, fieldName: String): T {
val field = getFieldFromClass(clazz, fieldName)
val wasAccessible = field.isAccessible
field.isAccessible = true
try {
return field.get(null) as T
} finally {
field.isAccessible = wasAccessible
}
}
fun <T> getField(obj: Any, fieldName: String): T {
val field = getFieldInternal(obj, fieldName)
val wasAccessible = field.isAccessible
field.isAccessible = true
try {
return field.get(obj) as T
} finally {
field.isAccessible = wasAccessible
}
}
fun getFieldInternal(obj: Any, fieldName: String): Field {
return getFieldFromClass(obj.javaClass, fieldName)
}
fun getFieldFromClass(aClass: Class<*>, fieldName: String): Field {
return try {
aClass.getDeclaredField(fieldName)
} catch (e: NoSuchFieldException) {
try {
aClass.getField(fieldName)
} catch (e1: NoSuchFieldException) {
getFieldFromClass(aClass.superclass, fieldName)
}
}
}
fun setField(obj: Any, fieldName: String, field: Any?) {
val declaredField = getFieldInternal(obj, fieldName)
val wasAccessible = declaredField.isAccessible
declaredField.isAccessible = true
try {
declaredField.set(obj, field)
} finally {
declaredField.isAccessible = wasAccessible
}
}
fun <T> newInstance(clazz: Class<*>, argTypes: Array<Class<*>>, vararg args: Any): T {
return clazz.getDeclaredConstructor(*argTypes).newInstance(*args) as T
}
fun <T> newInstance(clazz: Class<*>, vararg args: Any): T {
return newInstance(clazz, argTypes(*args), *args)
}
fun <T> newInstance(className: String, vararg args: Any): T {
return newInstance(className, argTypes(*args), *args)
}
private fun argTypes(vararg args: Any): Array<Class<*>> {
val argTypes = ArrayList<Class<*>>()
args.forEach { argTypes.add(it::class.java) }
return argTypes.toTypedArray()
}
fun dumpMethods(aClass: Class<*>): List<String> {
val methods = aClass.declaredMethods
val methodDescriptions = ArrayList<String>()
val version = nmsVersion
for (m in methods) {
var parmString = Arrays.toString(Arrays.stream(m.parameterTypes).map<String>{ it.name }.toArray())
parmString = parmString.substring(1, parmString.length - 1)
var description = ((if (Modifier.isPublic(m.modifiers)) "public " else if (Modifier.isPrivate(m.modifiers)) "private " else "")
+ (if (Modifier.isStatic(m.modifiers)) "static " else "")
+ m.returnType + " " + m.name
+ "(" + parmString + ")")
description = description
.replace("class net.minecraft.server.$version.".toRegex(), "")
.replace("net.minecraft.server.$version.".toRegex(), "")
.replace("java.lang.".toRegex(), "")
methodDescriptions.add(description)
}
val list = ArrayList<String>()
list.add(aClass.toString().replace("class net.minecraft.server.$version.".toRegex(), "")
.replace("net.minecraft.server.$version.".toRegex(), "")
.replace("java.lang.".toRegex(), "") + ":")
list.addAll(methodDescriptions.stream().sorted { obj, anotherString -> obj.compareTo(anotherString) }.collect(Collectors.toList()))
return list
}
companion object {
val instance = ReflectionUtil()
}
}
package io.github.utsukushihito.utsutil.nms.v1_13_R2
import io.github.utsukushihito.utsutil.api.bossbar.addBossBarForPlayer
import io.github.utsukushihito.utsutil.api.bossbar.enums.Color
import io.github.utsukushihito.utsutil.api.bossbar.enums.Property
import io.github.utsukushihito.utsutil.api.bossbar.enums.Style
import io.github.utsukushihito.utsutil.api.bossbar.removeBossBarForPlayer
import io.github.utsukushihito.utsutil.api.misc.ReflectionUtil
import io.github.utsukushihito.utsutil.api.nms.IBossBar
import net.md_5.bungee.api.chat.TextComponent
import net.md_5.bungee.chat.ComponentSerializer
import net.minecraft.server.v1_13_R2.BossBattle
import net.minecraft.server.v1_13_R2.IChatBaseComponent
import net.minecraft.server.v1_13_R2.PacketPlayOutBoss
import org.bukkit.Location
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer
import org.bukkit.entity.Player
import java.util.*
class PacketBossBar1_13_R2(
private var message: String,
private var color: Color,
private var style: Style,
private var progress: Float,
vararg properties: Property
) : IBossBar{
private val receivers = ArrayList<Player>()
private val uuid = UUID.randomUUID()
private var darkenSky: Boolean = false
private var playMusic: Boolean = false
private var createFog: Boolean = false
private var visible: Boolean = false
constructor(
message: TextComponent,
color: Color,
style: Style,
progress: Float,
vararg properties: Property
): this(ComponentSerializer.toString(message), color, style, progress, *properties)
// I Try to run this cotr with the reflection util.
constructor(
message: TextComponent,
color: Color,
style: Style,
progress: Float
): this(ComponentSerializer.toString(message), color, style, progress)
init {
setMessage(message)
setProgress(progress)
properties.forEach {
setProperty(it,true)
}
}
override fun getPlayers(): Collection<Player> {
return ArrayList(this.receivers)
}
override fun addPlayer(player: Player) {
if (!receivers.contains(player)) {
receivers.add(player)
sendPacket(PacketPlayOutBoss.Action.ADD, player)
player.addBossBarForPlayer(this)
}
}
override fun removePlayer(player: Player) {
if (receivers.contains(player)) {
receivers.remove(player)
sendPacket(PacketPlayOutBoss.Action.REMOVE, player)
player.removeBossBarForPlayer(this)
}
}
override fun getColor(): Color {
return color
}
override fun setColor(color: Color) {
if (color != this.color) {
this.color = color;
sendPacket(PacketPlayOutBoss.Action.UPDATE_STYLE, null);
}
}
override fun getStyle(): Style {
return style
}
override fun setStyle(style: Style) {
if (style != this.style) {
this.style = style
sendPacket(PacketPlayOutBoss.Action.UPDATE_STYLE, null)
}
}
override fun setProperty(property: Property, flag: Boolean) {
when (property) {
Property.DARKEN_SKY -> darkenSky = flag
Property.PLAY_MUSIC -> playMusic = flag
Property.CREATE_FOG -> createFog = flag
}
sendPacket(PacketPlayOutBoss.Action.UPDATE_PROPERTIES, null)
}
override fun setMessage(message: String) {
if (!message.startsWith("{") || !message.endsWith("}")) {
throw IllegalArgumentException("Invalid JSON")
}
if (message != this.message) {
this.message = message
sendPacket(PacketPlayOutBoss.Action.UPDATE_NAME, null)
}
}
override fun getMessage(): String {
return message;
}
override fun setVisible(flag: Boolean) {
if (flag != this.visible) {
this.visible = flag
sendPacket(if (flag) PacketPlayOutBoss.Action.ADD else PacketPlayOutBoss.Action.REMOVE, null)
}
}
override fun isVisible(): Boolean {
return visible
}
override fun getProgress(): Float {
return progress
}
override fun setProgress(progress: Float) {
if (progress > 1) this.progress = progress / 100F
if (progress != this.progress) {
this.progress = progress
sendPacket(PacketPlayOutBoss.Action.UPDATE_PCT, null)
}
}
private fun sendPacket(action: PacketPlayOutBoss.Action, player: Player?) {
try {
val packet = PacketPlayOutBoss()
val ref = ReflectionUtil.instance
ref.setField(packet,"a",uuid)
ref.setField(packet,"b",action)
ref.setField(packet,"c",IChatBaseComponent.ChatSerializer.a(message)?: "")
ref.setField(packet,"d",progress)
ref.setField(packet,"e", BossBattle.BarColor.a(color.id))
ref.setField(packet,"f",BossBattle.BarStyle.a(style.id))
ref.setField(packet,"g",darkenSky)
ref.setField(packet,"h",playMusic)
ref.setField(packet,"i",createFog)
if (player != null) {
(player as CraftPlayer).handle.playerConnection.sendPacket(packet)
} else {
for (player1 in this.getPlayers()) {
(player1 as CraftPlayer).handle.playerConnection.sendPacket(packet)
}
}
} catch (e: ReflectiveOperationException) {
throw RuntimeException(e)
}
}
override fun getMaxHealth(): Float {
return 100F
}
override fun setHealth(percentage: Float) {
setProgress(percentage / 100F)
}
override fun getHealth(): Float {
return getProgress() * 100F
}
override fun getReceiver(): Player {
throw UnsupportedOperationException()
}
override fun getLocation(): Location {
throw UnsupportedOperationException()
}
override fun updateMovement() {
throw UnsupportedOperationException()
}
}```
答案 0 :(得分:0)
您可以通过以下方式解决此特定情况
<?php
$name = $_POST['name'];
$num = $_POST['num'];
foreach ($num as $num){
foreach ($name as $name){
$num * $name
}
}
?>
但是找不到一个private fun argTypes(vararg args: Any): Array<Class<*>> {
val argTypes = args.map { it::class.javaPrimitiveType ?: it::class.java }
return argTypes.toTypedArray()
}
的构造函数。
简而言之:如果您知道构造函数/方法的实际参数,则签名中的类型有很多选项,因此,尝试一个(如java.lang.Float
一样)通常是不可能的。除了您遇到的问题外,声明的参数类型还可以是参数类的超类型,构造函数可以具有varargs,等等。
一个可能的解决方案是获取所有构造函数,将参数提供给它们,并使用第一个不会引发异常的构造函数。您仍然需要注意varargs。性能成本是否可以接受取决于您的用例。