【问题标题】:How can I get the Class object in a static method without using the class name?如何在不使用类名的情况下以静态方法获取 Class 对象?
【发布时间】:2012-12-31 23:49:37
【问题描述】:

我有

public class A {
    static X s_x = new X(A.class);
}

public class B {
    static X s_x = new X(B.class);
}

对于许多没有任何特殊关系或共性的类等等。我真正希望我能做的是在超类中初始化 s_x,但使用后代类特定的代码;这是不可能的,因为静态代码不可覆盖。所以,我想至少让我的复制粘贴更容易。我想要一个计算为 Class 对象的魔术表达式,即写:

    static X s_x = new X(/* magic expression here */);

无论我在哪个类中声明我的 X,魔术表达式都是相同的,但与上面的示例相同。次优选择是达到相同效果的静态方法。

注意事项:

  • 如果可能的话,Java 6。
  • 这个问题(不一定)与日志记录有关...

【问题讨论】:

  • A 类和B 类有某种形式的关系吗?
  • @BuhakeSindi:没有。编辑以使这一点更清楚。
  • 你可以使用getClass()方法。
  • @RohitKumar.. 不,它是静态引用变量。
  • 是关于静态日志变量的吗?

标签: java class inheritance reflection static


【解决方案1】:

我曾经也有这个奇怪的要求,我试图搜索但没有找到任何东西,所以我想答案是不可能的。

但是我被告知要重新考虑我的方法,当我尝试时,我想出了相同的解决方案,而没有这个奇怪的要求。所以请重新考虑你的方法。我相信你能像我一样解决它。另外,如果您可以发布您要解决的问题/场景,也许我可以提供帮助。

【讨论】:

  • 您实际上是对的,您的回答不仅启发了我自己提供答案,而且还让让我使用此代码的人尝试另辟蹊径。
【解决方案2】:

我认为唯一的解决方案是从当前堆栈跟踪中提取类名(请参阅Thread.getStackTrace()),这会将其作为String 提供给您,您可以从中获取Class 对象使用Class.forName(String),但这比你现在的做法丑多了。

【讨论】:

    【解决方案3】:

    在 Java 7 中,您可以为此使用 java.lang.invoke.MethodHandles 类:

    Class c = MethodHandle.lookup().lookupClass()
    

    您可能会收到关于使用原始类型而不是参数化版本Class<X> 的警告,但如果不自己恢复对类名进行硬编码,我看不出如何避免这种情况。

    【讨论】:

      【解决方案4】:

      在HotSpot/OpenJDK中你可以使用

       Class c = Reflection.getCallerClass(1)
      

      注意:这是一个内部 API,可能不适用于所有 JVM。

      【讨论】:

        【解决方案5】:

        您可以这样做,但需要重新考虑您的方法:

        试试这个:

        class X
        {
        
           public X(String cName)
           {
             try
             {
               Class.forName(cName);
              }catch(ClassNotFoundException cne)
               {}
           }
        }
        
        public class Test
        {
            static X x1 = new X(Thread.currentThread().getStackTrace()[1].getClassName());
        }
        

        【讨论】:

          【解决方案6】:

          如果你想创建一个日志对象,你可以使用lombok 为你注入一个日志对象。 页面示例:

          @Log
          public class LogExample {
          
            public static void main(String... args) {
              log.error("Something's wrong here");
            }
          }
          

          【讨论】:

            【解决方案7】:

            这里的一些答案有解决方案的想法,但不是我需要的代码 sn-p。所以在这里,在任何 JVM 上工作:

            static X s_x = new X(getClassStatic());
            
            public static Class<?> getClassStatic() {
                try {
                    // we're using the third highest stack element, since the
                    // first highest is the getStackTrace() method, followed by this method itself. We
                    // want the calling code's class.
                    String name = Thread.currentThread().getStackTrace()[2].getClassName();
                    return Class.forName(name);
                } catch (ClassNotFoundException e) {
                    // shouldn't be able to get here...
                    return null;
                }
            }
            

            或者,对于选定的 JVM,按照 Peter Lawrey 的建议:

            static X s_x = new X(getCallerClass(1));
            

            【讨论】:

              【解决方案8】:

              这是一个应该在 Java 5+ JVM 中工作并且不会向您的代码添加任何额外导入的单行代码:

              new Object(){}.getClass().getEnclosingClass()
              

              它创建一个匿名内部类,获取它的Class 对象,然后获取它的封闭类实例,它应该是你的类。例如:

              public class HelloClass {
                  static final Class<?> THIS_CLASS = new Object(){}.getClass().getEnclosingClass();
              
                  public static void main(String[] args) {
                      System.out.println(THIS_CLASS); // prints "class HelloClass"
                  }
              }
              

              根据您的问题:

              static X s_x = new X(new Object(){}.getClass().getEnclosingClass());
              

              【讨论】:

              • 很好......看起来这可以在编译时进行优化,而不是查看堆栈跟踪。但是,您不能真正将其放入方法中,并且new() 非常丑陋。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-08-05
              • 2016-10-03
              • 2016-08-13
              • 2018-10-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多