I am currently in the process of making a calculator for Android (I am not using any tutorials) and am running into an issue.
I have this:
public void buttonOnClick(View v){
int operation;
switch (v.getId()){
case R.id.one:
numberBox.append("1");
break;
case R.id.two:
numberBox.append("2");
break;
case R.id.plus:
operation=1;
break;
case R.id.eq:
if (operation == 1){
// Print value
}
break;
default:
break;
}
}
Note that this is not the exact code, it is just a mockup.
The problem is, with the scope of the case, when the operation is set to 1, it is not set publicly and when I go to read it in the equals case, it is set back to 0.
How can I fix this problem?
You must be new in Java or any other programming language:
local variables are only used in the method they are declared in.
Whenever you go out of the method the variable is destroyed as well as its value.
So each time you enter a new variable is initialized.
To make this work just create a global class variable and use it or
Pass an object to the method that holds some int variable : the current operation, then read/write the variable using that object.
In your case its better to use a global class variable:
public class MyClass {
int operation;
public int getOperation() {
return operation;
}
public void setOperation(int value) {
this.operation = value;
}
.....
THEN:
....
public void buttonOnClick(View v){
...
case R.id.plus:
this.operation = 1;
break;
case R.id.eq:
if (this.operation == 1){
// Print value
}
break;
.....
Related
I instantiated a class so that the information that I will input is stored into it. But I having difficulty in displaying the information that is stored. When I compiled it will say that I havent initialized the variable.
public class REPORTS
{
public static void main(String[]args)
{
Scanner input = new Scanner(System.in);
int x=choices();
STUDENT stud;
EQUIPMENT equip;
RESERVATION reserve;
switch(x)
{
case 1:
{
// Code here for input
stud = new STUDENT(Studid,Studname,Studcourse,Studlevel);
break;
}
case 2:
{
// Code also here for input
equip = new EQUIPMENT(eqpmntid,qty,eqpmntname);
break;
}
case 3:
{
// Same goes for here input
reserve = new RESERVATION(studentid,equipid1,reservationdate,returndate);
break;
}
case 4:
{
stud.display(); // error here variable might not have been initialized
break;
}
case 5:
{
equip.display(); // same goes here
break;
}
case 6:
{
reserve.display(); // and also here
break;
}
}
Here is the detailed error message:
It seems that you have to change your program behavior; There is one possible syntactic way of casting a new Object to Student at beginning of your code but you will probably get a runtime error. To change the behavior you can initialize objects with arguments that are null or empty or dummy objects based on the arguments that your constructor get and then Set the fields to appropriate values in related switch case; For example your first lines should look like this:
Student stud = new Student("", Null, dummyObject);
In documentation it is said you could equally use if-else multiple times or switch-case:
int condition;
setCondition(int condition) {
this.condition = condition;
}
Either switch-case
switch (condition) {
case 1: print("one"); break;
case 2: print("two"); break;
or
if (condition == 1) { print("one"); }
else if (condition == 2) { print("two"); }
Next, conditionis declared volatile and method setCondition() is called from multiple threads.
If-else is not atomic and volatile variable write is a synchronizing action. So both "one" and "two" string could be printed in the last code.
It could be avoided if some method local variable with initial value was used:
int localCondition = condition;
if (local condition == ..) ..
Does switch-case operator hold some initial copy of variable? How are cross threads operations implemented with it?
From the Java specification on switch statements:
When the switch statement is executed, first the Expression is evaluated. [...]
This suggests that the expression is evaluated once and that the result is temporarily kept somewhere else, and so no race-conditions are possible.
I can't find a definite answer anywhere though.
A quick test shows this is indeed the case:
public class Main {
private static int i = 0;
public static void main(String[] args) {
switch(sideEffect()) {
case 0:
System.out.println("0");
break;
case 1:
System.out.println("1");
break;
default:
System.out.println("something else");
}
System.out.println(i); //this prints 1
}
private static int sideEffect() {
return i++;
}
}
And indeed, sideEffect() is only called once.
The expression is evaluated once when entering the switch.
The switch may use the result internally as many times as it needs to determine what code to jump to. It's akin to:
int switchValue = <some expression>;
if (switchValue == <some case>)
<do something>
else if (switchValue == <some other case>
<do something else>
// etc
Actually, a switch compiles to a variety of byte code styles depending on the number of cases and the type of the value.
The switch only needs to evaluate the expression once.
I have a superclass TetrisPiece, with subclasses for each variation of the piece, i.e.
class PieceI extends TetrisPiece{
}
class PieceJ extends TetrisPiece{
}
etc...
In a different class I have a switch statement based on a random number that creates a random piece
switch(rand){
//I
case 1: {
PieceI pieceI = new PieceI();
break;
}
//T
case 2: {
PieceT pieceT = new PieceT();
break;
}
etc...
default:
break;
}
My intention is to extract the piece that is generated from the scope of the switch statement so I can use it later on in the class.
The switch method obviously does not work because of the scope issue, and I cannot create a superclass array outside of the switch statement because I would have no ability to cast the indices due to randomization.
Any help is appreciated.
Create an instance of the superclass TetrisPiece, and then assign PieceT, PieceI, etc to it inside the switch statement.
TetrisPiece piece;
switch(rand){
//I
case 1: {
piece = new PieceI();
break;
}
//T
case 2: {
piece = new PieceT();
break;
}
etc...
default:
break;
}
I'm writing a program to calculate GPA. It consists of several panels. The first panel
tells the user to specify the number of courses so that Comboboxes (gradeCombo),(hourCombo) and Textfields will be added dynamically to the second panel . Everything is fine to this point but the problem is with the listeners. In early stages, I registered the event listeners for these comboboxes individually for every element in the array and it resulted in 900 lines of codes, but it worked fine and all my results were correct. To enhance my code I'm trying to write a for loop for registering the events for the comboboxes and so far I couldn't succeed.
I tried to write the handling code as anonymous inner class and as separate inner class, Here is my last try:
for(i = 0; i<courseN;i++)
{
hourCombo[i].addItemListener(new HoursHandler());
gradeCombo[i].addItemListener(new GradeHandler());
}
public class HoursHandler implements ItemListener
{
public void itemStateChanged(ItemEvent event)
{
if(event.getStateChange()==ItemEvent.SELECTED)
{
String hour;
hour = (String) hourCombo[i].getSelectedItem();
currentHour[i]=Integer.parseInt(hour);
aquiredHours=aquiredHours+currentHour[i] prevHour[i];
prevHour[i]=currentHour[i];
}
}
}
public class GradeHandler implements ItemListener
{
public void itemStateChanged(ItemEvent event)
{
if(event.getStateChange()==ItemEvent.SELECTED)
{
String grade;
grade=(String) gradeCombo[i].getSelectedItem();
switch(grade)
{
case "A+":
currentPoint[i]=5*currentHour[i];
break;
case "A":
currentPoint[i]= 4.75 * currentHour[i];
break;
case "B+":
currentPoint[i]= 4.5 * currentHour[i];
break;
case "B":
currentPoint[i]= 4 * currentHour[i];
break;
case "C+":
currentPoint[i]= 3.5 * currentHour[i];
break;
case "C":
currentPoint[i]= 3 * currentHour[i];
break;
case "D+":
currentPoint[i]= 2.5 * currentHour[i];
break;
case "D":
currentPoint[i]= 2 * currentHour[i];
break;
case "F":
currentPoint[i]= 1 * currentHour[i];
break;
}
aquiredPoints=aquiredPoints+currentPoint[i]-prevPoint[i];
prevPoint[i]=currentPoint[i];
}
}
}
I get a NullPointerException for this statement:
hour = (String) hourCombo[i].getSelectedItem();
and everything goes wrong, none of my variables is updated and I cannot calculate the GPA..
It's hard to tell from the posted code what is wrong there. However, I assume that i is declared as an instance variable. In this case, the loop for(i = 0; i<courseN;i++) will change the value of this instance variable. Afterwards, all the listeners will internally use i with the last value that it received in the for-loop.
To circumvent this, you can declare an instance variable for each listener instance. So you can change your listener classes like this:
public class HoursHandler implements ItemListener
{
private final int index;
HoursHandler(int index)
{
this.index = index;
}
#Override
public void itemStateChanged(ItemEvent event)
{
// Use the "index" here:
String hour = (String) hourCombo[index].getSelectedItem();
currentHour[index]=Integer.parseInt(hour);
...
}
}
(similarly, introduce such an index for the GradeHandler).
Then, when you create the listeners, you can pass to each instance the index that it refers to:
// Note: "i" is declared here, and should NO longer
// be an instance variable!
for(int i = 0; i<courseN;i++)
{
hourCombo[i].addItemListener(new HoursHandler(i)); // Use "i" as "index"
gradeCombo[i].addItemListener(new GradeHandler(i)); // Use "i" as "index"
}
I assume that there might be some more elegant solutions, but this is one possible solution, solely based on the code that you provided.
It appears that i is a member field in your outer class. When your listener is executed, and your listener
hour = (String) hourCombo[i].getSelectedItem();
this statement will use whatever value i happens to be in this outer class. And after you execute your for loop, i will probably be equal to courseN, unless there's something else changing it somewhere else. In any case, it doesn't use the value that i held when you set up the listener, because you did nothing to tell it to use that value.
A simple way to fix this is to construct your listeners by giving it the index you want them to use:
public class HoursHandler implements ItemListener
{
private final int index;
public HoursHandler(int index) {
this.index = index;
}
public void itemStateChanged(ItemEvent event)
{
if(event.getStateChange()==ItemEvent.SELECTED)
{
String hour;
hour = (String) hourCombo[index].getSelectedItem();
and use index instead of i everywhere in the listener. When you construct the listener, it will store the index you want, and then the code will use that instead of the current value of i. Similarly for GradeHandler. Then
for(i = 0; i<courseN;i++)
{
hourCombo[i].addItemListener(new HoursHandler(i));
gradeCombo[i].addItemListener(new GradeHandler(i));
}
Note that the index you want the listeners to use is now passed as a parameter to the listeners' constructors.
EDITED to use final on the index member--plagiarized from Marco13's good idea.
Hi Im currently learning Java and Im doing an assignment where I need to *create a Menu that calls several methods. I have 3 classes (Contacto,Agenda and Principal). My assignment is trying to evaluate Constructors and Arrays and some other basic theory.
My menu error is: Principal.java:34: error: cannot find symbol while(opcion!=4).*
I already check and my variable "opcion" is declared.
public class Principal{
private static void imprimeMenu(){
Scanner input = new Scanner(System.in);
String mainMenu = ("Choose an option from the menu: \n"
+ "1. Add contact\n"
+ "2. Find contact\n"
+ "3. Search contact\n"
+ "4. Exit");
do{
System.out.println(mainMenu);
int opcion = input.nextInt();
switch(opcion){
case 1:
break;
case 2:
System.out.println("Search");
break;
case 3:
System.out.println("Erase");
break;
default:
System.out.println("Command not recognize");
break;
}
}
while(opcion!=4);
}
public static void main(String[] args){
imprimeMenu();
}
}
And inside the my cases I need to call 3 methods (Add, Search and Erase contacts) that are inside a class called Agenda. The 3 methods are void and receive a parameter. I tried but I get an error where it says I need some parameters:
case 1:
Agenda.addContacto(); and also tried Agenda.addContacto(contacto);
My Agenda class looks like this
public class Agenda{
private Contacto [] contactos;
private int numContactos;
public Agenda(){
this.contactos = new Contacto[10];
this.numContactos = 0;
}
public Agenda(int x){
this.contactos = new Contacto[x];
this.numContactos = 0;
}
public void addContact(Contacto contact){
if(numContactos<contactos.length){
this.contactos [numContactos] = contact;
numContactos+=1;
}
}
Your problem is that opcion is defined inside the loop, so it's scope ends before the closing while.
Move the definition outside the loop to fix the problem:
int opcion = 0;
do{
System.out.println(mainMenu);
opcion = input.nextInt();
switch(opcion){
case 1:
break;
case 2:
System.out.println("Search");
break;
case 3:
System.out.println("Erase");
break;
default:
System.out.println("Command not recognize");
break;
}
} while(opcion!=4);
The correct call of Agenda.addContacto method is indeed Agenda.addContacto(contacto). You need to make sure that contacto is set to an instance of Contacto object before making the call.
You have 2 issues with these programme
1.You need to declare option variable before the while loop.
2.If you want to call Agenda.anyMethod() you need to create an instance/object of the class otherwise you can declare the class Agenda as static.then you can directly call the method as
Agenda.addContacto();