Why must I qualify a reference to class inside the class that it's defined in? For example:
public class Foo {
private static Logger log = LoggerFactory.getLogger(Foo.class);
}
Why can't I just call LoggerFactory.getLogger(class) since I'm already in the context of the Foo class?
The JLS defines
15.8.2. Class Literals
A class literal is an expression consisting of the name of a class, interface, array, or primitive type, or the pseudo-type void, followed by a '.' and the token class.
It wouldn't make the language ambiguous to allow class where an expression is expected to allow the syntax you describe, but it would involve overriding the keyword class to mean both
a kind of declaration
a reference to an instance of type Class.
The syntax you suggest might allow naming the class of an anonymous class, but getClass() would have the same meaning in anonymous classes.
Getting rid of two tokens (the unqualified class name and the .) doesn't provide much value, and it could cause confusion inside an inner class. For example, what is class inside a lambda expression?
Related
In the following example if I make a constructor of a class called example like so:
public class Example{
public Example(){
this.super();
}
}
The above will not work because javac Example.java informs about following compilation error:
Example.java:3: error: illegal qualifier; Object is not an inner class
this.super();
^
1 error
But shouldn't it work as instead of implicitly stating this by using super(), we are explicitly stating it by using this?
Although invoking a superclass constructor by calling super(args) looks like it’s a regular method call, that syntax is actually different from a typical method call and isn’t subject to the same rules. For example:
You can only use super(args) in a constructor.
You can only use super(args) as the first line of a constructor.
In that sense, it probably helps to think of this not as a method call, but simply as a way of telling Java what you want to do to initialize the superclass.
Because this isn’t a typical method call, the rules for regular method calls don’t apply to it. As a result, you can’t prefix it with this. to make the receiver object explicit. There’s no fundamental reason why the Java language designers couldn’t have made this syntax legal; they just chose not to do so.
The JLS, Section 8.8.7.1, controls the specifications for explicit constructor invocations. It is possible in the grammar to specify this.super().
Primary . [TypeArguments] super ( [ArgumentList] ) ;
And a "Primary" expression can be this. Therefore, this.super() is a legal expression according to the grammar of the Java language, but that's not enough. It's not legal according to the semantics of such an expression.
Qualified superclass constructor invocations begin with a Primary expression or an ExpressionName. They allow a subclass constructor to explicitly specify the newly created object's immediately enclosing instance with respect to the direct superclass (§8.1.3). This may be necessary when the superclass is an inner class.
The semantics indicate that here, this is attempting to indicate an enclosing instance, not the current object instance. The compiler error you get isn't the clearest, but here, this is attempting to reference the enclosing class of the superclass, but Object does not have an enclosing class.
public class J {
public J() {
this.super();
}
}
J.java:17: error: illegal qualifier; Object is not an inner class
this.super();
^
1 error
Let's attempt to use this as an enclosing instance. Class J has an inner class K, and Foo attempts to subclass J.K.
class J {
public J() { }
public class K {}
}
class Foo extends J.K {
public Foo() {
this.super();
}
}
The error now is:
J.java:21: error: cannot reference this before supertype constructor has been called
this.super();
^
1 error
I can only get it to work with a primary expression other than this.
class Foo extends J.K {
public Foo() {
new J().super();
}
}
A semantics error, not a grammar error, prevents you from using this.super().
In Java classes are initialized top down. So if you make a class that extends object, it calls object's constructor then it calls your class's.
This is also the reason you can't initialize any fields before calling super, your class hasn't been created yet. this doesn't refer to anything as the template of the object hasn't been constructed.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.5
More information
There are 2 ways to get a class's Class object.
Statically:
Class cls = Object.class;
From an instance:
Object ob = new Object();
Class cls = ob.getClass();
Now my question is getClass() is a method present in the Object class,
but what is .class? Is it a variable? If so then where is it defined in Java?
That's implemented internally and called a class literal which is handled by the JVM.
The Java Language Specification specifically mentions the term "token" for it.
So .class is more than a variable, to be frank it is not a variable at all. At a broader level you can consider it as a keyword or token.
https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.8.2
A class literal is an expression consisting of the name of a class, interface, array, or primitive type, or the pseudo-type void, followed by a '.' and the token class.
A class literal evaluates to the Class object for the named type (or for void) as defined by the defining class loader (§12.2) of the class of the current instance.
That information resides in the class 'file', although classes need not have a physical .class file in the file system. The JVM takes care of making it available from the class definition, as the other answer states.
See also:
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html
As per multiple articles in Java Interface and Class are completely different. Let me write an Interface.
package com.main.service;
public interface SomeService{
public void someMethod();
}
But why below code is allowed in Java?
com.main.service.SomeService.class;
I am using this code to get beans from Spring application context like below:-
SomeService someservice = applicationContext
.getBean(com.main.service.SomeService.class);
The .class syntax at the end of a type (com.main.service.SomeService.class; in this case) references the class literal, which is an object of type Class. You can use this on any Java type, be it a concrete class, abstract class or an interface.
As per the Javadoc from the link above:
Instances of the class Class represent classes and interfaces in a running Java application
This may be confusing if you're new, and are used to having the distinction between class and interface drummed into you, but simply speaking it's how the underlying system works (all classes and interfaces are compiled to bytecode class files.)
You commonly see the syntax used in dependency injection (or other uses where you need to pass the "type" of something around), as it's the easiest way of doing so.
A class literal is an expression consisting of the name of a class, interface, array, or primitive type, or the pseudo-type void, followed by a '.' and the token class.
ClassLiteral:
TypeName {[ ]} . class
NumericType {[ ]} . class
boolean {[ ]} . class
void . class
The type of C.class, where C is the name of a class, interface, or
array type, is Class.
A class literal evaluates to the Class object for the named type (or for void) as defined by the defining class loader of the class of the current instance.
You should look at the Java docs of the method that you are using:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html#getBean-java.lang.Class-
Importantly the javadoc states:
Return the bean instance that uniquely matches the given object type,
if any.
NoUniqueBeanDefinitionException - if more than one bean of the given
type was found
So if you have more that one beans extending the interface you will get exception.
In the package java.lang I see,
public final class Class<T> extends Object implements Serializable, GenericDeclaration, Type, AnnotatedElement
Where exactly is the 'class' (the word used after 'public final') defined so that it could be used to declare 'Class' (the name of the class in the above declaration)?
It's a Java keyword. Simple as that.
It's not "defined" anywhere....it's part of the language itself.
Keep in mind that this answer is in response to your question below where you are asking about the word class. Based on your subsequent comments to your question, you're not interested in the java specification's BNF style language formalism, so you're asking simply about the word:
Where exactly is the 'class' (the word used after 'public final') defined so that it could be used to declare 'Class' (the name of the class in the above declaration)?
It's a keyword defined in the Java Specification:
8.1. Class Declarations
NormalClassDeclaration: {ClassModifier} class Identifier
[TypeParameters] [Superclass] [Superinterfaces] ClassBody
There are two things in Java by name class.
1) (what you mentioned above) is a class declaration (itself) - as in Javadocs
class MyClass {
// field, constructor, and
// method declarations
}
2) We have a special literal by same name 'class' as well, and as I just found - these two are different things. First is keyword, second is a literal.
class literal ...from Javadoc
Finally, there's also a special kind of literal called a class literal, formed by taking a type name and appending ".class"; for example, String.class. This refers to the object (of type Class) that represents the type itself.
Consider sample code below
public class Test {
public static void main(String args[]) {
Test t = new Test();
Class c2 = Test.class;
System.out.println(c2);
}
}
Test.class statically evaluates and returns compile time Class object. Looking at the Test.class syntax it looks like the variable class is of type java.lang.Class and is static and public. My question is where is this variable defined? It is not present in Test class (because I don't declare it) neither it is in the java.lang.Object class.
I saw an analogous method public final native Class<?> getClass();. This is present in java.lang.Object and is a native java method. This method returns the runtime Class of an object.
So my question is where is this public & static class variable defined?(Please correct me if I have mistaken) Is it again some native implementation? This is set at compile time and being static needs no class instance to be created. So if even this is some native implementation is it initialized by registerNatives() method in java.lang.Object?
These are called class literals and are defined by the language itself as per JLS §15.8.2 (there is no "class member"):
A class literal is an expression consisting of the name of a class, interface, array, or primitive type, or the pseudo-type void, followed by a '.' and the token class.
The type of C.class, where C is the name of a class, interface, or array type (§4.3), is Class<C>.
The type of p.class, where p is the name of a primitive type (§4.2), is Class<B>, where B is the type of an expression of type p after boxing conversion (§5.1.7).
The type of void.class (§8.4.5) is Class<Void>.
One indication that these constructs are intrinsically built into the language is that they even work with primitives!
System.out.println(int.class);
System.out.println(double.class);
// etc.
class is not normal static variable. It's a language construct which is replaced at compilation time.
Because class is a keyword it wouldn't even be possible to declare a variable with that name.
Your assumption that class is a static field of class Class is not exact. Assume that this is correct. In this case the value of this field will be exactly the same for all classes that is wrong.
Although MyClass.class syntactically looks like access to static field it is just a special syntax of language. Think about this as a kind of operator.
Probably JVM creates some kind of synthetic class that wraps real class and has such field but it is just an assumption about internal representation of classes in JVM.