场景
静态方法,必然是总集办法。
比如工厂类?公共的静态方法?比如打印日志什么的。
静态方法共有的一个特性,那就是提供方法给别人调用,且十分方便(抛开静态的开销的话)。
但是,唯一的弊端就是不由自主。因为调用的地方很多,静态方法很难做到自己的上下文管理。
比如打印日志,打在外面吧,没有详细信息,打在内部吧,又不知道谁调用了。
逻辑的具体实现不是问题了,但是,究竟是谁用了,谁动了我的奶罩。
stack
数据结构都知道堆栈,程序执行都离不开堆栈。
如果说我们很熟悉堆栈,那像是无稽之谈,不过如果经常调bug,那你可以说你很常接触堆栈了。
为什么,因为exception啊
为什么要说堆栈,为什么要炫耀着刺眼的血红?
因为真有用啊。
全部的Exception的顶层,那必然是Object(废话),但是,从有分类开始,它的始祖是Throwable。
这里面就有堆栈信息,为了抛出异常,它是已经记录堆栈了的,这个可以为我所用。
测试
first
package com.godme.stack;
public class First {
public static void test(){
StackTraceElement[] stack = new Throwable().getStackTrace();
StringBuffer sb = new StringBuffer();
for(StackTraceElement element:stack){
sb.delete(0, sb.length());
sb.append("file\t:\t" + element.getFileName() + "\n");
sb.append("class\t:\t" + element.getClassName() + "\n");
sb.append("line\t:\t" + element.getLineNumber() + "\n");
sb.append("method\t:\t" + element.getMethodName());
System.out.println(sb.toString());
System.out.println("========================================");
}
}
}
second
package com.godme.stack;
public class Second {
public static void test(){
First.test();
}
}
third
package com.godme.stack;
public class Third {
public static void test(){
Second.test();
}
}
fourth
package com.godme.stack;
public class Fourth {
public static void test(){
Third.test();
}
}
fifth
package com.godme.stack;
public class Fifth {
public static void test(){
Fourth.test();
}
}
好吧,我很蛋疼,接下来是主菜
package com.godme.stack;
public class Main {
public static void main(String[] args) {
Fifth.test();
}
}
执行结果如下
file : First.java
class : com.godme.stack.First
line : 5
method : test
========================================
file : Second.java
class : com.godme.stack.Second
line : 5
method : test
========================================
file : Third.java
class : com.godme.stack.Third
line : 5
method : test
========================================
file : Fourth.java
class : com.godme.stack.Fourth
line : 5
method : test
========================================
file : Fifth.java
class : com.godme.stack.Fifth
line : 5
method : test
========================================
file : Main.java
class : com.godme.stack.Main
line : 5
method : main
========================================
从下往上看,可以观察到java的压栈顺序。
分别是从调用顺序进行压栈:main>5>4>3>2>1
不过,Throwable记录的好像是出栈顺序,因为先进后出,所以看起来first的索引还会在前。
回到最初的想法:想知道谁在调用了静态方法。
不就是静态方法的上一个压栈么。方法得到执行,必然在出栈顺序的首位,索引为0。
那调用该方法的"东西",就在index=1的栈顶老二的位置了。
复验
first
package com.godme.stack;
public class First {
public static void test(){
StackTraceElement stack = new Throwable().getStackTrace()[1];
StringBuffer sb = new StringBuffer();
sb.delete(0, sb.length());
sb.append("file\t:\t" + stack.getFileName() + "\n");
sb.append("class\t:\t" + stack.getClassName() + "\n");
sb.append("line\t:\t" + stack.getLineNumber() + "\n");
sb.append("method\t:\t" + stack.getMethodName());
System.out.println(sb.toString());
System.out.println("=================================");
}
}
second
package com.godme.stack;
public class Second {
public static void test(){
First.test();
}
}
third
package com.godme.stack;
public class Third {
public static void test(){
First.test();
}
}
fourth
package com.godme.stack;
public class Fourth {
public static void test(){
First.test();
}
}
fifth
package com.godme.stack;
public class Fifth {
public static void test(){
First.test();
}
}
嗯,启动
package com.godme.stack;
public class Main {
public static void main(String[] args) {
First.test();
Second.test();
Third.test();
Fourth.test();
Fifth.test();
}
}
结果
file : Main.java
class : com.godme.stack.Main
line : 5
method : main
=================================
file : Second.java
class : com.godme.stack.Second
line : 5
method : test
=================================
file : Third.java
class : com.godme.stack.Third
line : 5
method : test
=================================
file : Fourth.java
class : com.godme.stack.Fourth
line : 5
method : test
=================================
file : Fifth.java
class : com.godme.stack.Fifth
line : 5
method : test
=================================
嗯,和理论一致了,这样就能够知道究竟是谁动了我的XX了。
有必要的话,可以研究一下StackTraceElement,还想有啥操作的话,不是可以getClass么。
反正一路上的家伙都记录在册,想做什么,自己开心啦。
简单一句即可完成
package com.godme.stack;
public class First {
public static void test(){
StackTraceElement stack = new Throwable().getStackTrace()[1];
StringBuffer sb = new StringBuffer();
sb.delete(0, sb.length());
sb.append("file\t:\t" + stack.getFileName() + "\n");
sb.append("class\t:\t" + stack.getClassName() + "\n");
sb.append("line\t:\t" + stack.getLineNumber() + "\n");
sb.append("method\t:\t" + stack.getMethodName());
System.out.println(sb.toString());
System.out.println("=================================");
}
}