I have this code copied from Android developers website:
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
I am wondering what exactly "this" keyword refers to? Does it refer to the class "ExampleActivity"? And in general how to find what "this" refers to?
It refers to the instance of ExampleActivity on which onCreate() has been called.
In general, from the Java Language Specification, 15.8.3:
The keyword this may be used only in the body of an instance method, instance initializer or constructor, or in the initializer of an instance variable of a class. If it appears anywhere else, a compile-time error occurs.
When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method was invoked (§15.12), or to the object being constructed. The type of this is the class C within which the keyword this occurs. At run time, the class of the actual object referred to may be the class C or any subclass of C.
this refers to the most inner class instance. In your example it refers to ExampleActivity which is of type OnClickListener which is passed in to setOnClickListener.
Within an instance method or a
constructor, this is a reference to
the current object — the object whose
method or constructor is being called.
You can refer to any member of the
current object from within an instance
method or a constructor by using this.
Reference (from the Sun Java Tutorial):
Using the this keyword
Understanding Instance and Class
Members
"this" is a reference to the current object.
In your case, it refers to an instance of the ExampleActivity class.
http://download.oracle.com/javase/tutorial/java/javaOO/thiskey.html
Yes, 'this' refers to the instance of the enclosing class.
Related
I want to know the difference between accessing parent class fields using this and super.
We have the following abstract class named ListItem which extends Node class.
public abstract class ListItem {
protected ListItem rightLink=null;
abstract ListItem next();
}
And the following code inside the Node class:
public class Node extends ListItem {
#Override
ListItem next() {
return this.rightLink;
}
But if we use the code super.rightLink, I do not get any error at compile time or runtime. I just want to know what is the difference between the both and is there a best practice to accomplish the task?
Explanation
It does not matter in this case, there is no difference.
The field is declared in the parent class. So technically super.rightLink would makes the most sense. However, super and this are only relevant for resolving ambiguous situations with variable shadowing.
The best in this case would be to leave out any prefix and just type rightLink. But this is a bit opinion-based.
Example
Suppose we have the following
public class Parent {
int variable = 1; // Field
}
public class Child extends Parent {
int variable = 2; // Field
public void foo() {
int variable = 3; // Local variable
System.out.println(variable); // 3
System.out.println(this.variable); // 2
System.out.println(super.variable); // 1
}
}
In-depth
So we have a situation with 3 different variables which all live in a different scope, but they have the same name. When you just type variable, Java will refer to the variable with the lowest scope. Which would be the local variable in the method.
If you want to access your field, you need to do this.variable. If you want to access the field of your parent, you need to do super.variable.
So again, we have three different variables here.
no prefix: lowest scope
this: field with lowest scope
super: field with lowest scope, starting from the direct parent
In your specific example, however, we have no name shadowing at all. There is only one variable with the name rightLink. So all three variants refer to the exact same variable.
The best in this case would be to use no prefix at all, just rightLink.
JLS
Let us see how the Java Language Specification defines this. and super..
For this., refer to JLS§15.8.3:
When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method or default method was invoked (§15.12), or to the object being constructed. The value denoted by this in a lambda body is the same as the value denoted by this in the surrounding context.
For super., refer to JLS§15.11.2:
The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.
Unless rightLink is marked as private, it will be accessible in all classes deriving from ListItem. Thus, call super.rightLing and this.rightLink will be equivalent.
Generally, super refers to base class and this refers to class you are in. Use them appropraitely.
It's commonly used when overriding methods, i.e.
#Override
public void DoSomething(){
// Execute base imlpementation of a method
super.DoSomething();
// some additional code to add extra functionality to base class
}
Given the following classes:
public abstract class Super {
protected static Object staticVar;
protected static void staticMethod() {
System.out.println( staticVar );
}
}
public class Sub extends Super {
static {
staticVar = new Object();
}
// Declaring a method with the same signature here,
// thus hiding Super.staticMethod(), avoids staticVar being null
/*
public static void staticMethod() {
Super.staticMethod();
}
*/
}
public class UserClass {
public static void main( String[] args ) {
new UserClass().method();
}
void method() {
Sub.staticMethod(); // prints "null"
}
}
I'm not targeting at answers like "Because it's specified like this in the JLS.". I know it is, since JLS, 12.4.1 When Initialization Occurs reads just:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
...
T is a class and a static method declared by T is invoked.
...
I'm interested in whether there is a good reason why there is not a sentence like:
T is a subclass of S and a static method declared by S is invoked on T.
Be careful in your title, static fields and methods are NOT inherited. This means that when you comment staticMethod() in Sub , Sub.staticMethod() actually calls Super.staticMethod() then Sub static initializer is not executed.
However, the question is more interesting than I thought at the first sight : in my point of view, this shouldn't compile without a warning, just like when one calls a static method on an instance of the class.
EDIT: As #GeroldBroser pointed it, the first statement of this answer is wrong. Static methods are inherited as well but never overriden, simply hidden. I'm leaving the answer as is for history.
I think it has to do with this part of the jvm spec:
Each frame (§2.6) contains a reference to the run-time constant pool (§2.5.5) for the type of the current method to support dynamic linking of the method code. The class file code for a method refers to methods to be invoked and variables to be accessed via symbolic references. Dynamic linking translates these symbolic method references into concrete method references, loading classes as necessary to resolve as-yet-undefined symbols, and translates variable accesses into appropriate offsets in storage structures associated with the run-time location of these variables.
This late binding of the methods and variables makes changes in other classes that a method uses less likely to break this code.
In chapter 5 in the jvm spec they also mention:
A class or interface C may be initialized, among other things, as a result of:
The execution of any one of the Java Virtual Machine instructions new, getstatic, putstatic, or invokestatic that references C (§new, §getstatic, §putstatic, §invokestatic). These instructions reference a class or interface directly or indirectly through either a field reference or a method reference.
...
Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface that declared the resolved field or method is initialized if it has not been initialized already.
It seems to me the first bit of documentation states that any symbolic reference is simply resolved and invoked without regard as to where it came from. This documentation about method resolution has the following to say about that:
[M]ethod resolution attempts to locate the referenced method in C and its superclasses:
If C declares exactly one method with the name specified by the method reference, and the declaration is a signature polymorphic method (§2.9), then method lookup succeeds. All the class names mentioned in the descriptor are resolved (§5.4.3.1).
The resolved method is the signature polymorphic method declaration. It is not necessary for C to declare a method with the descriptor specified by the method reference.
Otherwise, if C declares a method with the name and descriptor specified by the method reference, method lookup succeeds.
Otherwise, if C has a superclass, step 2 of method resolution is recursively invoked on the direct superclass of C.
So the fact that it's called from a subclass seems to simply be ignored. Why do it this way? In the documentation you provided they say:
The intent is that a class or interface type has a set of initializers that put it in a consistent state, and that this state is the first state that is observed by other classes.
In your example, you alter the state of Super when Sub is statically initialized. If initialization happened when you called Sub.staticMethod you would get different behavior for what the jvm considers the same method. This might be the inconsistency they were talking about avoiding.
Also, here's some of the decompiled class file code that executes staticMethod, showing use of invokestatic:
Constant pool:
...
#2 = Methodref #18.#19 // Sub.staticMethod:()V
...
Code:
stack=0, locals=1, args_size=1
0: invokestatic #2 // Method Sub.staticMethod:()V
3: return
The JLS is specifically allowing the JVM to avoid loading the Sub class, it's in the section quoted in the question:
A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.
The reason is to avoid having the JVM load classes unnecessarily. Initializing static variables is not an issue because they are not getting referenced anyway.
The reason is quite simple: for JVM not to do extra work prematurely (Java is lazy in its nature).
Whether you write Super.staticMethod() or Sub.staticMethod(), the same implementation is called. And this parent's implementation typically does not depend on subclasses. Static methods of Super are not supposed to access members of Sub, so what's the point in initializing Sub then?
Your example seems to be artificial and not well-designed.
Making subclass rewrite static fields of superclass does not sound like a good idea. In this case an outcome of Super's methods will depend on which class is touched first. This also makes hard to have multiple children of Super with their own behavior. To cut it short, static members are not for polymorphism - that's what OOP principles say.
According to this article, when you call static method or use static filed of a class, only that class will be initialized.
Here is the example screen shot.
for some reason jvm think that static block is no good, and its not executed
I believe, it is because you are not using any methods for subclass, so jvm sees no reason to "init" the class itself, the method call is statically bound to parent at compile time - there is late binding for static methods
http://ideone.com/pUyVj4
static {
System.out.println("init");
staticVar = new Object();
}
Add some other method, and call it before the sub
Sub.someOtherMethod();
new UsersClass().method();
or do explicit Class.forName("Sub");
Class.forName("Sub");
new UsersClass().method();
When static block is executed Static Initializers
A static initializer declared in a class is executed when the class is initialized
when you call Sub.staticMethod(); that means class in not initialized.Your are just refernce
When a class is initialized
When a Class is initialized in Java After class loading, initialization of class takes place which means initializing all static members of class. A Class is initialized in Java when :
1) an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
2) an static method of Class is invoked.
3) an static field of Class is assigned.
4) an static field of class is used which is not a constant variable.
5) if Class is a top level class and an assert statement lexically nested within class is executed.
When a class is loaded and initialized in JVM - Java
that's why your getting null(default value of instance variable).
public class Sub extends Super {
static {
staticVar = new Object();
}
public static void staticMethod() {
Super.staticMethod();
}
}
in this case class is initialize and you get hashcode of new object().If you do not override staticMethod() means your referring super class method
and Sub class is not initialized.
Since this object(stated in title) can invoke overridden methods in child class, why it can't invoke other methods of child class?
I need answer as detailed as possible like memory organization, internal logic in JVM etc.
below code will give you clear understanding of my question.
class A
{
int x=10;
public A()
{
System.out.println("Constructor of class A called!!!");
}
public void sayGreetings()
{
System.out.println("accept hye from class A");
}
}
class C extends A
{
int x=30;//why this is not accessed by stated object.
public C()
{
System.out.println("Constructor of Class C caled!!!");
}
public void sayGreetings()
{
System.out.println("accept hye from class C");
}
public void ssa()
{
System.out.println("Sat Sri Akal ji from class C");
}
}
public class ParentClassTypeObject
{
public static void main(String[] args)
{
C cObj=new C();
cObj.sayGreetings();
cObj.ssa();
A aCObj=new C();//this is let say stated object,main object
aCObj.sayGreetings();/*here we invoked method will be child class's
overriden method.*/
//aCObj.ssa(); //why this line gives error
System.out.println("x="+aCObj.x);
}
}
Because the interface you have to the object is the one you chose when you wrote:
A aCObj = new C();
If you want access to the C properties via the aCObj variable, declare it as a C.
By making it an A, you make it possible to write this later:
aCObj = new A();
So since the variable can point to an A, or a C, the compiler restricts you to accessing the methods defined by the interface exposed by the A type.
You still access C's definition of those methods, because that's one of the main points of OOP (polymorphism).
Reference Variable points to the object which is of same type or the Sub set of same type.
Please consider Parent and Child are two classes Where Parent is Super Class and Child inherits the Parent Class. The below image will give you a detailed explanation.
In the above picture, The Parent class Reference variable will search for the Parent Class Object in Child Object.It will find it , as it is there.So will give the output.And if you have the Same method in Child Class(Method Overriding) It will execute the child class overrided method.
But for the Child Class reference Variable ,It can not find out the child class object in Parent Class Object.So here,It's Not possible.
Hope This clear your Confusion.
If you compile the code you will get compile time error(not runtime error). The reason behind this is that
A aCObj=new C();
aCObj.sayGreetings();/* The compiler knows that aCobj is a reference of type A while compiling. Since compiler thinks aCobj is of type A and sayGreetings() method is present in class A so no error while calling this method */
aCObj.ssa(); /* As I mentioned above that compiler have no knowledge about run time. At run time aCobj will point to the object of type class C, but while compiling the compiler only knows that aCobj is of class A type and since class A have no such method called ssa(), you will get compile time error. */
One simple rule for object : Left side of assignment operator checking at compile time. Right side of assignment operator at run time.
Consider this statement:
Parent obj =new Child();
obj.method1();
obj.method2();
Whatever method u want to call using obj reference of Parent type, those method should present in Parent class because during compile time the compiler will strictly check for those methods presence in Parent class even though it may be present in Child class.
The compiler decides IF you can call a method based on the type of the reference variable.So if the reference variable is of class A you can only call methods of class A.
But also
the compiler decides WHICH method to call based on the actual type of the object and not the type of the reference variable starting a bottom up check on the inheritance tree.(it starts from the subclasses all the way up)
So in this case when you say aCObj.sayGreetings(); the compiler firstly checks the reference type of aCObj which is A.Class A has the sayGreetings() method so its ok.But the actual object is a C.So the compiler starts from subclass (C) to find whether this method is implemented all the way to the superclass (A).The method `sayGreetings() is overriden at C class. So it calls the C class sayGreetings() method(of the subclass).
On the other hand the ssa() method is of class C and since the reference variable is of class A the compiler gives an error when you try aCObj.ssa();
It's just polymorphism.Since an A class reference variable can be either A or C object the compiler restricts the access only to the methods that are common which are the methods of the superclass A.Next it checks whether this method is implemented at the class of the actual object (C).if it is not it moves up to the superclass (A) and calls the method of the superclass.But if it is implemented it calls the method of the subclass (C)
The Object is of type A not C so you cannot access the instance variable i think if you make it public then you can.
Because aCObj is declared as type A so only methods declared in type A are accessible. The compiler cannot guarantee it is also of type C.
E.g.
You may also have
public class B extends A {
public void sayGreetings() {
...
}
}
This does not have the ssa method, but could still be assigned to an object declared as type A
Case 1. The reference variable of a parent class can point to an object of its child class..
Case 2. The reference variable of a parent class that is pointing to an object of its child class can be typecasted to an object of its child class.
In case 1: reference variable of a parent class can only call the methods that are defined within the parent class and also it can call the methods of child class that are overriding the methods of parent class.But cannot call the methods that are exclusively only in child class.
In case 2: reference variable of a parent class can call the methods of its child class also.
This is due to the principle of Polymorphism.
here is the detailed explanation of your stated query:
The answer is the intersection of "polymorphism" and "static typing". Because Java is statically typed at compile time you get certain guarantees from the compiler but you are forced to follow rules in exchange or the code won't compile. Here, the relevant guarantee is that every instance of a subtype (e.g. Child) can be used as an instance of its supertype (e.g. Parent). For instance, you are guaranteed that when you access employee.getEmployeeDetails or employee.name the method or field is defined on any non-null object that could be assigned to a variable employee of type Parent. To make this guarantee, the compiler considers only that static type (basically, the type of the variable reference, Parent) when deciding what you can access. So you cannot access any members that are defined on the runtime type of the object, Child.
The answer has been taken from the following link:
Why do we assign a parent reference to the child object in Java?
This may be a very elementary question for Java, but I just can't recall it and have no clue how to search it online.
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Thread.sleep(100);
}
}
I'm used to initializing an object using constructors like new OnClickListener(arg1, arg2, ...). In my own experience I've never override a method when constructing an object. I've only done it when extending a class. What is this kind of instantiation called in Java if there's any term for it? In what other cases should we use it?
That's an anonymous class. It's an implementation of the OnClickListener interface, but that implementation is unnamed. It's concise to write and the implementation is visible in the calling context (often useful for readability), but since it's an implementation in-place, you can't use it elsewhere.
Note also that it's an inner class and hence has a reference to its surrounding class.
See here for more info.
Re. the reference to a surrounding class. An inner class has an implicit reference to its outer class (you can see this if you attempt to serialise the inner class using, say, XStream. It'll pull the outer class along with it). If you have a variable in the outer class, you can reference it in the inner (provided it's a final variable, mind)
They are called anonymous classes.
Technically they are subclasses of the class being instantiated, and provide overridden method implementations.
They are useful when you want to provide an implementation without having to specifically declare a top level class.
They are Java's answer to closures.
new OnClickListener()
{
#Override
public void onClick(View v)
{
Thread.sleep(100);
}
}
Both from the syntax and semantics perspective, this construct is a blend of instantiation and class declaration. In the same breath you specify which constructor of OnClickListener to call (interfaces are assumed to have the default constructor for this purpose) and provide the class body that belongs to the new subclass you are declaring. You are not giving a name to the subclass, that's why this construct is called an "anonymous class". With an anonymous class instantiation is tightly coupled to declaration and you can't instantiate this class from any other point in code except where it is declared.
There is a nearly identical construct in Java that you'll almost never see used in practice: a local class. It looks just like a regular class declaration, but it occurs inside a method, just like the anonymous class above. In this case the class is given a name and can be referred to and instantiated on several places, but all of them inside the method where it is declared.
In both cases you get the special feature not available to any other class, which is the ability to use the local variables declared in the method. This is odd at first because the local variable disappears when the method completes, but the reference to an instance of the local class goes on living. This is why these classes are called "closures": they are said to "close over" their local environment. They kind of "lift" the variable declarations and keep them as their instance variables.
Just to give a bit of an example of how this could be used...
public class TestClass {
public static void main(String args[]) {
OutOfTheMain ootm = new OutOfTheMain();
}
}
public interface SuperInner {
String words = "hello";
String getWords();
}
public class OutOfTheMain {
OutOfTheMain() {
testInnerStuff(new SuperInner() {
#Override
public String getWords() {
return words + " world";
}
});
}
private void testInnerStuff(SuperInner sinner) {
System.out.println(sinner.getWords());
}
}
When ran, this would print...
hello world
You can override methods to add additional functionality and use this class later on at runtime.
As per standard book constructor is a special type of function which is used to initialize objects.As constructor is defined as a function and inside class function can have only two type either static or non static.My doubt is what constructor is ?
1.)As constructor is called without object so it must be static
Test test =new Test();//Test() is being called without object
so must be static
My doubt is if constructor is static method then how can we frequently used this inside
constructor
Test(){
System.out.println(this);
}
Does the output Test#12aw212 mean constructors are non-static?
Your second example hits the spot. this reference is available in the constructor, which means constructor is executed against some object - the one that is currently being created.
In principle when you create a new object (by using new operator), JVM will allocate some memory for it and then call a constructor on that newly created object. Also JVM makes sure that no other method is called before the constructor (that's what makes it special).
Actually, on machine level, constructor is a function with one special, implicit this parameter. This special parameter (passed by the runtime) makes the difference between object and static methods. In other words:
foo.bar(42);
is translated to:
bar(foo, 42);
where first parameter is named this. On the other hand static methods are called as-is:
Foo.bar(42);
translates to:
bar(42);
Foo here is just a namespace existing barely in the source code.
Constructors are non-static. Every method first parameter is implicit this (except static) and constructor is one of that.
Constructors are NOT static functions. When you do Test test =new Test(); a new Test object is created and then the constructor is called on that object (I mean this points to the newly created object).
The new keyword here is the trick. You're correct in noting that in general, if you're calling it without an object, a method is static. However in this special case (i.e., preceded by the new keyword) the compiler knows to call the constructor.
The new operator returns a reference to the object it created.
new Test(); // creates an instance.
The System.out.println(this); is called after the new operator has instantiated the object
Not static. Read about constructors http://www.javaworld.com/jw-10-2000/jw-1013-constructors.html.
Neither.
Methods can be divided into 2 types: static/non-static methods, aka class/instance methods.
But constructors are not methods.
When we talk about static class then it comes to our mind that methods are called with class name,But in case of constructor ,Constructor is initialized when object is created So this proves to be non-static.
Constructors are neither static (as called using class name) or non-static as executed while creating an object.
Static:
Temp t= new Temp();
The new operator creates memory in the heap area and passes it to the constructor as Temp(this) implicitly. It then initializes a non-static instance variable defined in a class called this to the local parameter variable this.
Below example is just for understanding the concept, if someone tries to compile it, it will give the compile-time error.
class Temp{
int a;
Temp this; //inserted by compiler.
Temp(Temp this){ //passed by compiler
this.this=this; // initialise this instance variable here.
this.a=10;//when we write only a=10; and all the non-static member access by this implicitly.
return this; // so that we can't return any value from constructor.
}
}
Constructor is static because:
It is helping to create object.
It is called without object.
Constructor is used to initialize the object and has the behavior of non-static methods,as non-static methods belong to objects so as constructor also and its invoked by the JVM to initialize the objects with the reference of object,created by new operator