解决方案 »

  1.   

    怎么说呢~你这本身就是在调用People已经实现好的返回People这个类的类名的方法,如果你想让Teacher返回Teacher的类名,要么你覆盖父类实现的方法,要么你用Teacher.class.getName();应该就这两中方法了!
      

  2.   

    public class People {
    public static String getClassName(){
    return People.class.getName();
    }
    }
    为什么不是这样的?
      

  3.   

    楼主是挑战常规啊,类方法一般是针对类来定义的,这个和子类没有关系,如果想要在客户端通过类方法调用,获取类名,可以重写Teacer的类方法获取方法名,但如果楼主不想这么做的话,那就将传递Class类型的参数吧,但是这真的没有意义!个人想法,楼主可以参考。
      

  4.   

    实在要取,从堆栈中取吧.比如 :public static void getClassName() {
    StackTraceElement[] stacks = new Throwable().getStackTrace();

    for(StackTraceElement s : stacks){
    System.out.println(s.getClassName());
    }
    }判断s.getClassName()的值,去掉People这个名字,剩下那个就是Teacher了
      

  5.   

    String className = getClass().getName();其实是String className = this.getClass().getName();除非getClassName传一个参数class
      

  6.   

    之前有问过的,去看看这个帖子
    http://bbs.csdn.net/topics/390328961
      

  7.   


    我也想过从栈中去取,不过栈里面只能找到People的调用层次,根本没有Teacher的调用
      

  8.   


    主要我是ruby背景,静态方法里面无法用this让我有点手足无措吧。 就是没法判断静态方法的调用方是谁了。
      

  9.   

    你们都忽略了面向对象的特性了吧。继承是面向对象的特性。静态方法,静态变量,私有变量,私有方法根本不存在继承之说。类方法只是为这个方法找个容身之所罢了。虽然你的Teacher继承了这个People类但是静态方法根本就不存在继承。楼主不信的话把这个People的getClassName()复制到Teacher类中用多态的方式去调用
    People p=new Teacher();
    System.out.println(p.getClassName());
    看看它打印的还是不是原来的People
      

  10.   

    单从JAVA的语法上来看,此题无解如果从分析楼主的需求角度看,应该还是有办法可想的。楼主这样做想达到什么目的,不妨说出来讨论一下
      

  11.   

    public static String getClassName() {
    return new Object() {
    private String getName() {
    System.out.println(People.class);
    String className = getClass().getName();
    return className.substring(0, className.indexOf("$"));
    }
    }.getName();
    }
    写在people里面就默认使用了,没参数还真改不了
      

  12.   

    有些时候我也希望实现类似的行为,需求如下:class B extends A{}
    class C extends B{}
    class A{
     private static Map<Class<? extends A>,Set<? extends A>>map=new HashMap<>();
     //以下方法实现仅演示需求,可能有bug,不必深究
     /**
      * 初始化时将类型与实例分类存放在map中
      */
     public A(){
      Set<? extends A>set=A.map.get(this.getClass());
      if(set==null){
       set=new HashSet<>();
       A.map.put(this.getClass(),set);
      }
      set.add(this);
     }
     /**
      * 获取调用类型在map中储存的所有实例,如A类调用时获取所有的A的实例、B类则获取所有的B的实例
      */
     public static<T extends A> Set<T>getInstances(){
            StackTraceElement[] stacks = new Throwable().getStackTrace();
            Class<T>lastCla=A.class;
            for(StackTraceElement s : stacks){
                if(s instanceof A){
                 lastCla=(Class<T>)s;
                }
            }
            return A.map.get(lastCla);
     }
     @Override
     public String toString(){
      return this.getClass().getClassName();
     }
     public static void main(String[]args){
      new A();
      new B();
      new C();
      System.out.println(C.getInstances());//应该输出[C]
     }
    }
      

  13.   

    抱歉,写错了,s instanceof A改为通过s.getSuperclass()循环判断是A是否是s的超类,代码就不写了,你懂得
      

  14.   

    这回答真是无语抡笔...回正题,从堆栈找静态方法的实际调用类在jre7下测试似乎无效,测试代码如下:try {
    new SecurityManager(){
    public void print(){
    System.out.println(Arrays.asList(this.getClassContext()));
    }
    }.print();
    } catch (IllegalArgumentException
    | SecurityException e1) {
    e1.printStackTrace();
    }
    new Throwable().printStackTrace();以上代码打印结果都不包含实际调用类。就是说用Teacher调用方法打印出来的也只有People,8楼和10楼引用的例子是如何实现的呢?
      

  15.   

    public class Peple {
    public  void getObject(){
    // TODO Auto-generated method stub
    System.out.println(Peple.this);
    }

    }
    class Teacher extends Peple{ 
    public static void main(String[] args) {
    new Teacher().getObject();
    }
    } 改成这样试试把
      

  16.   


    Teacher的主方法可以放在Test类里
      

  17.   

    我觉得不可能做到,证明:Teacher.getClassName()访问的是静态代码段People.getClassName(),类名Teacher还是People是运行期特征,要动态获得只能通过this.getClass().getName() ,显然静态代码不能用this至于new Throwable().getStackTrace()[0].getClassName() 之类本质获得的还是编译期特征,如
    package script;public class Father { public void getClassNameDyn() {
    new Throwable().printStackTrace();
    System.out.println(this.getClass().getName());
    }}public class Child extends Father{}
    public class Test { 
        public static void main(String[] args) throws Exception { 
            new Child().getClassNameDyn(); 
        } 
    }
    的返回结果是:
    java.lang.Throwable
    at script.Father.getClassNameDyn(Father.java:32)
    at script.Test.main(Script.java:197)
    script.Child
    这里Father是编译期特征如果楼主只想实现单纯的这个需求,我看Teacher.class.getName()就行,你试着把class.getName()想象成一个不变的方法,否则只能传参数了
      

  18.   

    这个....需求是不能随便推翻的打印结果:
    com.test.People
    Test
    堆栈里也没有Teacher
      

  19.   

    我提供一个思路,就是比较绕:new Throwable().printStackTrace(); 的结果可得:java.lang.Throwable
    at com.test.People.getClassName(People.java:xxx1)
    at com.test.Test.main(Test.java:xxx2)硬要找printStackTrace的运行期特征,其实是可以的,就是读文件在Test.java:xxx2行通过正则表达式解析出那个Teacher
      

  20.   

    static方法中是没办法的,因为static方法的执行的时候可能只加载了class,但是对象并未产生,那么父类如何能知道他的儿子呢?就像儿子都还没怀上没出声,父亲怎么知道儿子是什么样呢?所以不要再纠结于此。
      

  21.   


    getClassName
    com.study.test.People
    main
    com.study.test.T
    测试结果,因为直接是调用的People的static方法,所以Teacher根本就不可能会有的
      

  22.   

    这个就是“静态方法继承”的问题么? 那个问题貌似有很多帖子,说清楚了的。
     lz的需求是什么么?
    我猜测,是有一大堆代码,其中有个 getClassName()方法一开始写成静态的了,结果后来发现实际运行中是需要根据不同的实例来给出结果,但是又一大堆代码已经完成,实在不想改了,是么?我有个建议供参考:把方法改成不是静态的。
       既然可能是运行时动态的,那我想代码里不会出现 Teacher.getClassName()这样的调用吧? 如果已经知道是Teacher类了,那就没必要调用了,所以很大可能代码里是 Teacher x; ... x.getClassName()这样的调用吧? 如果是这样的话,把getClassName改成非静态方法应该不会太影响已有的代码,用编译器跑一下就可以把需要修改的地方都找出来了;实际上,把代码写出来,假设有3个类,People,Teacher,Test,
    在Test中用Javap命令看字节码,你会看到类似
    Compiled from "TestMain.java"
    public class pkgname.staticinherit2.TestMain extends java.lang.Object

    const #16 = Method      #17.#19;        //  pkgname/staticinherit2/Teacher.getClassName:()Ljava/lang/String;
    const #17 = class       #18;    //  pkgname/staticinherit2/Teacher
    const #18 = Asciz       pkgname/staticinherit2/Teacher;
    const #19 = NameAndType #20:#21;//  getClassName:()Ljava/lang/String;
    const #20 = Asciz       getClassName;
    const #21 = Asciz       ()Ljava/lang/String;;

    public static void main(java.lang.String[]);
      Code:
       Stack=2, Locals=2, Args_size=1
       0:   invokestatic    #16; //Method pkgname/staticinherit2/Teacher.getClassName:()Ljava/lang/String;
       3:   astore_1
       4:   getstatic       #22; //Field java/lang/System.out:Ljava/io/PrintStream;
       7:   aload_1
       8:   invokevirtual   #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       11:  return
     
    在Teacher,class里你会看到类似
    Compiled from "TestMain.java"
    public class pkgname.staticinherit2.TestMain extends java.lang.Object
      SourceFile: "TestMain.java"
      minor version: 0
      major version: 46
      Constant pool:
    const #1 = class        #2;     //  pkgname/staticinherit2/TestMain
    const #2 = Asciz        pkgname/staticinherit2/TestMain;
    const #3 = class        #4;     //  java/lang/Object
    const #4 = Asciz        java/lang/Object;
    const #5 = Asciz        <init>;
    const #6 = Asciz        ()V;
    const #7 = Asciz        Code;
    const #8 = Method       #3.#9;  //  java/lang/Object."<init>":()V
    const #9 = NameAndType  #5:#6;//  "<init>":()V
    const #10 = Asciz       LineNumberTable;
    const #11 = Asciz       LocalVariableTable;
    const #12 = Asciz       this;
    const #13 = Asciz       Lpkgname/staticinherit2/TestMain;;
    const #14 = Asciz       main;
    const #15 = Asciz       ([Ljava/lang/String;)V;
    const #16 = Method      #17.#19;        //  pkgname/staticinherit2/Teacher.getClassName:()Ljava/lang/String;
    const #17 = class       #18;    //  pkgname/staticinherit2/Teacher
    const #18 = Asciz       pkgname/staticinherit2/Teacher;
    const #19 = NameAndType #20:#21;//  getClassName:()Ljava/lang/String;
    const #20 = Asciz       getClassName;
    const #21 = Asciz       ()Ljava/lang/String;;
    const #22 = Field       #23.#25;        //  java/lang/System.out:Ljava/io/PrintStream;
    const #23 = class       #24;    //  java/lang/System
    const #24 = Asciz       java/lang/System;
    const #25 = NameAndType #26:#27;//  out:Ljava/io/PrintStream;
    const #26 = Asciz       out;
    const #27 = Asciz       Ljava/io/PrintStream;;
    const #28 = Method      #29.#31;        //  java/io/PrintStream.println:(Ljava/lang/String;)V
    const #29 = class       #30;    //  java/io/PrintStream
    const #30 = Asciz       java/io/PrintStream;
    const #31 = NameAndType #32:#33;//  println:(Ljava/lang/String;)V
    const #32 = Asciz       println;
    const #33 = Asciz       (Ljava/lang/String;)V;
    const #34 = Asciz       args;
    const #35 = Asciz       [Ljava/lang/String;;
    const #36 = Asciz       result;
    const #37 = Asciz       Ljava/lang/String;;
    const #38 = Asciz       SourceFile;
    const #39 = Asciz       TestMain.java;{
    public pkgname.staticinherit2.TestMain();
      Code:
       Stack=1, Locals=1, Args_size=1
       0:   aload_0
       1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
       4:   return
      LineNumberTable:
       line 4: 0  LocalVariableTable:
       Start  Length  Slot  Name   Signature
       0      5      0    this       Lpkgname/staticinherit2/TestMain;
    public static void main(java.lang.String[]);
      Code:
       Stack=2, Locals=2, Args_size=1
       0:   invokestatic    #16; //Method pkgname/staticinherit2/Teacher.getClassName:()Ljava/lang/String;
       3:   astore_1
       4:   getstatic       #22; //Field java/lang/System.out:Ljava/io/PrintStream;
       7:   aload_1
       8:   invokevirtual   #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       11:  return
      LineNumberTable:
       line 13: 0
       line 14: 4
       line 15: 11  LocalVariableTable:
       Start  Length  Slot  Name   Signature
       0      12      0    args       [Ljava/lang/String;
       4      8      1    result       Ljava/lang/String;
    }
    D:\work\eclipse\ACP\WydLab\bin>javap -c -verbose pkgname.staticinherit2.Teacher
    Compiled from "Teacher.java"
    public class pkgname.staticinherit2.Teacher extends pkgname.staticinherit.People
      SourceFile: "Teacher.java"
      minor version: 0
      major version: 46
      Constant pool:
    const #1 = class        #2;     //  pkgname/staticinherit2/Teacher
    const #2 = Asciz        pkgname/staticinherit2/Teacher;
    const #3 = class        #4;     //  pkgname/staticinherit/People
    const #4 = Asciz        pkgname/staticinherit/People;
    const #5 = Asciz        <init>;
    const #6 = Asciz        ()V;
    const #7 = Asciz        Code;
    const #8 = Method       #3.#9;  //  pkgname/staticinherit/People."<init>":()V
    const #9 = NameAndType  #5:#6;//  "<init>":()V
    ......
    {
    public pkgname.staticinherit2.Teacher();
      Code:
       Stack=1, Locals=1, Args_size=1
       0:   aload_0
       1:   invokespecial   #8; //Method pkgname/staticinherit/People."<init>":()V
       4:   return
    .....也就是说,调用的地方“Test.class"里是有"Teacher"这个类的信息的,而Teacher这个类里(如果不覆盖父类的静态方法的话)是根本没有getClassName这个方法的,从Test.class的字节码中找到Teacher类,然后发现没有getClassName方法,然后向上找到父类的静态方法的整个过程,是JVM的字节码引擎处理的,纯java code是无法知道“getClassName"其实是从Teacher类开始找的,除非你的JVM引擎告诉你这些信息。