using { } after semicolon [duplicate] - java

This question already has answers here:
Anonymous code blocks in Java
(11 answers)
Closed 9 years ago.
In an example of android code given in a book regarding action bar, the sample given is as the following:
MenuItem menu1 = menu.add(0, 0, 0, "Item 1");
{
menu1.setIcon(R.drawable.ic_launcher);
menu1.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
How is using curly braces after a semi-colon possible? There is clearly some concept that I do not understand right here.

They are completely optional in this case and have no side-effect at all. In your example it sole serves to purpose of making the code more readable by intending the property assignment which belong to the control. You could as well do it without the braces. But if you'd use a tool to reformat your code, the indentation is likely gone.
However, if you have a Method and you put {} in there, you can create a new variable scope:
void someMethod() {
{
int x = 1;
}
// no x defined here
{
// no x here, so we may define a new one
string x = "Hello";
}
}
You can start a new scope anywhere in a Method where you can start a statement (a variable declaration, a method call, a loop etc.)
Note: When you have for example an if-statement you also create a new variable scope with that braces.
void someMethod() {
if (someThing) {
int x = 1;
}
// no x defined here
if (somethingElse) {
// no x here, so we may define a new one
string x = "Hello";
}
}
The same is true for while, for, try, catch and so on. If you think about it even the braces of a method body work in that way: they create a new scope, which is a "layer" on top of the class-scope.

It's called anonymous code blocks, they are supposed to restrict the variable scope.

Those are Initialization Blocks.
I don't think this is the correct usage of initialization block.
Apart from the example you have produced, these blocks are just used for initialization purpose. Click Here for detailed view.

Related

Problem binding a boolean property using a lambda [Java - JavaFX] [duplicate]

I want to be able to do something like this:
for(i = 0; i < 10; i++) {
//if any button in the array is pressed, disable it.
button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}
However, I get a error saying "local variables referenced from a lambda expression must be final or effectively final". How might I still do something like the code above (if it is even possible)? If it can't be done, what should be done instead to get a similar result?
As the error message says, local variables referenced from a lambda expression must be final or effectively final ("effectively final" meaning the compiler can make it final for you).
Simple workaround:
for(i = 0; i < 10; i++) {
final int ii = i;
button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}
Since you are using lambdas, you can benefit also from other features of Java 8, like streams.
For instance, IntStream:
A sequence of primitive int-valued elements supporting sequential and parallel aggregate operations. This is the int primitive specialization of Stream.
can be used to replace the for loop:
IntStream.range(0,10).forEach(i->{...});
so now you have an index that can be used to your purpose:
IntStream.range(0,10)
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Also you can generate a stream from an array:
Stream.of(button).forEach(btn->{...});
In this case you won't have an index, so as #shmosel suggests, you can use the source of the event:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));
EDIT
As #James_D suggests, there's no need of downcasting here:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
In both cases, you can also benefit from parallel operations:
IntStream.range(0,10).parallel()
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Stream.of(button).parallel()
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
Use the Event to get the source Node.
for(int i = 0; i < button.length; i++)
{
button[i].setOnAction(event ->{
((Button)event.getSource()).setDisable(true);
});
}
Lambda expressions are effectively like an annonymous method which works on stream. In order to avoid any unsafe operations, Java has made that no external variables which can be modified, can be accessed in a lambda expression.
In order to work around it,
final int index=button[i];
And use index instead of i inside your lambda expression.
You say If the button is pressed, but in your example all the buttons in the list will be disabled. Try to associate a listener to each button rather than just disable it.
For the logic, do you mean something like that :
Arrays.asList(buttons).forEach(
button -> button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
}
}));
I Also like Sedrick's answer but you have to add an action listener inside the loop .

java: Is it possible to set a lambda expression for an array of Buttons is a for loop? If so how?

I want to be able to do something like this:
for(i = 0; i < 10; i++) {
//if any button in the array is pressed, disable it.
button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}
However, I get a error saying "local variables referenced from a lambda expression must be final or effectively final". How might I still do something like the code above (if it is even possible)? If it can't be done, what should be done instead to get a similar result?
As the error message says, local variables referenced from a lambda expression must be final or effectively final ("effectively final" meaning the compiler can make it final for you).
Simple workaround:
for(i = 0; i < 10; i++) {
final int ii = i;
button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}
Since you are using lambdas, you can benefit also from other features of Java 8, like streams.
For instance, IntStream:
A sequence of primitive int-valued elements supporting sequential and parallel aggregate operations. This is the int primitive specialization of Stream.
can be used to replace the for loop:
IntStream.range(0,10).forEach(i->{...});
so now you have an index that can be used to your purpose:
IntStream.range(0,10)
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Also you can generate a stream from an array:
Stream.of(button).forEach(btn->{...});
In this case you won't have an index, so as #shmosel suggests, you can use the source of the event:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));
EDIT
As #James_D suggests, there's no need of downcasting here:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
In both cases, you can also benefit from parallel operations:
IntStream.range(0,10).parallel()
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Stream.of(button).parallel()
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
Use the Event to get the source Node.
for(int i = 0; i < button.length; i++)
{
button[i].setOnAction(event ->{
((Button)event.getSource()).setDisable(true);
});
}
Lambda expressions are effectively like an annonymous method which works on stream. In order to avoid any unsafe operations, Java has made that no external variables which can be modified, can be accessed in a lambda expression.
In order to work around it,
final int index=button[i];
And use index instead of i inside your lambda expression.
You say If the button is pressed, but in your example all the buttons in the list will be disabled. Try to associate a listener to each button rather than just disable it.
For the logic, do you mean something like that :
Arrays.asList(buttons).forEach(
button -> button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
}
}));
I Also like Sedrick's answer but you have to add an action listener inside the loop .

Modifying boolean value in Action Listeners [duplicate]

This question already has answers here:
The final local variable cannot be assigned
(6 answers)
Closed 8 years ago.
Code:
final boolean saveedit = true;
btnSaveEdit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (saveedit) {
// save function
if (txtMessage.getText().length() != 0) {
message = txtMessage.getText();
}
// show popup
JOptionPane.showMessageDialog(frmEventsAndProperties,
"Your last message is: " + message, "Message",
JOptionPane.PLAIN_MESSAGE);
btnSaveEdit.setText("Edit");
txtMessage.setEnabled(false);
saveedit = false;
} else {
// edit function
}
}
});
Error:
'The final local variable saveedit cannot be assigned, since it is defined in an enclosing type'.
Question:
I have seen other solutions for similar same errors, yet there must be a simple way to implement it - probably as simple as defining something earlier or moving it around.
I would appreciate any help.
Wherenver you want to use a variable inside an inner class (here ActionListener), you have two choices (regarding how you want to use it, modify(mutate) or access):
Using the final keyword with a local variable (it is not recommended for your case, since you want to modify your variable inside the inner class, not access only)
Using a field vairable, that need not be final (it is recommended)
As I mentioned, the seconed solution is feasible for you, since you want to do saveedit = false; which is mutating.
I completely agree with sager89. But i want to add one thing here which is.
If the keyword final is used for an instance variable, Then the final variable can be assigned only once and at the time of declaration or you will have to assign it in each and every constructor once.
This question is not a duplicate, the answer is for anyone wondering to simply move
final boolean saveedit = true;
to inbetween these lines:
btnSaveEdit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
That way it is not defined in an enclosing type :)

Java Reference Error

I am implementing a ray tracer and am having trouble with basic Java references :/ I have been staring at this for a while and I can't see the problem...
IntersectResult ir = new IntersectResult();
root.intersect(ray, ir);
if(r.material!=null)
System.out.println(result.material.diffuse);
// Doesn't print at all!!
// in my Node Class...
#Override
public void intersect(Ray ray, IntersectResult result) {
IntersectResult i = new IntersectResult();
for (Intersectable child:children){
child.intersect(ray, i);
if (result.t>i.t)
result = new IntersectResult(i);
}
if(result.material!=null)
System.out.println(result.material.diffuse); // prints correctly!
}
Basically my question is why is result.material null after the intersect method call when the print statements within the method call show that it is not?
This is a classic case of how the "pass-by-value" approach works and it is not specific to the code in question.
With respect to the latter, the ir reference passed to the intersect() method is redirected by the statement
result = new IntersectResult(i);
So, whenever the above statement is executed, the material object created is not saved in the original material variable, but to a local one, which is lost after the intersect method returns.
If you want to propagate that change, make the intersect() method always return the result object at its end and change the statement at the start of the code to
ir = root.intersect(ray, ir);
and correct the typo in the following if statement (it is ir.material, not r.material).

Not using an if statement in Java

This is a very odd, and quite specific question.
Ultimately I am trying to write a program convert that takes in java source, and transforms it such that it does not use (Among other things)
Arrays
Loops
User defined methods
If statements
This is a challenge that I set for myself, after my teacher told me that it was impossible to write a program without using these things.
I have most of these worked out, including function inlining and array substitution, however I cannot work out how to manage an if statement.
In C++ I'd use labels and gotos and maybe ?:, however Java does not support GOTO statements.
My question is this:
Given a section of code,
if(CONDITION)
{
//More code in here
}
How can transform it such that it is functionally the same, however does not use the if keyword. Note that loop structures are also out of the question.
Given this, it would be easy to create else and else if statements.
However I am also unsure of how to create loops using this, as there is no GOTO statement and methods are out of the question.
Edit:
Please note that switches are also not allowed, nor is recursion (Ruled out by the fact that you cannot define user methods, and a recursive main function wouldn't work with every program)
The ?: operator does not work for all situations. AFAIK you cannot call a void function with ?: as it wants to assign a value as part of its operation.
These conditions come from the IB Computer Science SL requires course, I am taking HL and as a class we were laughing at the 'mastery' factors for SL which include 'if' statements (And if fact 3/15 of them are 'User defined methods with params and return types) The challenge is effectively to FAIL a mastery test in SL while still producing a program that functions correctly.
Answer: (By bdares)
String result = (CONDITION)?"0":"A";
try{
Integer.parseInt(result);
//Condition is true
} catch(NumberFormatException e){
//Condition is false
}
if(A) {
X();
}
else{
Y();
}
can be converted to:
A?X():Y();
You can nest these all you want, or simply remove one side of the : and get a simple if. The conditionals are easy.
If you want it to work for void methods, here's a way:
String result = A?"0":"A";
try{
Integer.parseInt(result);
X();
} catch(NumberFormatException e){
Y();
}
I'm not sure it's possible to write an entire useful program without using an if statement. However, I think what your teacher may be getting at is that you can write code to follow the same "logical" path by using a more object-oriented approach in place of an if statement. For example:
public interface Moveable {
void move(int x, int y);
}
public class Ball implements Moveable {
private int x;
private int y;
public void move(int x, int y) {
this.x = x;
this.y = y;
}
}
public class NullMoveable {
public void move(int x, int y) {
// Do nothing.
}
}
... and then in your main application code:
Moveable mv = new NullMoveable();
// Move object; don't care if it's a Ball or a NullMoveable
// so no need to explicitly check with an if-statement.
mv.move(10, 50);
The principle here is that the fewer possible paths there are in your code (due to if statements) the easier it is to test and maintain.
You can use the conditional operator and a switch:
switch( CONDITION ? 1 : 0 )
{
case 1:
//... true code
break;
case 0:
//... false code
break;
}
For the loops you can unroll your code to some predefined maximum and use labeled breaks to jump out of the unrolled code early based on some condition. You can use break to end any code block in Java not just loops.
The Java language has no goto but the Virtual Machine has it, so you could of course also generate JVM instructions directly although this would be not much different from a regular Java compiler which also translates all ifs an loops into jump instructions.
In some cases, you can use bit manipulation. For example:
if(x > 0) // positive number
{
isPositive = true;
}
else // negative number
{
isPositive = flase;
}
is equivalent to:
isPositive = (x >> 31) == 0;
EDIT:
This is just an example, of course you can do much more complex bit manipulation with one statement instead of doing it using bunch of if statements.
If you were allowed to use anonymous inner classes (these probably classify as user-defined methods, but I'll let you be the judge):
if(COND) {
X();
} else {
Y();
}
becomes:
ifReplacement(COND,
new Runnable() { public void run() { X();}},
new Runnable() { public void run() { Y();}});
with signature:
public static void ifReplacement(boolean condition,
Runnable ifBranch,
Runnable elseBranch)
Of course, JDK8 lambdas would make this much nicer:
ifReplacement(COND, ()->X(), ()->Y());

Categories

Resources