2011-04-20 14 views
24

En contextos estáticos, ¿cómo es que no puede llamar a una versión estática de getClass() (en lugar de tener que usar my.package.name.MyClassName.class)?¿Por qué no está disponible getClass() como método estático?

¿No es el compilador lo suficientemente inteligente como para determinar cuándo usar métodos de objetos + cuándo usar métodos estáticos?


para mayor claridad NOTA:

no estoy diciendo que un static getClass() debe usarse en lugar del método no estático getClass() (que es bastante obvio - si SpecialFoo es una subclase de Foo , entonces el getClass() de un Foo podría devolver Foo.class o SpecialFoo.class o algo más y debe determinarse en tiempo de ejecución).

Estoy diciendo que me pregunto por qué no hay dos versiones de getClass(), que es un método estático que sólo se aplica en un contexto estático, y el método no estático normal getClass(). Si no es posible, entonces no es posible, y esa es la respuesta. Si es posible, pero no se ha hecho, entonces es una opción histórica, y tal vez haya una buena razón para ello. Eso es lo que me gustaría saber.

Sería muy bueno para declarar

final static Logger logger = LoggerFactory.getLogger(getClass()); 

en lugar de

final static Logger logger = LoggerFactory.getLogger(my.package.name.MyClass.class); 

en el que el primero podría ser copiado textualmente de una clase a la siguiente, mientras que el segundo se requiere para copiar el nombre de la clase en cada archivo.

+0

Buena pregunta. Groovy permite 'this' hacer referencia a la * clase actual * en un contexto estático ;-) –

+0

Probablemente porque en el tiempo de ejecución los métodos estáticos no tienen ningún contexto de clase. – halfdan

+0

Correcto, pero desde el punto de vista del compilador, cuando llamas a un método estático 'foo()', sabe que 'foo()' se refiere al método estático. Supongo que lo que estoy preguntando es por qué no hay un método estático 'getClass()' que devuelve el campo '.class' estático incorporado. –

Respuesta

3

Si nada más, porque no es legal tener tanto una versión de un método (y no staticstatic probablemente porque es legal, si desalentado, para llamar a un método en un static no static contexto).

También me parece que este método, aunque útil en el contexto de la definición de un registrador o lo que sea, podría ser confuso en otros contextos, como cuando se llama desde un método de instancia.

7

Cada objeto es una instancia de una clase en Java y ninguna clase puede ser una instancia de otra clase. Es por eso que getClass() no es estático ya que solo tiene sentido en el contexto de un objeto: estás tratando de encontrar para un objeto en qué clase es una instancia de. Si se trata de una función estática, se le puede llamar fuera de un objeto - pero no tiene sentido escribir

String.getClass() 

porque ya se sabe que está "pidiendo" la clase String!

+0

correcta - Lo entendí al escribir mi pregunta. Ver las ediciones –

+1

no agrega ningún valor para el uso * fuera de la clase, pero agrega valor para el uso * dentro * de la clase. –

2

Porque si getClass() fuera estático, su código debería definirse en una clase, probablemente Object. Allí, no puede determinar la clase de llamadores y no hay una instancia de objeto que la llame.

Editar:

No se trata del nombre; podría estar muy bien getClass2(). Estoy diciendo que si se define un método estático, no se puede saber la clase que lo llama:

public class Object { 

    public static Class<?> getClass2() { 
     return ...? 
    } 

} 
+2

Hay un truco similar en el trabajo con 'Enum.getValues ​​()': es un método estático que está disponible en cada 'enum' (también conocido como" cada subclase de 'java.lang.Enum'). Algo similar sería pensable aquí. –

+0

No estoy diciendo que debería ser * en su lugar * del método no estático 'getClass()' (eso es obvio, si 'SpecialFoo' es una subclase de' Foo', luego 'getClass()' de un 'Foo' podría devolver' Foo.class' o 'SpecialFoo.class' u otra cosa). Estoy diciendo que en un contexto estático por qué no hay una segunda versión * estática * de getClass(). –

+1

@Jason S - No puede declarar dos métodos que se diferencian solo en la palabra clave estática :) –

5

getClass() proporciona una funcionalidad diferente que el .class estática. Se usa para obtener la clase de tiempo de ejecución de la instancia a la que se llama.

Object o = new String(); 
o.getClass() // returns Class<String>  
Object.class // returns Class<Object> 
+0

sí, por supuesto, lo siento, no me hice claro en mi pregunta original. ver mis ediciones –

+1

Me parece que alguien más ya ha dado esta respuesta, pero lo más probable es que no pueda sobrecargar los nombres de los métodos solo con la palabra clave estática. Necesitarías un segundo método con un nombre o parámetros diferentes. Supongo que pensaron que sería innecesario y/o confuso agregar un segundo método getClass. Supongo que pensaron que nadie tendría un problema simplemente usando la propiedad static .class. – Jberg

1

No sería un método estático getClass() devolver la clase de objeto a la clase de la variable que contiene el objeto es de? Eso cambiaría la semántica de getClass(). Ejemplo:

Interface foo = new FooImpl(); 
foo.getClass(); // returns Class<FooImpl> because the runtime type is FooImpl. 
       // If getClass() was static, it would return Class<Foo>. 
1

Además de otras respuestas (que explican por qué no podemos hacer un método estático con la misma firma que el método 'getClass()' no estático), uno se preguntaría si sería posible tener, digamos un static Class getStaticClass() de modo que, por ejemplo, String.getStaticClass() sería equivalente a String.class. Pero, de nuevo, este método no podría ser un método "normal" ¿Dónde se definiría? en el objeto? Entonces, ¿cómo sabe este único método qué devolver (String.class o Object.class) cuando se llamó como String.getStaticClass() o Object.getStaticClass()? ¿Lo decidiría en tiempo de ejecución? De ninguna manera.

Un método estático no tiene sentido porque String.class es conocido (resuelto) en tiempo de compilación. El método no tiene nada razonable que hacer en tiempo de ejecución; tendrías que hacer un poco de magia de compilación para que el resultado de esa llamada al método se resuelva en tiempo de compilación.

2

Puede implementar uno usted mismo. Obtén la stacktrace y encuentra la clase de llamante.

En realidad, el registrador podría lib implementado que sí

static Logger logger = LoggerFactory.getLogger(); // auto detect caller class 
25

Se puede utilizar esta expresión idiomática

Class<?> cl=new Object(){}.getClass().getEnclosingClass(); 

Por ejemplo:

static class Bar { 
    public static void main(String[] args) { 
     Class<?> cl=new Object(){}.getClass().getEnclosingClass(); 
     System.out.println(cl==Bar.class); //will print true 
    } 
} 
+0

+1 ... ¡interesante! –

+0

Siempre obtengo nulo usando este método. ¿Depende de que Bar sea una clase estática? –

+1

Es posible que haya escrito 'new Object(). GetClass(). GetEnclosingClass()'. La forma correcta es usar 'new Object() {}', que define y crea una clase anónima basada en 'Object'. – wdscxsj

Cuestiones relacionadas