I needed to change variables inside an inner class and I got the infamous "Cannot refer to a non-final variable inside an inner class defined in a different method" error.
void onStart(){
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int q = i;
}
});
}
I quickly made a class that held all of the things I wanted to change and made a final version of the class outside the inner class
class temp{
int q;
}
void onStart(){
final temp x = new temp();
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
x.q = i;
}
});
}
This seems to be what I need and it works but I am wondering if this is how to correctly work around the problem. Also, I really hate using the word temp to name my class. Is there an actual programming term for what I did so that I make a more descriptive name for my class?
You can simply create an inner class instead of an anonymous one (like you are currently doing). Then you have a constructor and any other methods you want to set your members. No hackiness required (like the array of 1 case).
I find this cleaner if the class requires any exchange of data with its outer class, but admit it is a personal preference. The array of 1 idiom will work as well and is more terse, but frankly, it just looks fugly. I typically limit anonymous inner classes to those that just perform actions without trying to update data in the outer class.
For example:
private MyListener listener = new MyListener();
void onStart(){
bt.setOnClickListener(listener);
}
class MyListener implements OnClickListener
{
String name;
int value;
void setName(String newName)
{
name = newName;
}
void setValue(int newValue)
{
value = newValue;
}
public void onClick(View v)
{
// Use the data for some unknown purpose
}
}
If there are multiple threads involved, then appropriate synchronization will have to be used as well.
I posted a similar answer in my other thread here. Basically the idea is to create a "wrapper" which wraps over pretty much any Object type. Since final in Java stands for "no reassignment" and not "constant", this trick pretty much works out fine. But as mentioned in the original post, make sure you tread with caution when using it in a multi-threaded environment.
I would keep a reference to your on click listener in the outer class, and make the int a member variable in your listener. Just store the variable in the listener on click, then grab the variable in the outer class when you need it, rather than setting it at the point of the click.
To put it simply, if the inner class needs to change it, make it a variable in the inner class.
Since you appear to be setting multiple things (from the comments), make a method in the main class, button1WasClicked(), (a better name might be doUpdate, doSave etc. - something relevant to what the button does), put the proper code there, and call it from the inner class / listener. (If you are using Swing I'd make it an Action, YMMV)
That way if later on there is a menu or an intent or a gesture that needs to execute the same stuff, the call is there.
Related
I have currently created a new CountDownTimer object in my java file, I then have that timer have an onFinish() method where it makes another new CountDownTimer object that has required functionality in it's own onFinish() method.
However when I create a boolean value outside of the second timer (and maintain it as false) and then attempt to modify this boolean to true within the onFinish() method of the second timer it gives me the error:"Variable [boolean variable name] is accessed from within inner class, needs to be declared final".
When I declare the variable final though I absolutely cannot modify it.
So what is the most effective way to go about resolving this problem? I cannot lose the functionality of the timers, yet my experience with java is very shallow. I apologise if this question seems silly.
I would love to also use something like a getter/setter method but with a timer I am not sure if that would even be effective.
Thank you to everyone who replies in advance! It is greatly appreciated! :)
For the sake of clarity: I require the timer to set a boolean flag that will detect that the second timer has indeed finished. This will set the boolean flag to true and then with that I modify the functionality of a button I created. In a similar fashion I also desire this second timer to initialize a long value to be referenced outside of it as well.
If the boolean = false then the button causes a rejection of the user.
If the boolean = true then the button accepts the user.
And then I use the long number obtained below.
Code as requested:
boolean clickAppropriate = false;
new CountDownTimer(t1, t2) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
mTextField.setText("text");
new CountDownTimer(t3, t4) {
public void onTick(long millisUntilFinished) {
public void onFinish() {
long startTime = System.nanoTime();
clickAppropriate = true;
}
}.start();
}
}.start();
Easiest fix I see here without modifying the structure of your solution is to choose ´final boolean[] clickAppropriate = new boolean[1]´ and work with ´clickAppropriate[0]´ element instead. Choosing AtomicBoolean might give extra benefit if you work with multiple threaded environment.
You can use the this keyword together with the outer class (The class where the boolean is declared) name to access its member.
Example:
public class Outer {
public boolean bool = false;
public class Inner {
public void displayOuterClassVariable () {
System.out.println(Outer.this.bool);
}
}
}
In your case, you need to use your outer class name with clickApprpriate. But it seems like your variable is declared in a method. You have to put that variable in the class in order to use this syntax.
This is an interesting question. The way that you have your code currently structured, you will not be able to alter the contents of your clickAppropriate variable from within your anonymous CountDownTimer class declaration.
This is what Oracle writes in regards to accessing local variables from within Anonymous Classes:
"An anonymous class cannot access local variables in its enclosing scope that are not declared as final or effectively final."
http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
This is the reason why your compiler is giving you this error.
One way that you can access and alter your clickApproriate variable from within your anonymous class is to change this variable from being a local variable to being a class variable.
I was able to successfully compile the below code without any errors.
public class Main
{
static boolean clickAppropriate;
public static void main(String args[])
{
clickAppropriate = false;
new CountDownTimer()
{
public void onFinish()
{
clickAppropriate = true;
};
}.start();
}
}
One thing that I would point out that is not evident - your use of anonymous classes is in affect overriding any code declared in your class file. For example, each time you declare your anonymous class CountDownTimer as follows:
new CountDownTimer(t1, t2) {
public void onTick(long millisUntilFinished) {
}
};
This is overriding any code in the onTick() method that might be present in the CountDownTimer class file. This is correct when the onTick() method is abstract, but might not be what you had intended if this method is a regular class method. Best of luck.
I am trying to end an never ending circle. I need to call a void that is not static from another class. The reason that I do not make it static is that some things are very hard to make static. (Everything inside a static void needs to be static).
I am trapped in a circle where I need to call a non static void from another class. I can not make it static because it some code do not like to be passed.
Till now I solved it sort of by a handler:
public static void change(){
//This is called to change a boolean
start=true;}
private void startDone(){
int timeBetweenChecks = 50;
final Handler h = new Handler();
h.postDelayed(new Runnable(){
public void run(){
if (start==false){
startDone();
} else{
//Do something
}
}
}
}, timeBetweenChecks);
};
The problem with this is that I have to run a handler that is checking if something has changed pretty often(In my case).
Is there any way of calling the non static startDone() directly?
If you are asking if there is a way to call a non-static method of a class without instantiating an object of that class, then no.
If I don't own a dog, I cannot tell my dog to sit.
The answer to your question is: No, you cannot call a non-static method from a static method without an instance of the class containing the non-static method.
To solve your problem: maybe the best way would be to broadcast an intent from change().
Something like:
public static void change(Context c){
start=true;
c.sendBroadcast(new Intent("CHANGE_HAS_BEEN_CALLED"));
}
Then in the non-static code of your activity you can register a receiver like this:
IntentFilter filter = new IntentFilter();
filter.addAction("CHANGE_HAS_BEEN_CALLED");
registerReceiver(new BroadcastReceiver() {
#Override public void onReceive(Context context, Intent intent) {
if (start==false){
startDone();
} else{
//Do something
}
}
}, filter);
By definition, if startDone() is non-static, then it makes no sense to call it unless you've instantiated the class that contains it. A non-static method is an instance method, which means it can return a different result for every object of its enclosing type.
I think what you want is a class that only contains startDone(). You want to instantiate the class once for your entire application, and then be able to call startDone().
Suppose the class is called ItsDone. Instantiate it as a singleton, then return the singleton when you do a "new", and call startDone().
a handler that is checking
if something has changed pretty often (In my case).
Sounds like callback to me. You pass a piece of code to that "something", and this piece of code is executed by "something" whenever its state changes. If you have control over this "something", it's very easy to implement such behavior, if you don't (if "something" is a part of some library), it probably has this behavior implemented (of course, if it is well-designed).
Anyway, checking the state "something" by querying it every, say, 50 ms is not the way to go.
The accepted answear for this question is a better solution then the solutions that are already sugested. Hope this will help anybody googling.
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.
I have this code here to create a key binding:
KeyStroke k = KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0);
getInputMap(WHEN_IN_FOCUSED_WINDOW).put(k, k.toString());
getActionMap().put(k.toString(), new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
//put action here
}
});
The problem is I have 8 of these across my program. Each of these creates a separate class file to hold the abstract class. How would I rewrite this, if possible, to limit the amount of classes created. (I have searched for this, but reduce abstract classes doesn't come up with anything useful)
In addition to extension, suggested here by #EdC, you can use composition, as shown in this example in which the Action uses parameters specified to the constructor of an enclosing JButton. Also, one Action can forward its ActionEvent to another Action, as shown in this KeyPadPanel.
So what would help is if you update the question with perhaps some examples of where the duplication is. E.g. is it just the boiler plate of the anonymous inner class that's duplicated. If so you're stuck till java 8. Or is it that there is some significant portion of the method body that's duplicated?
In this case you could add an abstract super-class with the common code. This will actually increase the number of classes though which is not generally a problem. E.g.
private static abstract class MyBaseAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
// Do Common Stuff
// ....
doSpecificStuff(e);
}
protected abstract void doSpecificStuff(ActionEvent e);
}
Then subclass this instead of abstract action for your anonymous inner class.
I am writing a setonclick listner, and I want to be able to refer to that button so that I can change its properties. I.e. make it disabled?
I get thismessage:
Cannot refer to a non-final variable confirmButton inside an inner class defined in a different method
confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
confirmButton.setEnabled(false);
}
});
This because you are probably trying to access that button from an anonymous class that you use in this way:
button.addActionListener(
new MyListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//do your things on button }
}
}
);
This doesn't work because in Java anonymous classes cannot see variables declared in methods in which they are declared too since their scope are separated. The only way to let your class see it is forcing the final constraint which assures the compiler that the variable won't change after being initialized, allowing it to extend its scope to the anonymous classes.
To quickly fix this you can access the button from the ActionEvent inside the actionPerformed:
((JButton)e.getSource()).setEnabled(false)
Otherwise you have to concretely declare your ActionListener somewhere or declare the buttons outside the method with static or final attribute.. especially if you plan to modify some elements by an action that is fired by another element.
I would recommend against the getSource; the documentation doesn't promise that it will be your button. You can either make your button final in the scope, or use a more sophisticated class
public class ComponentRelevantOnClickListener implements View.OnClickListener {
private JComponent component;
public ComponentRelevantOnClickListener(JComponent component) {
this.component = component;
}
}
// then, in your code...
confirmButton.setOnClickListener(new ComponentRelevantOnClickListener(confirmButton) {
public void onClick(View view) {
component.setEnabled(false);
}
});
If you move toward a design of action and listener classes instead of anonymous subclasses, you get more chance for re-use (you can already see that ComponentRelevantOnClickListener could be replaced with a "DisableOnClickListneer" that you can use anywhere for this purpose), and your code will be overall better designed.
vars that are referenced within anonymous classes need to be defined as final in Java. Jon Skeet has a great example of this nestled within this article.
Anonymous inner classes can only access variables from the outer scope if they are final. Assuming you only assign to the confirmButton once, I suggest simply tagging it as final.
final JButton confirmButton = new JButton();