在Java中,我可以TheClass.class.getName()
来获取一个我需要的类名,在某处(避免再次输入,避免拼写错误,明确记录依赖关系)。
我可以为Scala中的函数(或其他东西)执行相同的操作吗?
val theName : String = nameOf[aFunctionThatICanSeeHere]
答案 0 :(得分:3)
对于班级名称:
val theName = classOf[TheClass].getName
classOf[TheClass]
与Java中的TheClass.class
相同。
对于方法等的名称,您可以使用reflection,就像在Java中一样。 (请注意,Scala反射API目前仍处于试验阶段。)
edit - 除了面向对象的编程语言之外,Scala也是一种函数式编程语言。您可以将函数作为值传递。例如:
class Thing {
def method(x: Int): Int = x + 2
}
val thing = new Thing
// fn is a value that refers to a method
// similar to (but not really the same as) a method reference in Java
val fn = thing.method _
// you can call the method through fn
val result = fn(3) // same as thing.method(3)
答案 1 :(得分:2)
您可以使用scala-nameof来获取函数名称,变量名称,类成员名称或类型名称。它发生在编译时,因此不涉及反射,也不需要运行时依赖。
val theName = nameOf(aFunctionThatICanSeeHere _)
将编译为:
val theName = "aFunctionThatICanSeeHere"
答案 2 :(得分:1)
这使用ObjectWeb ASM库。这将提取给定类实例的所有方法。还有用于获取方法名称的代码。
import org.objectweb.asm.Type
import org.objectweb.asm.Type
import org.objectweb.asm.tree._
import org.objectweb.asm.util._
import java.lang.reflect.Method
case class ScalaMethod(name:String, returnType:Type, params:List[Param], parentClassName:String)
case class Param(paraName:String, paraType:Type)
object MethodReader {
/*
* stackoverflow.com/questions/7640617/how-to-get-parameter-names-and-types-via-reflection-in-scala-java-methods
*/
def getMethods(c:AnyRef, is:java.io.InputStream) = {
val cn = new ClassNode();
val cr = new ClassReader(is);
cr.accept(cn, 0);
is.close();
val methods = cn.methods.asInstanceOf[java.util.List[MethodNode]];
var mList:List[ScalaMethod] = Nil
if (methods.size > 0) for (i <- 1 to methods.size) {
try {
val m:MethodNode = methods.get(i-1)
val argTypes:Array[Type] = Type.getArgumentTypes(m.desc);
val vars = m.localVariables.asInstanceOf[java.util.List[LocalVariableNode]];
var pList:List[Param] = Nil
if (argTypes.length > 0 && vars.length > 0) for (i <- 1 to argTypes.length) {
// The first local variable actually represents the "this" object in some cases
val difference = if (vars.get(0).name == "this") 0 else 1
pList = Param(vars.get(i-difference).name, argTypes(i-1)) :: pList
}
mList = ScalaMethod(m.name, Type.getReturnType(m.desc), pList.reverse, c.getClass.getCanonicalName):: mList
} catch {
case e:Throwable =>
}
}
mList.reverse
}
def getMethods(c, is):List[ScalaMethod] = {
val t = Type.getType(c);
val url = t.getInternalName() + ".class";
val is = try {
val cl = c.getClassLoader();
val is = cl.getResourceAsStream(url);
if (is == null) throw new IllegalArgumentException("Cannot find class: " + url);
else is
} catch {
case e:IllegalArgumentException =>
new java.io.FileInputStream(url)
}
}
}