Java : is there any way that this code can be improved - java

I have this coding inside my java file .
This code basically receives an int value and sets a char value for an Object
Student st = new Student();
if (attributeName.equals("Grade")) {
int sidevalue = Integer.parseInt(attribute.getValue()); // This returns an int value , and this value needs to be converted into char later as shown
if(sidevalue==1)
st.grade=1;
else if(sidevalue==2)
st.grade=2;
else if(sidevalue==5)
st.grade=3;
}
class Student
{
char grade ;
}

Integer.parseInt throws an exception, if the attribute name is not a number. Catch it and handle the error.
The Student class should be made public and go to a separate java file
The grade field should be an int (your passing numbers)
Alternatively - if you need to store chars, you may have to say st.grade = '1'; (to pass a '1' instead of a 0x01)
The grade field should be private, use getGrade and setGrade methods to read an write the property
I don't understand the meaning of "sidevalue" - if it does not have a well known meaning in the domains context, then consider renaming it.
The local variable st should be renamed to student
the if-else-if chain could be replaced by a switch-case statement.

You could use a map
Map<Integer, Integer> gradeMappings = new HashMap<Integer, Integer>();
gradeMappings.put(1,1);
gradeMappings.put(2,2);
gradeMappings.put(3,5);
if (attributeName.equals("Grade")) {
int sidevalue = Integer.parseInt(attribute.getValue());
st.grade = gradeMappings.get(sidevalue);
}
In real life, you'd want to add some exception checking for when the attribute value is not a key in the map. You could also make the default behaviour to use the parsed attribute value as the grade, and only override the value if an appropriate entry is present in the map.

A switch case check here statement could avoid multiple if else indentation!
switch(sidevalue){
case 1: st.grade = 1;
break;
case 2: st.grade = 2;
break;
case 5: st.grade = 3;
break;
default: break;
}
There is no significant execution difference in running between if-else and switch.
Observed differences may be due to the sample space of the particular code you are running.
In the little code snippet you provide there is not a best choice, except that switch statement provides improved readability.
Check these links for further details:
Is "else if" faster than "switch() case"?
if-else vs switch
When to use If-else if-else over switch statments and vice versa

Look into the control keyword switch. This will somewhat alleviate this style of coding.

The best way to improve this code is to write a test for it.
Problems at this stage: 'grade' should be private.
Grade is probably a first class object.
How do you plan to support other grades? Say 4 or 6? What happens if sidevalue comes back with invalid value?

Others have suggested minor syntax changes (which may be helpful), but I think you are best thinking about this in an object-oriented sense, encapsulating this logic into the student class itself, that way you will only need to write it once. If you need different logic for different scenarios you can always use inheritance and override setGrade.
Student st = new Student();
st.setGrade(Integer.parseInt(attribute.getValue()))
class Student{
private char grade ;
public setGrade(int sidevalue){
if(sidevalue==1)
grade=1;
else if(sidevalue==2)
grade=2;
else if(sidevalue==5)
grade=3;
else
throw new IllegalArgumentException();
}
public char getGrade(){
return grade;
}
}

If you have canonical String values stored in attribute.getValue() then you can remove integer parsing and simply compare string values
String sidevalue=attribute.getValue()
if(sidevalue=="1"){
}else if(sidevalue=="2"){
}...
Refer to String.intern method for more details. This will help improve performance of your program.

1) Start using coding formats. Its advisable to use objStudent rather than some 'st'.
2) There is no use of creating int sidevalue. Directly use a switch case as give below:
switch(Integer.parseInt(attribute.getValue()))
{
case 1:
----
.
.
.
and so on...
}

Related

Return inside a method one or two arrays

Its not duplicated i have read all and nothing suite in my case so please read it and answer it.I have two arrays.One is Vehicle and the other is pin.This is a part of code and it is only the method.
First question :
if i have declare the arrays on the same main out of
this method the way i pass them on the method is right?With other words the parameteres
are good or need (int vehicle[],int pin[]) or something else?
Second question +=
i dont know what it does but i think that in the array pin it takes
as an ecample the pin[1] cost has 10.The number 10 is taken by
getcostosvehicle();(we put it from userinput) so when the array fills
and it hasnt any slot then the costs will be finished.As a result will
have lets say the ended slot is 20 in pin[20] lets say it has 350.The
return statement will give us only the last cost?It would be better to
write return pin[i]; so in that way it will return all the pin with
the whole costs of each one slot,am i right?
Third question
On this code and that i want to write me as an answer could you return
two arrays?I mean return pin[i],vehicle[i]; not only return pin[i];.If
yes,could you do an answer and doesnt need to fill in the vehicle
array.Just to show me if this can happen.
public static int getallcosts(vehicle[],pin[]) {
int costos = 0;
for(int i =0; i < pin.length; i++) {
costos += pin[i].getcostosvehicle();
}
return costos;
}
if i have declare the arrays on the same main out of this method the way i pass them on the method is right?With other words the parameteres are good or need (int vehicle[],int pin[]) or something else?
I'm not sure I understand you correctly but of course getallcosts(vehicle[],pin[]) won't compile, i.e. you need to define the type of the arrays (or the names if vehicle and pin would actually be the types).
It would be better to write return pin[i]; so in that way it will return all the pin with the whole costs of each one slot,am i right?
No, you can only have one return value. If you want to return multiple values then you need to wrap them in an object (array, list, pojo, etc.).
On this code and that i want to write me as an answer could you return two arrays?
See the part above: if you want to return multiple arrays you need to add them so some object and return that object. Since you didn't provide the types for the arrays I'll use another example:
class Result {
String[] strings;
int[] numbers;
}
Result someMethod() {
Result r = new Result();
r.strings = new String[]{"a","b","c"};
r.numbers= new int[]{1,2,3};
return r;
}
First question:
If you are calling a method (so you're not defining it) yuo can write parameters as you do, without type.
Otherwise you need to specify type. In this case you are defining a new method so you need to specify type of parameters.
Second question:
'+=' it's like write
costos = costos + pin[i].getcostosvehicle();
So you will add to the current value of 'costos' the 'costos' of vehicle retrieved by 'getcostosvehicle()';
Third question:
As i know you can't return two Objects of any type in return statement.
So you'll need to reorganize your code to do operation first on an array and return it and then on the other one and return it.
For example you can do a method that have as parameter a generica array do some logic inside and then return it. You will call this method for the first array and then for the second.
Example:
public int[] method(int[] array){
/*do something
*/
return array;
}
Then you will call:
firstArray = method(firstArray);
secondArray = method(secondArray);
If you want more, or i have to change something comment please.

Android switch by values from strings.xml

I'm new with Android and want to understand another one moment. I've got a strings.xml, which values I use in activity.xml. How use this values from JAva code in switch block?
private void gotoActivity(CharSequence text) {
switch (text.toString()) {
case getString(R.string.title_activity_first):
break;
case RADIO_BUTTON_SECCOND:
break;
}
}
Not compiles 'cos of "Constant expression required". But the main benefit of strings.xml - is string constants in one place.
Help plz.
Unfortunately you cannot use resource string in switch-case. You have two options. Choose anyone...
use static final String in your activity.
Example: Initialize the strings
public static final String TITLE_ACTIVITY_FIRST = "activity_title";
public static final String RADIO_BUTTON_SECCOND = "radio_button_second";
Then you can use the TITLE_ACTIVITY_FIRST in switch case. like,
switch(text.toString()){
case TITLE_ACTIVITY_FIRST: break;
case RADIO_BUTTON_SECOND: break;
}
No error will show!
use if-else. You can then use your resource strings.
Example:
if(text.toString().equals(getString(R.string.title_activity_first))){
//your code in case of 1st condition
}else if(text.toString().equals(getString(R.string.title_activity_second))){
//your code in case of 2nd condition
}
The second might look clumsy. But you wont have to change your code too much. Whereas the first one might look quite handy and you can easily modify later. Hope it helps!
You can not use getString(R.string.title_activity_first) since it returns a localised string from the application's package's default string table.So the result will be different based on the locale and hence it won't be a constant.You can not even get a particular local string using getString() method.Better to use a static final String filed instead.Please refer here

How do I call a method on an object when it is outside the scope of where the object was created [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have an ArrayList called "filmList" in a separate class called actors, I want to use case 2 in the switch to call newActor.filmList.get(i); but I keep getting object may not be initialized errors from the compiler. If I put the same line in switch case 1 it works fine, but in case 2 i get the error. Can someone please tell me how I can call a method on the object from outside where the constructor creates the newActor object, I will be eternally grateful, it is doing my head in and my lecturer is terrible at explaining things. Thanks.
public class ActorsMain {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
String fName="";
String lName="";
String address="";
int age;
String filmEntry="";
String code="";
ArrayList actors = new ArrayList();
ArrayList films = new ArrayList();
int choice=0;
while(choice!=3){
System.out.println("Make your selection.\n1. Add Actor\n2. List Actors");
choice=kb.nextInt();
switch (choice){
case 1:
System.out.println("\nPlease enter the actors first name:");
fName=kb.next();
System.out.println("Please enter the actors second name:");
lName=kb.next();
System.out.println("Please enter the actors address:");
address=kb.next();
System.out.println("Please enter the actors age:");
age=kb.nextInt();
kb.nextLine();
for(int a=0;a<10;a++){
System.out.println("Please enter the actors film.\nType 'Stop' to stop entering films.");
filmEntry=kb.nextLine();
//kb.nextLine();
if(filmEntry.equalsIgnoreCase("stop")){
break;
}
else {
Films filmObject = new Films(filmEntry,code);
films.add(filmObject);
}
}
Actors newActor = new Actors(fName,lName,address,age);
actors.add(newActor);
newActor.setFilm(films);
films.clear();
break;
case 2:
break;
}
}
}
}
You will have to declare newActor outside the scope of the switch statement. Inside case 2 of your switch, newActor doesn't exist.
int c = 0;
switch (c) {
case 1:
Object obj = new Object();
break;
case 2:
System.out.println(obj.toString()); // obj only exists in case 1
break;
}
This is actually a little peculiar and maybe somebody else can explain why, but the error you are getting seems to be particular to the switch statement. If you try to do the following:
int c = 0;
if (c == 1) {
Object obj = new Object();
} else if (c == 2) {
System.out.println(obj.toString());
}
You will get a different error that says "cannot find symbol" which is more to the point. Apparently cases inside a switch share scope such that they can "see each other". I assume this is related to the sans-break fall-through. Switches are all one block and the cases only determine the entrance point.
I'm not sure what you are trying to do to tell you where to put your newActor declaration but the point is right now case 2 in your switch can't use it. It only exists inside case 1.
Also you shouldn't use a switch for such a long statement. You should at least refactor it so it uses if statements. Switches are just not meant for this kind of thing. They are meant for long conditions with lots of possibilities and small statements for each case:
char operator = '*';
int leftNumber = 5;
int rightNumber = 9;
switch (operator) {
case '+': System.out.println(leftNumber + rightNumber);
break;
case '-': System.out.println(leftNumber - rightNumber);
break;
case '*': System.out.println(leftNumber * rightNumber);
break;
case '/': System.out.println(leftNumber / rightNumber);
break;
case '^': System.out.println(Math.pow(leftNumber, rightNumber));
break;
default: System.out.println("Unknown operator");
}
As a long side note, you are not passing a type parameter to your ArrayLists. Java doesn't know that your ArrayLists contain Actors and Films unless you say so:
ArrayList<Actors> actors = new ArrayList<Actors>();
ArrayLists and other generics are supposed to be initialized with a bracketed parameter of <E> where E is the desired class type of the elements in the array.
The type parameter is a little bit like extending a class. The ArrayList class will have E all over the source code and when you pass Actor in to the E parameter, E is replaced with Actor.
class ArrayList<E> {
Object[] array = new Object[some_length];
public E get(int index) {
return (E)array[index];
}
}
becomes
class ArrayList<Actor> {
Object[] array = new Object[some_length];
public Actor get(int index) {
return (Actor)array[index];
}
}
Note that even then whether or not Java knows that that ArrayList contains Actors while the application is running is still vague due to the way generics are implemented. They are implemented using something called erasure. At runtime there is no way to know that the ArrayList is of the Actor type.
If you declare them with the type parameter, you will be able to access their elements using get() as Actors and Films in your code which you won't be able to right now.
In other words you can do this:
System.out.println(actors.get(aIndex).filmList.get(fIndex));
Which it looks like you are starting to try to do under case 2 but you also won't be able to do at the moment. Without <Actor> or <Film> it will tell you "cannot find symbol" or "incompatible types" because the ArrayList holds an array of Object without the type parameter. (It's still an array of Object with the type parameter but you can use it like the type you pass in.)
Im guessing your Actor class has an ArrayList called filmList and you want to get the value from it at a certain position. If that is the case you should probably create a getFilmListIndex(int pos) method in your Actor class that takes in an index value and returns whatever object your film list stores. Assuming your filmList stores String it might look something like this.
public String getFilmListIndex(int pos)
{
return filmList.get(i);
}
Then call this method from your ActorMain class.
String result = newActor.getFilmListIndex(i);
age is uninitialized when you declare it. In case 1 it will be set, but in case 2 it is not clear that it has been set yet.
You could assign it a dummy value when you declare it, but in general it is better practice to mostly scope variables only where they are actually being used & have a valid value.
That would suggest putting all the actor details into a separate method or (not as nice) inside {} curly brackets, and only declare them as you are assigning the value. Having accessible variables hanging around with undefined, dummy or outdated values is provably less correct than only having a variable declared with a scope equivalent to when it's value is valid & applicable.

How to eliminate hardcoding when switch case like conditions are used by function to be called

Consider a common validation function.
private static void check(int[][] m1, int[][] m2, char op) {
if (m1 == null || m2 == null) {
throw new NullPointerException("No input matrix should be null.");
}
/**
* Switch case was thought to be beneficial in case of future extensibility.
* http://en.wikipedia.org/wiki/Switch_statement#Advantages_and_disadvantages
*/
switch (op) {
case 'a' : if (m1.length != m2.length && m1[0].length != m2[0].length) throw new IllegalArgumentException("bla bla"); else break;
case 'm' : if (m1[0].length != m2.length) throw new IllegalArgumentException("bla bla"); else break;
}
}
Here if 'a' is passed then validation ensures matrices are good for multiplication, if m is passed its good for addition. However, I can see several loopholes in this code, eg: 1. the client needs to be aware of what to pass as parameter 2. Client may pass in a wrong character. A global constants or enums are my possible solutions.. Is there a better / more common method to solve this problem ? Thanks,
Enums will be much better than global constants because with a global constant it's still easy pass in a bad value. I'm assuming your values would be ints, so the user could pass in any int. Enums will do typechecking for you, so that's a plus.
However, why don't you just refactor this into 2 different methods: checkMult vs checkAdd? These are doing totally different checks, so there's no reason (as far as I can see) they shouldn't be different methods.
Don't write one method to check two entirely different things. This should be two methods, one for multiplication and one for addition.

How do i compare a variable's data with the data in an array?

I have an int array:
int[] BankClientNumber = new int[10];
I want the user to input an id number...
findidd = JOptionPane.showInputDialog ("\nEnter ID number:\n\n");
findid = Integer.parseInt(findidd);
...and have the program look through the data of the array, match the id number and print the other details of the client.
How do I compare the variable's data with that of the array?
Any suggestions will be much appreciated.
You want to know if the int array contains the number, this is probably the esiest way:
Arrays.asList(BankClientNumber).contains(findidd)
Note: As an advice I would use a Collection as BankClientNumber for instance a Set.
You would be better off storing the Bank Client Numbers in a Collection rather than an array. Collections have nice methods for searching, sorting etc.
If you don't want to use a collection for whatever reason it's simply:
boolean exists = false;
for(int check: bankClientNumber) {
if(check == findid) {
exists = true;
break;
}
}
if(exists) {
//do something
}
FYI Java coding conventions dictate that variables start in lowercase so BankClientNumber should be bankClientNumber.
Method names also start with lowercase and object names start with Uppercase.
It is also recommended to use camel cases (youShouldUseCamelCase or YouShouldUseCamelCase) and avoid underscores in method and object names. IMHO use camel case for variables as well.

Categories

Resources