39

I need a quick approach to something like:

  MyClass mc = new MyClass();
  String theName = ClassNameProvider.getName(mc); // returns 'MyClass'
2

4 Answers 4

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.

4
  • 7
    harder, better, faster, stronger Jan 11, 2014 at 13:38
  • 5
    NOTE: String.valueOf(mc).split(':')[0] will not include the top level class for inner classes
    – NSjonas
    Oct 10, 2016 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, 2018 at 4:54
  • 2
    Worth considering: String name = String.valueOf( mc ).substringBefore( ':' ) as it's just a little bit clearer Nov 7, 2019 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.

1
  • This method is also better than the String.valueOf(obj) method because it includes the top-level class for inner classes. Jan 16, 2023 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(':'));
3
  • 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 7, 2017 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 5, 2019 at 9: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, 2021 at 15:52
1

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;
    }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .