39

I need a quick approach to something like:

  MyClass mc = new MyClass();
  String theName = ClassNameProvider.getName(mc); // returns 'MyClass'
ca_peterson
  • 22,983
  • 7
  • 69
  • 123
max
  • 2,419
  • 2
  • 22
  • 31

4 Answers4

59

I think your requirement falls in the gap for apex but we have the ability to do one of following things:

We can retrieve the name of an object using code such as

String name = MyClass.class.getName(); //returns MyClass

We can check whether the instance of a particular type using

Boolean isSame = mc instanceof MyClass; //returns true

Or if we want to get the name from an instance of an unknown type we can do:

String name = String.valueOf(mc).split(':')[0];//returns MyClass

Hopefully one of those covers your need. See the discussion to a similar question here for more info.

pbattisson
  • 3,308
  • 1
  • 22
  • 25
  • 7
    harder, better, faster, stronger – Matt and Neil Jan 11 '14 at 13:38
  • 5
    NOTE: String.valueOf(mc).split(':')[0] will not include the top level class for inner classes – NSjonas Oct 10 '16 at 18:15
  • 2
    NOTE: That String.valueOf(mc) returns the toString() value of the class. The default return value is format of ClassName:[field1=value1, field2=value2,...fieldN=valueN] but if the class overrides the toString() method then this trick may not work for you. – Doug Ayers Jun 22 '18 at 04:54
  • 1
    Worth considering: String name = String.valueOf( mc ).substringBefore( ':' ) as it's just a little bit clearer – Rob Baillie Nov 07 '19 at 11:42
11

This is an interesting hack as posted on the idea Method to get the Type of an Object (also Primitive Type not only SObject) by Robert Strunk:

public static String getObjectType(Object obj){

    String result = 'DateTime';
    try{
        DateTime typeCheck = (DateTime)obj;
    }
    catch(System.TypeException te){

        String message = te.getMessage().substringAfter('Invalid conversion from runtime type ');
        result = message.substringBefore(' to Datetime');
    }

    return result;
}

The parse conversion exception approach overcomes the caveat that using String.valueOf(obj).split(':')[0] does not work in scenarios where the Apex class' toString() method has been overriden and returns a value in a different format, as pointed out in this comment.

Doug Ayers
  • 4,186
  • 2
  • 28
  • 51
  • This method is also better than the String.valueOf(obj) method because it includes the top-level class for inner classes. – Jason Clark Jan 16 '23 at 22:18
6

To answer the title of the question: to get the name of the class from within any class use this:

String CurrentClassName = String.valueOf(this).substring(0,String.valueOf(this).indexOf(':'));
paulmorriss
  • 272
  • 3
  • 12
  • 2
    Note the accepted answer recommends String.valueOf(mc).split(':')[0] among other approaches. This approach is just a slower version of that (you take String.valueOf twice). – Adrian Larson Apr 07 '17 at 13:17
  • 1
    Actually, sometimes Paul's answer works better. Split-approach in some cases, for example within a loop, could reach a "Regex is too complicated" Salesforce Limit. – kvor Jul 05 '19 at 09:04
  • 1
    This could be improved by saving String.valueOf(this) in a string, which is then referenced twice. But, it beats all the other methods becuase they all need a line with the Class name in it in the first place - just save it as a String if you are going to do that. This method works, exactly as it is, everywhere! – cyberspy May 26 '21 at 15:52
0

While my response might be a delayed, it could help for someone currently in search of this solution.

GitHub Gist Link

Usage :

ClassUtility.getClassName(); // will return the class name from where we are calling
ClassUtility.getMethodName(); // will return the method name from where we are calling

ClassUtility.getMethodNameByLevelup(1); ClassUtility.getMethodNameByLevelup(1);

Class :

/**
 * Company: Kloudflex.com
 * Purpose: A utility class for extracting class and method names from the stack trace.
 * Author: Mohamed Thameem
 * 
 * Change Log:
 * 01/11/2024 - Initial Version of the class
 */

public class ClassUtility {

/**
* Gets the class name from the stack trace.
* @return String - The class name.
*/
public static String getClassName() {
    List<String> splitClassList = getClassOrMethodName(0);
    return (splitClassList != null) && splitClassList.size() > 1 ? splitClassList[1] : 'Unavailable';
}

/**
* Gets the method name from the stack trace.
* @return String - The method name.
*/
public static String getMethodName() {
    List<String> splitMethodList = getClassOrMethodName(0);
    return (splitMethodList != null) && splitMethodList.size() > 2 ? splitMethodList[2] : 'Unavailable';
}

/**
* Gets the class name from the stack trace by moving up a specified number of levels.
* @param levelUp - The number of levels to move up in the stack trace.
* @return String - The class name.
*/
public static String getClassNameByLevelup(Integer levelUp) {
    List<String> splitClassList = getClassOrMethodName(levelUp);
    return (splitClassList != null) && splitClassList.size() > 1 ? splitClassList[1] : 'Unavailable';
}

/**
* Gets the method name from the stack trace by moving up a specified number of levels.
* @param levelUp - The number of levels to move up in the stack trace.
* @return String - The method name.
*/
public static String getMethodNameByLevelup(Integer levelUp) {
    List<String> splitMethodList = getClassOrMethodName(levelUp);
    return (splitMethodList != null) && splitMethodList.size() > 2 ? splitMethodList[2] : 'Unavailable';
}

/**
* Gets the class or method name from the stack trace by moving up a specified number of levels.
* @param levelUp - The number of levels to move up in the stack trace.
* @return List<String> - The list containing class and method names.
*/
private static List<String> getClassOrMethodName(Integer levelUp) {
    levelUp = levelUp == null ? 0 : levelUp;

    try {
        Integer a;
        a = a + 1;
    } catch (Exception e) {
        List<String> splitStackTrace = e.getStackTraceString().split('\n');
        String traceString = (splitStackTrace.size() > (2 + levelUp)) ? splitStackTrace[(2 + levelUp)] : null;
        return (traceString != null) ? traceString.split(':').size() > 0 ? traceString.split(':')[0].split('\\.') : null : null;
    }

    return null;
}

}