代码之家  ›  专栏  ›  技术社区  ›  Wolkenarchitekt

以字符串形式获取类属性或类函数的名称

  •  3
  • Wolkenarchitekt  · 技术社区  · 14 年前

    假设我有以下课程:

    class Person {
      @BeanProperty
      var firstName: String = _
    }
    

    是否可以通过反射或其他方式以类型安全的方式获得“firstname”的字符串表示形式?或者生成的“getfirstname”函数的字符串表示形式?

    如果它看起来像:

    val p = new Person
    p.getFunction(p.getFirstName).toString // "getFirstName"
    p.getAttribute(p.firstName).toString   // "firstName"
    

    编辑

    好的,需要更多的解释;)

    假设我想构建这样的SQL查询:

    val jpql = "select p from Person p where p.age > 20";
    

    因此,我想尽可能保证它的类型安全,并写下如下内容:

    val jpql = "select p from " + classOf[Person].getName + " where p." + 
      Person.getAttName(p.age) + " > 20";
    

    这样,如果将来可以重构scala代码,我可以在不破坏代码的情况下更改person的属性名。

    2 回复  |  直到 14 年前
        1
  •  2
  •   Adam Rabung    14 年前

    坏消息是scala没有能力引用这样的成员。你 可以 获取“方法引用”,如下所示:

    scala> class Person(val firstName:String)         
    defined class Person
    
    scala> val methodRef = new Person("i").firstName _
    methodRef: () => String = <function0>
    
    scala> methodRef()                                
    res1: String = i
    

    但它并没有给你想要的反光材料。好消息是,有几个库提供了这种类型的安全JDBC。这是您的代码使用 Squeryl :

    import org.squeryl.Schema
    import org.squeryl.Session
    import org.squeryl.PrimitiveTypeMode._
    import org.squeryl.adapters.H2Adapter
    import org.squeryl.SessionFactory
    
    object Sample {
    case class Person(val firstName:String, val age:Int)
    
    object AppSchema extends Schema {
      val people = table[Person]("People")
    }
    
    def main(args:Array[String]) { 
      import AppSchema.people
      Class.forName("org.h2.Driver")
      SessionFactory.concreteFactory = Some(()=> Session.create(java.sql.DriverManager.getConnection("jdbc:h2:~/temp/db", "sa", ""), new H2Adapter))
    
      transaction {
        AppSchema.create
        people.insert(new Person("ifischer", 92)) 
        people.insert(new Person("baby", 2)) 
        for (olderPerson <- from(people)(p=> where(p.age gt 20) select(p))) {
          println(olderPerson) //wont return "baby"!
        }
      } 
    }
    }
    

    这有多酷?例如,如果您试图将年龄与字符串进行比较,则无法编译。当然,如果使用p.ssn或其他未知字段,它也不会编译。

        2
  •  2
  •   Abhinav Sarkar    14 年前

    我假设您不知道要检查的类中的方法和属性名(否则,为什么要获取它们的名称而不只是输入它们?)。此示例演示如何获取 java.lang.String 班级。

    scala> classOf[String].getMethods.map(_.getName)
    res4: Array[java.lang.String] = Array(equals, hashCode, toString, charAt, compareTo, 
    compareToIgnoreCase, concat, endsWith, equalsIgnoreCase, getBytes, getBytes, getBytes, 
    getChars, indexOf, indexOf, indexOf, indexOf, intern, lastIndexOf, lastIndexOf, 
    lastIndexOf, lastIndexOf, length, regionMatches, regionMatches, replace, startsWith, 
    startsWith, substring, substring, toCharArray, toL...