|
發表者 |
討論內容 |
冷日 (冷日) |
發表時間:2019/4/2 5:44 |
- Webmaster
- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]getting only name of the class Class.getName()
- getting only name of the class Class.getName()
How can i get the name of the class
String.class.getName() returns java.lang.String
I am only interested in getting last part ie only String
The below both ways works fine.
System.out.println("The Class Name is: " + this.getClass().getName());
System.out.println("The simple Class Name is: " + this.getClass().getSimpleName());
Output as below:
The Class Name is: DemoJava.Student
The simple Class Name is: Student
or programmaticaly
String s = String.class.getName();
s = s.substring(s.lastIndexOf('.') + 1);
You can use following simple technique for print log with class name.
private String TAG = MainActivity.class.getSimpleName();
Suppose we have to check coming variable value in method then we can use log like bellow :
private void printVariable(int variable){
Log.e(TAG, "printVariable: "+variable);
}
Importance of this line is that, we can check method name along with class name. To write this type of log. write :- loge and Enter. will print on console
E/MainActivity: printVariable: 5
Social.class.getSimpleName()
getSimpleName() : Returns the simple name of the underlying class as given in the source code. Returns an empty string if the underlying class is anonymous. The simple name of an array is the simple name of the component type with "[]" appended. In particular the simple name of an array whose component type is anonymous is "[]".
To get simple class name without any reference or path use..
String onlyClassName = getLocalClassName();
原文出處:java - getting only name of the class Class.getName() - Stack Overflow
|
|
冷日 (冷日) |
發表時間:2019/4/2 5:50 |
- Webmaster
- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]Java - get the current class name?
- Java - get the current class name?
All I am trying to do is to get the current class name, and java appends a useless non-sense $1 to the end of my class name. How can I get rid of it and only return the actual class name?
String className = this.getClass().getName();
The "$1" is not "useless non-sense". If your class is anonymous, a number is appended. If you don't want the class itself, but its declaring class, then you can use getEnclosingClass(). For example:
Class<?> enclosingClass = getClass().getEnclosingClass();
if (enclosingClass != null) {
System.out.println(enclosingClass.getName());
} else {
System.out.println(getClass().getName());
}
You can move that in some static utility method. But note that this is not the current class name. The anonymous class is different class than its enclosing class. The case is similar for inner classes.
Try,
String className = this.getClass().getSimpleName();
This will work as long as you don't use it in a static method.
Try using this this.getClass().getCanonicalName() or this.getClass().getSimpleName(). If it's an anonymous class, use this.getClass().getSuperclass().getName()
You can use this.getClass().getSimpleName(), like so:
import java.lang.reflect.Field;
public class Test {
int x;
int y;
public void getClassName() {
String className = this.getClass().getSimpleName();
System.out.println("Name:" + className);
}
public void getAttributes() {
Field[] attributes = this.getClass().getDeclaredFields();
for(int i = 0; i < attributes.length; i++) {
System.out.println("Declared Fields" + attributes[i]);
}
}
public static void main(String args[]) {
Test t = new Test();
t.getClassName();
t.getAttributes();
}
}
this answer is late, but i think there is another way to do this in the context of anonymous handler class. let's say:
class A {
void foo() {
obj.addHandler(new Handler() {
void bar() {
String className=A.this.getClass().getName();
// ...
}
});
}
}
it will achieve the same result. additionally, it's actually quite convenience since every class is defined at compile time, so no dynamicity is damaged. above that, if the class is really nested, i.e. A actually is enclosed by B, the class of B can be easily known as:
B.this.getClass().getName()
The combination of both answers. Also prints a method name:
Class thisClass = new Object(){}.getClass();
String className = thisClass.getEnclosingClass().getSimpleName();
String methodName = thisClass.getEnclosingMethod().getName();
Log.d("app", className + ":" + methodName);
In your example, this probably refers to an anonymous class instance. Java gives a name to those classes by appending a $number to the name of the enclosing class.
I'm assuming this is happening for an anonymous class. When you create an anonymous class you actually create a class that extends the class whose name you got. The "cleaner" way to get the name you want is: If your class is an anonymous inner class, getSuperClass() should give you the class that it was created from. If you created it from an interface than you're sort of SOL because the best you can do is getInterfaces() which might give you more than one interface. The "hacky" way is to just get the name with getClassName() and use a regex to drop the $1.
I've found this to work for my code,, however my code is getting the class out of an array within a for loop.
String className="";
className = list[i].getClass().getCanonicalName();
System.out.print(className); //Use this to test it works
Reflection APIs There are several Reflection APIs which return classes but these may only be accessed if a Class has already been obtained either directly or indirectly.
Class.getSuperclass()
Returns the super class for the given class.
Class c = javax.swing.JButton.class.getSuperclass();
The super class of javax.swing.JButton is javax.swing.AbstractButton.
Class.getClasses()
Returns all the public classes, interfaces, and enums that are members of the class including inherited members.
Class<?>[] c = Character.class.getClasses();
Character contains two member classes Character.Subset and Character.UnicodeBlock.
Class.getDeclaredClasses()
Returns all of the classes interfaces, and enums that are explicitly declared in this class.
Class<?>[] c = Character.class.getDeclaredClasses();
Character contains two public member classes Character.Subset and Character.UnicodeBlock and one private class
Character.CharacterCache.
Class.getDeclaringClass()
java.lang.reflect.Field.getDeclaringClass()
java.lang.reflect.Method.getDeclaringClass()
java.lang.reflect.Constructor.getDeclaringClass()
Returns the Class in which these members were declared. Anonymous Class Declarations will not have a declaring class but will
have an enclosing class.
import java.lang.reflect.Field;
Field f = System.class.getField("out");
Class c = f.getDeclaringClass();
The field out is declared in System.
public class MyClass {
static Object o = new Object() {
public void m() {}
};
static Class<c> = o.getClass().getEnclosingClass();
}
The declaring class of the anonymous class defined by o is null.
Class.getEnclosingClass()
Returns the immediately enclosing class of the class.
Class c = Thread.State.class().getEnclosingClass();
The enclosing class of the enum Thread.State is Thread.
public class MyClass {
static Object o = new Object() {
public void m() {}
};
static Class<c> = o.getClass().getEnclosingClass();
}
The anonymous class defined by o is enclosed by MyClass.
原文出處:Java - get the current class name? - Stack Overflow
|
|
|
冷日 (冷日) |
發表時間:2019/4/2 6:10 |
- Webmaster
- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]Getting the name of the currently executing method
- Getting the name of the currently executing method
Is there a way to get the name of the currently executing method in Java?
Thread.currentThread().getStackTrace() will usually contain the method you’re calling it from but there are pitfalls (see Javadoc): Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this thread is permitted to return a zero-length array from this method.
Technically this will work...
String name = new Object(){}.getClass().getEnclosingMethod().getName();
However, a new anonymous inner class will be created during compile time (e.g. YourClass$1.class). So this will create a .class file for each method that deploys this trick. Additionally an otherwise unused object instance is created on each invocation during runtime. So this may be an acceptable debug trick, but it does come with significant overhead. An advantage of this trick is that getEncosingMethod() returns java.lang.reflect.Method which can be used to retrieve all other information of the method including annotations and parameter names. This makes it possible to distinguish between specific methods with the same name (method overload). Note that according to the JavaDoc of getEnclosingMethod() this trick should not throw a SecurityException as inner classes should be loaded using the same class loader. So there is no need to check the access conditions even if a security manager is present. It is required to use getEnclosingConstructor() for constructors. During blocks outside of (named) methods, getEnclosingMethod() returns null.
January 2009: A full code would be (to use with @Bombe's caveat in mind):
/**
* Get the method name for a depth in call stack. <br />
* Utility function
* @param depth depth in the call stack (0 means current method, 1 means call method, ...)
* @return method name
*/
public static String getMethodName(final int depth)
{
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
//System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
// return ste[ste.length - depth].getMethodName(); //Wrong, fails for depth = 0
return ste[ste.length - 1 - depth].getMethodName(); //Thank you Tom Tresansky
}
More in this question. Update December 2011: bluish comments:
I use JRE 6 and gives me incorrect method name.
It works if I write ste[2 + depth].getMethodName().
0 is getStackTrace(),
1 is getMethodName(int depth) and
2 is invoking method.
virgo47's answer (upvoted) actually computes the right index to apply in order to get back the method name.
We used this code to mitigate potential variability in stack trace index - now just call methodName util:
public class MethodNameTest {
private static final int CLIENT_CODE_STACK_INDEX;
static {
// Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
int i = 0;
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
i++;
if (ste.getClassName().equals(MethodNameTest.class.getName())) {
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
public static void main(String[] args) {
System.out.println("methodName() = " + methodName());
System.out.println("CLIENT_CODE_STACK_INDEX = " + CLIENT_CODE_STACK_INDEX);
}
public static String methodName() {
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
}
}
Seems overengineered, but we had some fixed number for JDK 1.5 and were a bit surprised it changed when we moved to JDK 1.6. Now it's the same in Java 6/7, but you just never know. It is not proof to changes in that index during runtime - but hopefully HotSpot doesn't do that bad. :-)
public class SomeClass {
public void foo(){
class Local {};
String name = Local.class.getEnclosingMethod().getName();
}
}
name will have value foo.
The fastest way I found is that:
import java.lang.reflect.Method;
public class TraceHelper {
// save it static to have it available on every call
private static Method m;
static {
try {
m = Throwable.class.getDeclaredMethod("getStackTraceElement",
int.class);
m.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getMethodName(final int depth) {
try {
StackTraceElement element = (StackTraceElement) m.invoke(
new Throwable(), depth + 1);
return element.getMethodName();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
It accesses the native method getStackTraceElement(int depth) directly. And stores the accessible Method in a static variable.
Both of these options work for me with Java:
new Object(){}.getClass().getEnclosingMethod().getName()
Or:
Thread.currentThread().getStackTrace()[1].getMethodName()
Use the following Code :
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
String methodName = e.getMethodName();
System.out.println(methodName);
public static String getCurrentMethodName() {
return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
}
This is an expansion on virgo47's answer (above). It provides some static methods to get the current and invoking class / method names.
/* Utility class: Getting the name of the current executing method
* https://stackoverflow.com/questions/442747/getting-the-name-of-the-current-executing-method
*
* Provides:
*
* getCurrentClassName()
* getCurrentMethodName()
* getCurrentFileName()
*
* getInvokingClassName()
* getInvokingMethodName()
* getInvokingFileName()
*
* Nb. Using StackTrace's to get this info is expensive. There are more optimised ways to obtain
* method names. See other stackoverflow posts eg. https://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection/2924426#2924426
*
* 29/09/2012 (lem) - added methods to return (1) fully qualified names and (2) invoking class/method names
*/
package com.stackoverflow.util;
public class StackTraceInfo
{
/* (Lifted from virgo47's stackoverflow answer) */
private static final int CLIENT_CODE_STACK_INDEX;
static {
// Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
int i = 0;
for (StackTraceElement ste: Thread.currentThread().getStackTrace())
{
i++;
if (ste.getClassName().equals(StackTraceInfo.class.getName()))
{
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
public static String getCurrentMethodName()
{
return getCurrentMethodName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentMethodName(int offset)
{
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getMethodName();
}
public static String getCurrentClassName()
{
return getCurrentClassName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentClassName(int offset)
{
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getClassName();
}
public static String getCurrentFileName()
{
return getCurrentFileName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentFileName(int offset)
{
String filename = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getFileName();
int lineNumber = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getLineNumber();
return filename + ":" + lineNumber;
}
public static String getInvokingMethodName()
{
return getInvokingMethodName(2);
}
private static String getInvokingMethodName(int offset)
{
return getCurrentMethodName(offset + 1); // re-uses getCurrentMethodName() with desired index
}
public static String getInvokingClassName()
{
return getInvokingClassName(2);
}
private static String getInvokingClassName(int offset)
{
return getCurrentClassName(offset + 1); // re-uses getCurrentClassName() with desired index
}
public static String getInvokingFileName()
{
return getInvokingFileName(2);
}
private static String getInvokingFileName(int offset)
{
return getCurrentFileName(offset + 1); // re-uses getCurrentFileName() with desired index
}
public static String getCurrentMethodNameFqn()
{
return getCurrentMethodNameFqn(1);
}
private static String getCurrentMethodNameFqn(int offset)
{
String currentClassName = getCurrentClassName(offset + 1);
String currentMethodName = getCurrentMethodName(offset + 1);
return currentClassName + "." + currentMethodName ;
}
public static String getCurrentFileNameFqn()
{
String CurrentMethodNameFqn = getCurrentMethodNameFqn(1);
String currentFileName = getCurrentFileName(1);
return CurrentMethodNameFqn + "(" + currentFileName + ")";
}
public static String getInvokingMethodNameFqn()
{
return getInvokingMethodNameFqn(2);
}
private static String getInvokingMethodNameFqn(int offset)
{
String invokingClassName = getInvokingClassName(offset + 1);
String invokingMethodName = getInvokingMethodName(offset + 1);
return invokingClassName + "." + invokingMethodName;
}
public static String getInvokingFileNameFqn()
{
String invokingMethodNameFqn = getInvokingMethodNameFqn(2);
String invokingFileName = getInvokingFileName(2);
return invokingMethodNameFqn + "(" + invokingFileName + ")";
}
}
To get the name of the method that called the current method you can use:
new Exception("is not thrown").getStackTrace()[1].getMethodName()
This works on my MacBook as well as on my Android phone I also tried:
Thread.currentThread().getStackTrace()[1]
but Android will return "getStackTrace" I could fix this for Android with
Thread.currentThread().getStackTrace()[2]
but then I get the wrong answer on my MacBook
Util.java:
public static String getCurrentClassAndMethodNames() {
final StackTraceElement e = Thread.currentThread().getStackTrace()[2];
final String s = e.getClassName();
return s.substring(s.lastIndexOf('.') + 1, s.length()) + "." + e.getMethodName();
}
SomeClass.java:
public class SomeClass {
public static void main(String[] args) {
System.out.println(Util.getCurrentClassAndMethodNames()); // output: SomeClass.main
}
}
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
An alternative method is to create, but not throw, an Exception, and use that object from which to get the stack trace data, since the enclosing method will typically be at index 0 - as long as the JVM stores that information, as others have mentioned above. This not the cheapest method, however. From Throwable.getStackTrace() (this has been the same since Java 5 at least): The zeroth element of the array (assuming the array's length is non-zero) represents the top of the stack, which is the last method invocation in the sequence. Typically, this is the point at which this throwable was created and thrown. The snippet below assumes the class is non-static (because of getClass()), but that's an aside.
System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
I've got solution using this (In Android)
/**
* @param className fully qualified className
* <br/>
* <code>YourClassName.class.getName();</code>
* <br/><br/>
* @param classSimpleName simpleClassName
* <br/>
* <code>YourClassName.class.getSimpleName();</code>
* <br/><br/>
*/
public static void getStackTrace(final String className, final String classSimpleName) {
final StackTraceElement[] steArray = Thread.currentThread().getStackTrace();
int index = 0;
for (StackTraceElement ste : steArray) {
if (ste.getClassName().equals(className)) {
break;
}
index++;
}
if (index >= steArray.length) {
// Little Hacky
Log.w(classSimpleName, Arrays.toString(new String[]{steArray[3].getMethodName(), String.valueOf(steArray[3].getLineNumber())}));
} else {
// Legitimate
Log.w(classSimpleName, Arrays.toString(new String[]{steArray[index].getMethodName(), String.valueOf(steArray[index].getLineNumber())}));
}
}
I don't know what is the intention behind getting the currently executed method's name, but if that's just for debugging purpose, then logging frameworks like "logback" can help here. For example, in logback, all you need to do is to use the pattern "%M" in your logging configuration. However, this should be used with caution as this may degrade performance.
Just in case the method which name you want to know is a junit test method, then you can use junit TestName rule: https://stackoverflow.com/a/1426730/3076107
This can be done using StackWalker since Java 9.
public static String getCurrentMethodName() {
return StackWalker.getInstance()
.walk(s -> s.skip(1).findFirst())
.get()
.getMethodName();
}
public static String getCallerMethodName() {
return StackWalker.getInstance()
.walk(s -> s.skip(2).findFirst())
.get()
.getMethodName();
}
StackWalker is designed to be lazy, so it's likely to be more efficient than, say, Thread.getStackTrace which eagerly creates an array for the entire callstack. Also see the JEP for more information.
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
What's wrong with this approach:
class Example {
FileOutputStream fileOutputStream;
public Example() {
//System.out.println("Example.Example()");
debug("Example.Example()",false); // toggle
try {
fileOutputStream = new FileOutputStream("debug.txt");
} catch (Exception exception) {
debug(exception + Calendar.getInstance().getTime());
}
}
private boolean was911AnInsideJob() {
System.out.println("Example.was911AnInsideJob()");
return true;
}
public boolean shouldGWBushBeImpeached(){
System.out.println("Example.shouldGWBushBeImpeached()");
return true;
}
public void setPunishment(int yearsInJail){
debug("Server.setPunishment(int yearsInJail=" + yearsInJail + ")",true);
}
}
And before people go crazy about using System.out.println(...) you could always, and should, create some method so that output can be redirected, e.g:
private void debug (Object object) {
debug(object,true);
}
private void dedub(Object object, boolean debug) {
if (debug) {
System.out.println(object);
// you can also write to a file but make sure the output stream
// ISN'T opened every time debug(Object object) is called
fileOutputStream.write(object.toString().getBytes());
}
}
原文出處:java - Getting the name of the currently executing method - Stack Overflow
|
|
冷日 (冷日) |
發表時間:2019/4/2 6:16 |
- Webmaster
- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]How to Get a Name of a Method Being Executed?
How to Get a Name of a Method Being Executed?Last modified: August 18, 2018 1. OverviewSometimes we need to know the name of the current Java method being executed. This quick article presents a couple of simple ways of getting hold of the method name in the current execution stack. 2. Using getEnclosingMethodWe can find the name of the method being executed by using the getEnclosingMethod() API:
public void givenObject_whenGetEnclosingMethod_thenFindMethod() { String methodName = new Object() {} .getClass() .getEnclosingMethod() .getName(); assertEquals("givenObject_whenGetEnclosingMethod_thenFindMethod", methodName); } 3. Using Throwable Stack TraceUsing a Throwable stack trace gives us stack trace with the method currently being executed:
public void givenThrowable_whenGetStacktrace_thenFindMethod() { StackTraceElement[] stackTrace = new Throwable().getStackTrace(); assertEquals( "givenThrowable_whenGetStacktrace_thenFindMethod", stackTrace[0].getMethodName()); } 4. Using Thread Stack Trace
Also, the stack trace of a current thread (since JDK 1.5) usually includes the name of the method that is being executed:
public void givenCurrentThread_whenGetStackTrace_thenFindMethod() { StackTraceElement[] stackTrace = Thread.currentThread() .getStackTrace(); assertEquals( "givenCurrentThread_whenGetStackTrace_thenFindMethod", stackTrace[1].getMethodName()); }
However, we need to remember that this solution has one significant drawback. Some virtual machines may skip one or more stack frames. Although this is not common, we should be aware that this can happen. 5. ConclusionIn this tutorial, we have presented some examples how to get the name of the currently executed method. Examples are based on stack traces and the getEnclosingMethod(). As always, you can check out the examples provided in this article over on GitHub. 原文出處:How to Get a Name of a Method Being Executed? | Baeldung
|
|
|
冷日 (冷日) |
發表時間:2019/4/2 6:20 |
- Webmaster
- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [分享]冷日取得 ClassName & MethodName 的方案
- 結論:
冷日最後是這樣取得 Class Name 和 Method Name:
String className2Show = new Object(){}.getClass().getName();
String methodName2Show = new Object(){}.getClass().getEnclosingMethod().getName();
雖然效能和資源問題肯定蠻嚴重,但在 Servlet 或是 Public Static 的 class 裡面也都可以順利運作,就只好先這樣搞了!
註:冷日目前一定需要 Class Name 和 Method Name 的時機都是要 Log 輸出,所以使用率有限,正式環境也不會亂 Log,所以影響似乎還行!
|
|
冷日 (冷日) |
發表時間:2019/4/3 15:26 |
- Webmaster
- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]How to get the caller class in Java
- How to get the caller class in Java [duplicate]
I want to get the caller class of the method, i.e. In the method bar, I need to get the class name foo, and I found this method:
Class clazz = sun.reflect.Reflection.getCallerClass(1);
However, even though getCallerClass is public, when I try to call it Eclipse says:
You can generate a stack trace and use the informations in the StackTraceElements. For example an utility class can return you the calling class name :
public class KDebug {
public static String getCallerClassName() {
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
for (int i=1; i<stElements.length; i++) {
StackTraceElement ste = stElements[i];
if (!ste.getClassName().equals(KDebug.class.getName()) && ste.getClassName().indexOf("java.lang.Thread")!=0) {
return ste.getClassName();
}
}
return null;
}
}
If you call KDebug.getCallerClassName() from bar(), you'll get "foo". Now supposing you want to know the class of the method calling bar (which is more interesting and maybe what you really wanted). You could use this method :
public static String getCallerCallerClassName() {
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
String callerClassName = null;
for (int i=1; i<stElements.length; i++) {
StackTraceElement ste = stElements[i];
if (!ste.getClassName().equals(KDebug.class.getName())&& ste.getClassName().indexOf("java.lang.Thread")!=0) {
if (callerClassName==null) {
callerClassName = ste.getClassName();
} else if (!callerClassName.equals(ste.getClassName())) {
return ste.getClassName();
}
}
}
return null;
}
Is that for debugging ? If not, there may be a better solution to your problem.
To get caller/ callee class name use below code, it works fine for me.
String callerClassName = new Exception().getStackTrace()[1].getClassName();
String calleeClassName = new Exception().getStackTrace()[0].getClassName();
This Highly depends what you are looking for... But this should get the class and method that called this method within this object directly.
index 0 = Thread
index 1 = this
index 2 = direct caller, can be self.
index 3 ... n = classes and methods that called each other to get to the index 2 and below.
For Class/Method/File name:
Thread.currentThread().getStackTrace()[2].getClassName();
Thread.currentThread().getStackTrace()[2].getMethodName();
Thread.currentThread().getStackTrace()[2].getFileName();
For Class:
Class.forName(Thread.currentThread().getStackTrace()[2].getClassName())
FYI: Class.forName() throws a ClassNotFoundException which is NOT runtime. Youll need try catch. Also, if you are looking to ignore the calls within the class itself, you have to add some looping with logic to check for that particular thing. Something like... (I have not tested this piece of code so beware)
StackTraceElement[] stes = Thread.currentThread().getStackTrace();
for(int i=2;i<stes.length;i++)
if(!stes[i].getClassName().equals(this.getClass().getName()))
return stes[i].getClassName();
Just a thought....
By creating a utility class which extends SecurityManager, you can access this.
public class CallingClass extends SecurityManager {
public static final CallingClass INSTANCE = new CallingClass();
public Class[] getCallingClasses() {
return getClassContext();
}
}
Use CallingClass.INSTANCE.getCallingClasses() to retrieve the calling classes. There is also a small library (disclaimer: mine) WhoCalled which exposes this information. It uses Reflection.getCallerClass when available, else falls back to SecurityManager.
I know this is an old question but I believed the asker wanted the class, not the class name. I wrote a little method that will get the actual class. It is sort of cheaty and may not always work, but sometimes when you need the actual class, you will have to use this method...
/**
* Get the caller class.
* @param level The level of the caller class.
* For example: If you are calling this class inside a method and you want to get the caller class of that method,
* you would use level 2. If you want the caller of that class, you would use level 3.
*
* Usually level 2 is the one you want.
* @return The caller class.
* @throws ClassNotFoundException We failed to find the caller class.
*/
public static Class getCallerClass(int level) throws ClassNotFoundException {
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
String rawFQN = stElements[level+1].toString().split("\\(")[0];
return Class.forName(rawFQN.substring(0, rawFQN.lastIndexOf('.')));
}
This is the most efficient way to get just the callers class. Other approaches take an entire stack dump and only give you the class name. However, this class in under sun.* which is really for internal use. This means that it may not work on other Java platforms or even other Java versions. You have to decide whether this is a problem or not.
The error message the OP is encountering is just an Eclipse feature. If you are willing to tie your code to a specific maker (and even version) of the JVM, you can effectively use method sun.reflect.Reflection.getCallerClass(). You can then compile the code outside of Eclipse or configure it not to consider this diagnostic an error. The worse Eclipse configuration is to disable all occurrences of the error by: Project Properties / Java Compiler / Errors/Warnings / Enable project specific settings set to checked / Deprecated and restrited API / Forbidden reference (access rules) set to Warning or Ignore. The better Eclipse configuration is to disable a specific occurrence of the error by: Project Properties / Java Build Path / Libraries / JRE System Library expand / Access rules: select / Edit... / Add... / Resolution: set to Discouraged or Accessible / Rule Pattern set to sun/reflect/Reflection.
i am using the following method to get the caller for a specific class from the stacktrace:
package test.log;
public class CallerClassTest {
public static void main(final String[] args) {
final Caller caller = new Caller(new Callee());
caller.execute();
}
private static class Caller {
private final Callee c;
public Caller(final Callee c) {
this.c = c;
}
void execute() {
c.call();
}
}
static class Callee {
void call() {
System.out.println(getCallerClassName(this.getClass()));
}
}
/**
* Searches the current threads stacktrace for the class that called the given class. Returns {@code null} if the
* calling class could not be found.
*
* @param clazz
* the class that has been called
*
* @return the caller that called the class or {@code null}
*/
public static String getCallerClassName(final Class<?> clazz) {
final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
final String className = clazz.getName();
boolean classFound = false;
for (int i = 1; i < stackTrace.length; i++) {
final StackTraceElement element = stackTrace[i];
final String callerClassName = element.getClassName();
// check if class name is the requested class
if (callerClassName.equals(className)) classFound = true;
else if (classFound) return callerClassName;
}
return null;
}
}
Since I currently have the same problem here is what I do: I prefer com.sun.Reflection instead of stackTrace since a stack trace is only producing the name not the class (including the classloader) itself. The method is deprecated but still around in Java 8 SDK. // Method descriptor #124 (I)Ljava/lang/Class; (deprecated) // Signature: (I)Ljava/lang/Class<*>; @java.lang.Deprecated public static native java.lang.Class getCallerClass(int arg0); The method without int argument is not deprecated // Method descriptor #122 ()Ljava/lang/Class; // Signature: ()Ljava/lang/Class<*>; @sun.reflect.CallerSensitive public static native java.lang.Class getCallerClass(); Since I have to be platform independent bla bla including Security Restrictions, I just create a flexible method: Check if com.sun.Reflection is available (security exceptions disable this mechanism) If 1 is yes then get the method with int or no int argument. If 2 is yes call it. If 3. was never reached, I use the stack trace to return the name. I use a special result object that contains either the class or the string and this object tells exactly what it is and why. [Summary] I use stacktrace for backup and to bypass eclipse compiler warnings I use reflections. Works very good. Keeps the code clean, works like a charm and also states the problems involved correctly. I use this for quite a long time and today I searched a related question so
Find below a simple example illustrating how to get class and method names.
public static void main(String args[])
{
callMe();
}
void callMe()
{
try
{
throw new Exception("Who called me?");
}
catch( Exception e )
{
System.out.println( "I was called by " +
e.getStackTrace()[1].getClassName() +
"." +
e.getStackTrace()[1].getMethodName() +
"()!" );
}
}
e has getClassName(), getFileName(), getLineNumber() and getMethodName()...
原文出處:How to get the caller class in Java - Stack Overflow
|
|
|