I am doing Android programming and was learning about Intents, when I saw a constructor that, to my C# trained mind, seemed funky. The call was:
Intent myIntent = new Intent(CurrentActivity.this, NextActivity.class);
Both of the parameters are new to me. How is there a static ".this" off of a Class Name? Is this a Java thing or an Android thing? I am assuming that it is the same as just saying "this", since I am in the context of CurrentActivity, but I don't get how the "this" can be called off of the Class name itself. Also. The ".class" looks like it is used for reflection, which I am familiar with in C#, but any insight into this would be welcomed as well.
Thanks.
Usually, you can use only this. But, sometimes this makes reference to an inner class... so, for example:
Button button = (Button)findViewById(R.id.ticket_details_sell_ticket);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// it will be wrong to use only "this", because it would
// reference the just created OnClickListener object
Intent login = new Intent(ClassName.this, Login.class);
startActivityForResult(login, LOGIN_REQUEST);
}
});
One at a time:
The first construct is called a qualified this. The purpose of the syntax is in the case where you are in an inner class (typically an anonymous inner class) and you want to reference the this of the outer class rather than the this of the (anonymous) inner class. The "qualified this" can only be used in a context where this would be ambiguous. The quote the JLS "It is a compile-time error if the expression occurs in a class or interface which is not an inner class of class T or T itself".
The second construct is called a class literal is the way to reference the Class object that represents that type. It can be used in any context.
The syntax "Classname.this" is for inner classes. If you want to refer to the enclosing instance of type "Outerclass" then you do it as "Outerclass.this".
NextActivity.class is simply the Class object that describes class "NextActivity".
NextActivity.class in java means typeof(NextActivity) in C#
ClassName.this is used to reference the current instance of an outerclass from an inner class.
<ClassName>.this
is used in nested classes to refer to the current instance of the enclosing class, since the `this' keyword refers to the nest class instance.
public class Siht {
class NestedSiht {
void demoThis() {
System.err.println("this' is an instance of: " +
this.getClass().getName());
System.err.println("Siht.this' is an instance of: " +
Siht.this.getClass().getName());
}
}
void demoThis() {
new java.lang.Object() {
void demoThis() {
System.err.println("`this' is an instance of: " +
this.getClass().getName());
System.err.println("`Siht.this' is an instance of: " +
Siht.this.getClass().getName());
}
}.demoThis();
new NestedSiht().demoThis();
}
public static void main(String [] args) {
new Siht().demoThis();
}
}
It's confusing only because when you use "MainActivity.this", it seems that you are referring to the class and not the object.
In reality when you use "this" you are always referring to the current object,
as the java se documentation states:
https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
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.
It's just syntactically peculiar.
Related
What I want to do is like this. My question is how can I call tm.test in inner.
// TestMain is a class implemented handler
public void outer() {
inner(TestMain::test); // call inner
}
public void inner(handler h) {
TestMain tm = new TestMain();
//invoke tm.h(), i.e. invoke tm.test() in this example
}
public interface handler<M> {
void entitySelector();
}
I know how to call tm.test in inner if tm is declared in method outer, i.e. pass the function as tm::test
But I have to declare the instance every time I call inner.
Simply spoken: you can't. And even it would be possible, you shouldn't do something like that.
There is the "principle of least surprise": you don't that people reading your code tell you "wtf?!" because your code surprises them.
In other words: you should step back and see if your design really makes sense this way. Can't you use a fixed tm instance for example; one that sits as field on your class; instead of being a local variable in your method?
This was asked slightly differently earlier but asking for a yes/no answer but I'm looking for the explanation that's missing from the book (Java Concurrency in Practice), of how this apparent big mistake would be exploited maliciously or accidentally.
A final mechanism by which an object or its internal state can be
published is to publish an inner class instance, as shown in
ThisEscape in Listing 3.7. When ThisEscape publishes the
EventListener, it implicitly publishes the enclosing ThisEscape
instance as well, because inner class instances contain a hidden
reference to the enclosing instance.
Listing 3.7. Implicitly Allowing the this Reference to Escape. Don't
do this.
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
3.2.1. Safe Construction Practices
ThisEscape illustrates an important special case of escape—when the
this references escapes during construction. When the inner
EventListener instance is published, so is the enclosing ThisEscape
instance. But an object is in a predictable, consistent state only
after its constructor returns, so publishing an object from within its
constructor can publish an incompletely constructed object. This is
true even if the publication is the last statement in the constructor.
If the this reference escapes during construction, the object is
considered not properly constructed.[8]
[8] More specifically, the this reference should not escape from the
thread until after the constructor returns. The this reference can be
stored somewhere by the constructor so long as it is not used by
another thread until after construction. SafeListener in Listing 3.8
uses this technique.
Do not allow the this reference to escape during construction.
How would someone code against this to get to the OuterClass before it's finished constructing? What is the hidden inner class reference mentioned in italics in the first paragraph?
Please see this article. There it's clearly explained what could happen when you let this escape.
And here is a follow-up with further explanations.
It's Heinz Kabutz amazing newsletter, where this and other very interesting topics are discussed. I highly recommend it.
Here is the sample taken from the links, which show how the this reference escapes:
public class ThisEscape {
private final int num;
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
num = 42;
}
private void doSomething(Event e) {
if (num != 42) {
System.out.println("Race condition detected at " +
new Date());
}
}
}
When it gets compiled, javac generates two classes. The outer class looks like this:
public class ThisEscape {
private final int num;
public ThisEscape(EventSource source) {
source.registerListener(new ThisEscape$1(this));
num = 42;
}
private void doSomething(Event e) {
if (num != 42)
System.out.println(
"Race condition detected at " + new Date());
}
static void access$000(ThisEscape _this, Event event) {
_this.doSomething(event);
}
}
Next we have the anonymous inner class:
class ThisEscape$1 implements EventListener {
final ThisEscape this$0;
ThisEscape$1(ThisEscape thisescape) {
this$0 = thisescape;
super();
}
public void onEvent(Event e) {
ThisEscape.access$000(this$0, e);
}
}
Here the anonymous inner class created in the constructor of the outer class is converted to a package-access class that receives a reference to the outer class (the one that is allowing this to escape). For the inner class to have access to the attributes and methods of the outer class, a static package-access method is created in the outer class. This is access$000.
Those two articles show both how the actual escaping occurs and what might happen.
The 'what' is basically a race condition that could lead to a NullPointerException or any other exception when attempting to use the object while not yet fully initialized. In the example, if a thread is quick enough, it could happen that it runs the doSomething() method while num has not yet been correctly initialized to 42. In the first link there's a test that shows exactly that.
EDIT:
A few lines regarding how to code against this issue/feature were missing. I can only think about sticking to a (maybe incomplete) set of rules/principles to avoid this problem and others alike:
Only call private methods from within the constructor
If you like adrenaline and want to call protected methods from within the constructor, do it, but declare these methods as final, so that they cannot be overriden by subclasses
Never create inner classes in the constructor, either anonymous, local, static or non-static
In the constructor, don't pass this directly as an argument to anything
Avoid any transitive combination of the rules above, i.e. don't create an anonymous inner class in a private or protected final method that is invoked from within the constructor
Use the constructor to just construct an instance of the class, and let it only initialize attributes of the class, either with default values or with provided arguments
If you need to do further things, use either the builder or the factory pattern.
I'll modify the example a bit, to make it more clear. Consider this class:
public class ThisEscape {
Object someThing;
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e, someThing);
}
});
someThing = initTheThing();
}
}
Behind the scenes, the anonymous inner class has access to the outer instance. You can tell this, because you can access the instance variable someThing and, as Shashank mentioned you can access the outer instance via ThisEscape.this.
The problem is that by giving the anonymous inner class instance to the outside (in this case the EventSource object) it will also carry the ThisEscape instance with it.
What can happen bad with it? Consider this implementation of EventSource below:
public class SomeEventSource implements EventSource {
EventListener listener;
public void registerListener(EventListener listener) {
this.listener = listener;
}
public void processEvent(Event e) {
listener.onEvent(e);
}
}
In ThisEscape's constructor we register an EventListener which will be stored in the listener instance variable.
Now consider two threads. One is calling the ThisEscape constructor, while the other calls processEvent with some event. Also, let's say the JVM decides to switch from the first thread to the second one, right after the source.registerListener line and right before someThing = initTheThing(). The second thread now runs, and it will call the onEvent method, which as you can see, does something with someThing. But what is someThing? It's null, because the other thread did not finish initializing the object, so this will (probably) cause a NullPointerException, which is not actually what you want.
To sum up: be careful that you don't escape objects that have not been fully initialized (or in other words, their constructor did not finish yet). One subtle way you could inadvertently do this, is by escaping anonymous inner classes from the constructor, which will implicitly escape the outer instance, which is not fully initialized.
The key point here is that it is often easy to forget that an in-lined anonymous object still has a reference to its parent object and that's how this code fragment is exposing a not-yet-completely-initialised instance of itself.
Imagine EventSource.registerListener immediately calls EventLister.doSomething()! That doSomething will be called on an object whose parent this is incomplete.
public class ThisEscape {
public ThisEscape(EventSource source) {
// Calling a method
source.registerListener(
// With a new object
new EventListener() {
// That even does something
public void onEvent(Event e) {
doSomething(e);
}
});
// While construction is still in progress.
}
}
Doing it this way would plug the hole.
public class TheresNoEscape {
public TheresNoEscape(EventSource source) {
// Calling a method
source.registerListener(
// With a new object - that is static there is no escape.
new MyEventListener());
}
private static class MyEventListener {
// That even does something
public void onEvent(Event e) {
doSomething(e);
}
}
}
It is my understanding that the issue is not that the user can gain access to the escaped ThisEscape reference (it is, after all, said to be hidden). The issue is that because of the way the classes are compiled and executed, the JVM can see that reference and start referencing it elsewhere before the constructor has finished building the ThisEscape instance. So race conditions can result.
I'm puzzled by the possibility to call new on an instance, like
InnerClass sc = pc.new InnerClass();
I understand how to use it, but my question is about fully understanding this. Like:
Where is it described in the JAVA documentation?
Is this a recommended solution that should be used, or is there a better way?
Why doesn't a plain "new" work?
I saw it in a code example, and I have worked out enough to understand that I'm unable to use a plain "new" in a static context.
This is the full context as a runnable example:
class ParentClass{
ParentClass(){
}
public static void main(String[] args){
ParentClass pc = new ParentClass();
InnerClass sc = pc.new InnerClass();
}
class InnerClass {
InnerClass() {
System.out.println("I'm OK");
}
}
}
Disclaimer: The terms "parent class" and "sub class" you use are not correct in your example, so my example below will use the correct terms "outer class" and "inner class" (thanks to #eis for the hint).
Where is it described in the JAVA documentation?
See #eis' comment to my answer for a link.
Is this a recommended solution that should be used, or is there a better way?
It depends – on what you need it for.
If SubClass doesn't need any information of an instance of ParentClass, it could (and should) be either made static or extracted to not be an inner class at all anymore. In that case, you can just call new on it without having an instance of ParentClass.
Why doesn't a plain "new" work?
Because SubClass may refer to information of the surrounding instance, which requires you to specify that instance. It's not a sub class in the sense that it extends ParentClass, but instead its type becomes a member of the outer class.
Consider this (and see it in action here):
public class OuterClass {
private int field;
public OuterClass(int field) {
this.field = field;
}
class InnerClass {
public int getOuterClassField() {
// we can access the field from the surrounding type's instance!
return OuterClass.this.field;
}
}
public static void main(String[] args) throws Exception {
OuterClass parent = new OuterClass(42);
// prints '42'
System.out.println(parent.new InnerClass().getOuterClassField());
// cannot work as it makes no sense
// System.out.println(new InnerClass().getOuterClassField());
}
}
If you were able to simply do new InnerClass(), there's no way of knowing what getOuterClassField should return since it is connected to the instance of its surrounding type (rather than just the type itself).
Working with anonymous innerclasses in java,you have to declare the variables of enclosing class which you are using in the anonymous innerclass as final. Ok i got it that why this must be done from
Cannot refer to a non-final variable inside an inner class defined in a different method
but also the answerer says that
"By making lastPrice and price final, they are not really variables
anymore, but constants. The compiler can then just replace the use of
lastPrice and price in the anonymous class with the values of the
constants (at compile time, ofcourse), and you won't have the problem
with accessing non-existent variables anymore"
This made me to wander that is the final keyword working like as Macros are in C\C++.Till now, I was using final for variables in a way that whenever I will try to modify them(accidentally) I will be getting an error that You can't modify it as it is declared as final.But this replacement thing is not clear to me.
Question: According to the selected answer from the above link answerer says
This is why it doesn't work:
The variables lastPrice and price are local variables in the main()
method. The object that you create with the anonymous class might last
until after the main() method returns.
When the main() method returns, local variables (such as lastPrice and
price) will be cleaned up from the stack, so they won't exist anymore
after main() returns.
But the anonymous class object references these variables. Things
would go horribly wrong if the anonymous class object tries to access
the variables after they have been cleaned up.
**
Where this storage is taking place for replacement later?Who is taking care of it?final variables are just replaced by values?
**
No, this is not like macros in C++. The difference is that macros are evaluated at compile time and the preprocessor replace the macro with its definition.
final variables on the other hand can be computed at run time. Once set, though, the value cannot change at a later time. This constraint is what makes it possible to use the value in an inner class.
Let's look at an example to make this more clear:
public void func(final int param) {
InnerClass inner = new InnerClass() {
public void innerFunc() {
System.out.println(param);
}
}
inner.innerFunc();
}
Note that param can be set at run time by passing different values to it. But each time func() is called, a new InnerClass object is created and captures the current value of param which is guaranteed to never change because it is declared as final.
In a different situation where the variable is constant, then the compiler can replace the value at compile time. However, this isn't special for inner classes because constants are replaced at compile time no matter where they are used.
The moral of the story is that an anonymous inner class can access any final variable whether or not it is a compile time constant or calculated at run time.
#Butterflow from Brian Goetz:
Declaring a final field helps the optimizer make better optimization decisions, because if the compiler knows the field's value will not change, it can safely cache the value in a register. final fields also provide an extra level of safety by having the compiler enforce that a field is read-only.
You can find here the full article about the keyword final
With anonymous classes, you are actually declaring a "nameless" nested class. For nested classes, the compiler generates a new standalone public class with a constructor that will take all the variables it uses as arguments (for "named" nested classes, this is always an instance of the original/enclosing class). This is done because the runtime environment has no notion of nested classes, so there needs to be a (automatic) conversion from a nested to a standalone class.
Take this code for example:
public class EnclosingClass {
public void someMethod() {
String shared = "hello";
new Thread() {
public void run() {
// this is not valid, won't compile
System.out.println(shared); // this instance expects shared to point to the reference where the String object "hello" lives in heap
}
}.start();
// change the reference 'shared' points to, with a new value
shared = "other hello";
System.out.println(shared);
}
}
That won't work, because this is what the compiler does under the hood:
public void someMethod() {
String shared = "hello";
new EnclosingClass$1(shared).start();
// change the reference 'shared' points to, with a new value
shared = "other hello";
System.out.println(shared);
}
The original anonymous class is replaced by some standalone class that the compiler generates (code is not exact, but should give you a good idea):
public class EnclosingClass$1 extends Thread {
String shared;
public EnclosingClass$1(String shared) {
this.shared = shared;
}
public void run() {
System.out.println(shared);
}
}
As you can see, the standalone class holds a reference to the shared object, remember that everything in java is pass-by-value, so even if the reference variable 'shared' in EnclosingClass gets changed, the instance it points to is not modified, and all other reference variables pointing to it (like the one in the anonymous class: Enclosing$1), will not be aware of this. This is the main reason the compiler forces you to declare this 'shared' variables as final, so that this type of behavior won't make it into your already running code.
Now, this is what happens when you use an instance variable inside an anonymous class (this is what you should do to solve your problem, move your logic to an "instance" method or a constructor of a class):
public class EnclosingClass {
String shared = "hello";
public void someMethod() {
new Thread() {
public void run() {
System.out.println(shared); // this is perfectly valid
}
}.start();
// change the reference 'shared' points to, with a new value
shared = "other hello";
System.out.println(shared);
}
}
This compiles fine, because the compiler will modify the code, so that the new generated class Enclosing$1 will hold a reference to the instance of EnclosingClass where it was instantiated (this is only a representation, but should get you going):
public void someMethod() {
new EnclosingClass$1(this).start();
// change the reference 'shared' points to, with a new value
shared = "other hello";
System.out.println(shared);
}
public class EnclosingClass$1 extends Thread {
EnclosingClass enclosing;
public EnclosingClass$1(EnclosingClass enclosing) {
this.enclosing = enclosing;
}
public void run() {
System.out.println(enclosing.shared);
}
}
Like this, when the reference variable 'shared' in EnclosingClass gets reassigned, and this happens before the call to Thread#run(), you'll see "other hello" printed twice, because now EnclosingClass$1#enclosing variable will keep a reference to the object of the class where it was declared, so changes to any attribute on that object will be visible to instances of EnclosingClass$1.
For more information on the subject, you can see this excelent blog post (not written by me): http://kevinboone.net/java_inner.html
Providing finish() and this.finish() in onPause() or onStop() method is same?
Yes. Please become familiar with meaning of this. -> it's value is the reference to the current object. For example, if you have a class named Foo, and it has method named method(), then this in it would be a reference to a instance of the Foo (that is: a Foo object). Usually you do not need to use this.
this in any context refers to the containing class. So, if you are using the method inside an Activity, then this.finish() is same as finish(). However, if you are using this in a different class type, you may not have this.finish()
Even though the question is 3 years old.I prefer to torch some light over the present and future researchers.
this is just an object reference.You don't have to use this every time ,other than you need to get a reference of parent class from a child class instance.
Let's consider an example when using Thread class.
public class A
{
public A()
{
new Thread(new Runnable()
{
public void start()
{
B child=new B(A.this);//In this scenario,'A.this' refers to the parent class 'A' in which the 'Thread' class instantiated.If you simply pass 'this' ,then it would refer to the 'Thread' class as this statement executed in the current scope.
}
}).start();
}
}
public class B
{
A parent;
public B(A parent)
{
this.parent=parent;//'this' refers to the class B ,so that it can access the global variable 'parent' ,then assigns it with the local variable 'parent' passed through the constructor.
}
}
Like listed above ,there are different usages of this keyword.Its better to refer the oracle's documentation over here https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
finish() and this.finish() is the same.
For the other part of the question, please read about the Activity lifecycle.
In your case It's the same. It's sometimes important to use this->... if you have an member and an method parameter with the same name like in the following example:
class foo{
int number;
void setNumber(int number);
}
so you can write in your method
void foo::setNumber(int number)
{
this->number = number;
}
And so It's clear which element you have used. But be careful don't use the same names it's not really nice.