tuler
tuler

Reputation: 3389

How do I check if a groovy class has a static property?

Given the following groovy class:

​class A {
    static x = { }
}

How do I check if class A has defined a static property called 'x'? Neither option below seems to work:

A.hasProperty('x')
A.metaClass.hasProperty('x')

Upvotes: 6

Views: 6580

Answers (5)

Sudhir N
Sudhir N

Reputation: 4096

Look at GrailsClassUtils.getStaticFieldValue - it returns a static field value by name, null if no property exist or not set. You may look at implementation if that's helpful

Upvotes: 4

Seva
Seva

Reputation: 2488

As of 2017 and groovy 2.4.x, the best way to check appears to be this:

A.metaClass.getMetaProperty('x') != null

It works for both static and non-static properties as well as for properties defined with only getter and setter (but no actual field), or by a field without a getter or setter (e.g. in a java class). You can inspect returned MetaProperty for more details if required. Beware that a property might be defined by a setter only thus being not readable. So, if it is important, adjust your checks accordingly.

Note however that this method does not allow to check whether property is static.

sudhir answer is probably second best, as it's implementation relies on getDeclaredFields and as a result, does not find properties defined only by getter and setter. It also only useful if you're using grails. It also fetches the actual value if present which may or may not be desired.

SteveD answers does not work. Yet can be fixed by removing 'class' before declaredFields and adding checks for getters and setters. So, full check for property existence is as follows:

def hasProperty = { Class c, String propertyName ->
    if (!propertyName)
        return false;
    String p2 = propertyName.substring(0, 1).toUpperCase()
    if (propertyName.length()> 1)
        p2 += propertyName.substring(1)
    return c.declaredFields.find {
        it.name == propertyName /* && isStatic(it.modifiers) */
    } || c.declaredMethods.find {
        it.name == ('get' + p2) /* && isStatic(it.modifiers) */
    } || c.declaredMethods.find {
        it.name == ('is' + p2) /* && isStatic(it.modifiers) */
    } || c.declaredMethods.find {
        it.name == ('set' + p2)/* && isStatic(it.modifiers) */
    }
}

Note that this method also checks that property is actually static (just import static java.lang.reflect.Modifier.isStatic and uncomment isStatic checks). Same as above, beware of setter-only properties.

Upvotes: 0

Cagatay Kalan
Cagatay Kalan

Reputation: 4126

A.metaClass.hasProperty(A,'x')

or

A.metaClass.respondsTo(A,'getX')

Upvotes: 3

SteveD
SteveD

Reputation: 5405

I couldn't see a groovier way of doing this other than using Java's reflection API:

import static java.lang.reflect.Modifier.isStatic

class A {
  static x = 1
}

def result = A.class.declaredFields.find { 
    it.name == 'x' && isStatic(it.modifiers)
}

println result == null ? 'class does not contain static X' : 
                         'class contains static X'

Upvotes: 6

Dónal
Dónal

Reputation: 187499

I couldn't see any obvious way to check for a static property directly, but checking for a static method named getProperty is equivalent (I think)

def getStaticProperty(String name, Class clazz) {
  def noArgs = [].toArray()
  def methodName = 'get' + name[0].toUpperCase()

  if (name.size() > 1) {
    methodName += name[1..-1]
  }

  clazz.metaClass.getStaticMetaMethod(methodName, noArgs)
}

// class that will be used in tests
class Foo {

  static String x = 'bar'
  static Integer num = 3
}

// tests
assert getStaticProperty('x', Foo)
assert getStaticProperty('num', Foo)
assert getStaticProperty('noSuchProperty', Foo) == null

Upvotes: 0

Related Questions