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.
Related
I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.
I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
#Override
public void initialize()
{
System.out.println(bar);
}
}
And the base class:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!
Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?
Thanks for any insight!
The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.
The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.
Generally though, it's bad practice to call overridable methods from a constructor.
It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.
See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields
Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.
There's just one thing I would like to add to the accepted answer, because I don't entirely agree with his conclusion.
We've all done this.
class Engine {
public Engine() {
init();
}
void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
...
}
Now the question is, which access modifier should we add to our init() function. Should it be private or protected.
make it private <-- keeps subclasses out
make it protected <-- allows subclasses in
Before you make a choice
Now first of all, you should realize that (almost) all code in the Engine class can be replaced by a subclass.
code in a public function, can easily be overridden
code in a protected function, can easily be overridden
code in a private function, can be replaced by overriding all methods that call it.
Well, there is just one exception:
you can never modify the code of a constructor
you can never avoid a private method being called from the constructor of a super class.
(and of course, you cannot replace a final method)
Protected init() - the wrong way
Let's say the init() method is protected there is indeed a pitfall. It is tempting to override it to add features as follows. That would indeed be a mistake.
class SubEngine extends Engine {
int screws = 5;
void init() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this won't print 5, but it will print 0.
System.out.println("tightening " + screws + " screws");
}
}
Protected init() - the right way
So, basically, you should just disable the parents code and postpone execution to your own constructor instead.
class SubEngine extends Engine {
int screws = 5;
public SubEngine() {
initSubEngine();
}
void init() {
// disable parent code
}
void initSubEngine() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this will print 5 as expected
System.out.println("tightening " + screws + " screws");
}
}
Private init() - you may need a phonecall
Now, what if the init() method is private ?
Like mentioned above, there is no way to disable the code of a parent constructor. And if init() is private you simply cannot disable it.
You'll end up copying the entire Engine class, perhaps just to add 1 line of code.
And that may not be the end of it. Even after copying your class, your copied object won't be an Engine meaning that you won't be able to use your EngineUtil#inspectEngine(Engine engine) function.
Perhaps somebody knew this in advance and made an IEngine interface. Then you can get away with it.
In practice it means you'll have to take your phone, and call to that other department that made the Engine class, and ask them to change their code a little to take away some restrictions.
Intelligent design
There is another way. Constructors are for setting variables. They shouldn't activate anything. Everytime you see a class creating a new Thread from their constructor (or through a private method) that should be a red flag.
class Engine {
public Engine() {
}
public void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
// and you probably also want one of these
public void shutdown() { ... }
...
}
Intention
Of course, your intention may very well be not to open up your code. Perhaps you really don't want to allow others to extend your classes. There certainly can be cases where you want to lock people out.
Be aware that it will also make it harder to write tests for your code.
Anyway that's a different scenario.
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 currently have a parent class which has two subclasses and what I essentially want to do is have them both inherit a shared variable (a float). I need to set the value of the float in subclass1 and then use the value of the float in subclass2. I should add that these are all android activities and that subclass1 is at the beginning of a chain of activities and subclass2 is at the end of this chain, all the activities in between are also children of the same parent class.
What I currently have is something similar to the following:
(I've left a lot of the other code out this is just the bare bones)
class activityParent extends Activity{
public static float value;
public void setValue(){
//grab the value from phone (ill leave this code out and will hardcode a value below as an example)
value = 0.6f;
}
public void useValue(){
//where i use the value in another function here
otherFuncion(value);
}
}
class subclass1 extends activityParent
{
#Override
public void onCreate(Bundle bundle){
setValue();//need this to be initialized first
super.onCreate(bundle);
}
}
class subclass2 extends activityParent{
//some previous code here
//i need to use the value just before the activity finishes
useValue();
finish();
}
That float value is never used anywhere else.
This approach just seems wrong and I know it but I'm not sure how to go about implementing this properly.
I was thinking about passing data with intents but as mentioned the two subclasses arent in direct contact with each other, theres a series of activities between them and I'd rather not have to string this data through them all just to reach the end.
There is FAQ discussed in below link.
How do I pass data between Activities/Services within a single application?
Ideally, since you want to share a primitive data type (a float), Intent is recommended. But since this does not fit well with your requirement, you may skip this.
Next, using "static" (which you are currently doing) is also fine. You can access these static fields from any other class in your application.
But, if you want to have an alternate, then "Singleton" class can be used. This is a class that is designed to have only one instance.
public class Singleton {
private static Singleton INSTANCE ;
private Singleton() {}
public static synchronized Singleton getInstance() {
if(INSTANCE == null){
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
It has a static method with a name such as getInstance() that returns the instance; the first time this method is called, it creates the global instance.
For example activity subclass1 may retrieve the instance and call setValue(0.6); later activity subclass2 may retrieve the instance and call getValue() to retrieve the last set value.
Be very carefull with a cascade of classes. The onCreate() of a SubClass1 calls super.onCreate() which is the onCreate() of ActivityParent. This may trigger a chain reaction (the intent calling ActivityParent is still available to onCreate()).
So this may be a very simple question that I'm overthinking but if I do something like the following:
class A{
public String test_string = "before (default)";
public A(){
B b = new B(this);
}
public void testA(){
this.test_string = "after (new)";
}
}
where B is:
class B{
private A parent;
public B(A mParent){
parent = mParent;
}
private void testB(){
System.out.println(parent.test_string);
}
}
Would that allow me to still access the same instance of A (all of its public fields and methods)? If I called A.testA() from another class somewhere else on that specific instance of A, would the B that was constructed in that A's constructor's testB function return the "after (new)" string? Or would that be a copy of A because doesn't java assign by value, not reference? Is there a better way of doing this? Am I just over complicating the issue?
I wasn't sure what to search for so I couldn't find other questions that answered my question.
Thanks in advance!
It is breaking encapsulation to have public fields in a class and access them. Please wrap them in accessors if you must have them.
Besides, if you stick by the "tell don't ask" rule, then actually your code would be:
private void testB(){
parent.printTestString();
}
and in A you'd have
public void printTestString(){
System.out.println(test_string);
}
In answer to your question
"Would that allow me to still access the same instance of A (all of its public fields and methods)? If I called A.testA() from another class somewhere else on that specific instance of A"
Yes it would if it was the same instance.
"would the B that was constructed in that A's constructor's testB function return the "after (new)" string?"
Yes it would, the member field would be pointed to a new string reference so any usage of that instance of A would get the same value (threadsafety notwithstanding)
Yes, it is the same instance. It works like shown in this image:
So, calling a method over b.parent.foo, it is called over the same instance passed in the constructor.
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.