Как мне проанализировать класс переменной в APEX? - PullRequest
4 голосов
/ 03 марта 2012

Я хотел бы знать класс переменной / свойства во время выполнения.Например:

Integer i = 5;

//pseudo-code
if (i.className == 'Integer') {
    System.debug('This is an integer.');
} else {
    System.debug('This is not an integer, but a ' + i.className);
}

Я не могу найти метод / свойство, которое возвращает тип класса в документации (при условии, что он есть).Я скучаю по нему?

Ответы [ 7 ]

9 голосов
/ 04 марта 2012

С стр. 122 Руководства разработчика Apex :

Если вам нужно во время выполнения проверить, является ли объект экземпляр определенного класса, используйте ключевое слово instanceof ...

Но вы не можете использовать ключевое слово instanceof в экземпляре класса его подклассов, иначе вы получите ошибку компиляции. Например:

Integer i = 0;
System.debug(i instanceof Integer);

>> COMPILE ERROR: Operation instanceof is always true since an instance of Integer is always an instance of Integer.

Вам необходимо использовать ключевое слово instanceof только для суперклассов. Например:

System.debug((Object)i instanceof Integer);

>> true

Если вам когда-нибудь понадобится информация о типе самого Класса, проверьте методы System.Type ( стр. 396 руководства текущего разработчика Apex . Вот несколько примеров:

Type integerType;
integerType = Type.forName('Integer');
integerType = Integer.class;
8 голосов
/ 17 апреля 2012

Кто-то спросил меня об этом ранее сегодня. Вот более динамичное решение.

MyClass mine     = new MyClass();
String myStr     = String.valueOf(mine);
String className = myStr.split(':')[0];
System.assertEquals('MyClass', className);
2 голосов
/ 16 апреля 2014

Просто для добавления дополнительной информации относительно toString() и String.valueOf().

String.valueOf() нельзя полагаться на получение имени класса Apex во время выполнения.Я не думаю, что это задокументировано, но если вы добавите метод toString() в свой пользовательский класс с ключевым словом override, то String.valueOf() будет использовать его для определения строкового значения вашего объекта.

class MyClassDefaultToString {
}

class MyClassOverrideToString {
    public override String toString() {
        return 'override toString';
    }
}

MyClassDefaultToString c1 = new MyClassDefaultToString();
System.assertEquals('MyClassDefaultToString:[]', String.valueOf(c1));

MyClassOverrideToString c2 = new MyClassOverrideToString();
System.assertNotEquals('MyClassOverrideToString:[]', String.valueOf(c2));
System.assertEquals('override toString', String.valueOf(c2));
2 голосов
/ 05 мая 2013

Общий код Salesforce Apex для объяснения:

public class Animal {}
public class Bird extends Animal {}

Animal a = new Bird();                      // Success
System.debug(a);                            // Bird:[]
System.debug((Bird)a);                      // Bird:[]
System.debug((Animal)a);                    // Bird:[]
System.debug(a instanceof Bird);            // true
System.debug((Animal)a instanceof Bird);    // true
System.debug((Bird)a instanceof Bird);      // Operation instanceof is always true since an instance of Bird is always an instance of Bird
System.debug((Bird)a instanceof Animal);    // Operation instanceof is always true since an instance of Bird is always an instance of Animal
0 голосов
/ 11 апреля 2019

Что если вам понадобится FQCN вместо имени класса (например, что вы получите от getName() в Java)? Вот что вы можете сделать.

public class Beasts {
  public interface Animal {}
  public virtual class Bird implements Animal {}
  public class Robin extends Bird {}
}

System.assertEquals(
  Robin.class,
  Type.forName(ObjUtil.getName(new Robin(), true))
);
System.assertEquals(
  Robin.class,
  Type.forName(ObjUtil.getName((Animal)new Robin(), true)))
);
System.assertEquals(
  Robin.class,
  Type.forName(ObjUtil.getName((Bird)new Robin(), true)))
);

public class ObjUtil {
  public static String getName(Object obj, Boolean isQualifiedName) {
    // Qualified name
    if (isQualifiedName) {
      try {
        if (0 == (Long) obj) {
        }
      } catch (Exception ex) {
        typeName = ex.getMessage().remove('Invalid conversion from runtime type ').remove(' to Long');
        System.debug('typeName = ' + typeName);
        return typeName;
      }
    } else {
      // Class name
      typeName = String.valueOf(obj);
      if (typeName.indexOf(':[') != -1) {
        typeName = typeName.split(':')[0];
        System.debug('typeName = ' + typeName);
        return typeName;
      }
    }
  }
}
0 голосов
/ 29 июня 2016

Это работает для меня

Map<String, Object> m =  (Map<String, Object>)JSON.deserializeUntyped(JSON.serialize(myObjectInstance));
Map<String, Object> mComplexProperty = (Map<String, Object>)m.get('complexProperty');
String mSimpleProperty = (String)m.get('simpleProperty');

Я не уверен, что сериализация и десериализация JSON будут накладными, но ... пока это работает

0 голосов
/ 05 марта 2012

Не идеально, но вот способ сделать это:

public String getClassType(Object o)
{
    String retVal = 'Unknown';

    if(o instanceof Klass1)
        retVal = 'Klass1';
    else if(o instanceof Klass2)
        retVal = 'Klass2';
    else if(o instanceof Klass3)
        retVal = 'Klass3';

    return retVal;
} 
...