Using methods inside a constructor - java

I'm new to learning Java and was trying to understand OOP, but I can't seem to find anyone who has the same exact question. My question is, is it okay to use methods inside a constructor like the example here:
package ezrab.nl;
public class Calculations {
private int number;
private int multiplier;
private String operator = "";
public Calculations(int number, String operator, int multiplier) {
this.number = number;
this.operator = operator;
this.multiplier = multiplier;
switch (getOperator()) {
case "+":
System.out.println(getNumber() + getMultiplier());
break;
case "-":
System.out.println(getNumber() - getMultiplier());
break;
case "*":
System.out.println(getNumber() * getMultiplier());
break;
case "/":
System.out.println(getNumber() / getMultiplier());
break;
case "%":
System.out.println(getNumber() % getMultiplier());
break;
default:
System.out.println("Something went wrong.");
}
}
public int getNumber() {
return this.number;
}
public void setNumber(int number) {
this.number = number;
}
public int getMultiplier() {
return this.multiplier;
}
public void setMultiplier(int multiplier) {
this.multiplier = multiplier;
}
public String getOperator() {
return this.operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
}
So I'd like to know, is it allowed to use the methods I've created inside the constructor.
EDIT: I'd like to point out that the program is working. I just want to know if I followed the rules to OOP correctly.

Put behavior of object separately with creation:
public class Calculations {
private int number;
private int multiplier;
private String operator = "";
public Calculations(int number, String operator, int multiplier) {
this.number = number;
this.operator = operator;
this.multiplier = multiplier;
}
public int getNumber() {
return this.number;
}
public void setNumber(int number) {
this.number = number;
}
public int getMultiplier() {
return this.multiplier;
}
public void setMultiplier(int multiplier) {
this.multiplier = multiplier;
}
public String getOperator() {
return this.operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public void print() {
switch (getOperator()) {
case "+":
System.out.println(getNumber() + getMultiplier());
break;
case "-":
System.out.println(getNumber() - getMultiplier());
break;
case "*":
System.out.println(getNumber() * getMultiplier());
break;
case "/":
System.out.println(getNumber() / getMultiplier());
break;
case "%":
System.out.println(getNumber() % getMultiplier());
break;
default:
System.out.println("Something went wrong.");
}
}
}

is it allowed to use the methods I've created inside the constructor.
It's allowed but dangerous as you need to know if everything which should be set, has been set. It's better to use the value which was passed as a parameter.
However your switch should be in the constructor as you can change the operator or operand later. I would have a separate method for it.
NOTE: Having a field called multiplier is confusing as it's not a multiplier in most cases.

Yes it's allowed but better way is to separate the behavior and construction of object. Constructors are mainly used to set properties of the class.

To better code in OOP (Object Oriented Programming) this concept you are referring to is known as Encapsulation. You can generally code in the way you are saying to do it. However, down the line when the application gets bigger, it would make your life much easier if you follow established design patterns. Please review this link for the Encapsulation concept:
https://www.tutorialspoint.com/java/java_encapsulation.htm

Related

How does OpenClover count branches?

The code:
public class Branches {
public double justOneIf(int a) {
double result;
if (a > 0) {
result = 1.0d;
} else {
result = -1.0d;
}
return result;
}
public String switches(int x) {
String result;
switch (x) {
case 0: {
result = "zero";
break;
}
case 1: {
result = "one";
break;
}
case 2: {
result = "two";
break;
}
default: {
result = "kill all humans";
}
}
return result;
}
public int deepIf(int x) {
int y;
if (x == 0) {
y = 1;
} else {
if (x > 0) {
y = 2;
} else {
y = 3;
}
}
return y;
}
}
In OpenClover (version 4.4.1) report I got metrics for this class:
Code metrics
Branches:6
...
Why six branches here? How does clover count it?
I've got it. It's pretty simple: one "IF" means 2 branches. Just it.
Branch coverage
Branch coverage (or 'decision coverage') is a code coverage metric
that measures which possible branches in flow control structures are
followed. Clover does this by recording if the boolean expression in
the control structure evaluated to both true and false during
execution.

TimeUnit on floating values

I created method like this, where I have 2 inputs.
first is type (e.g. 'd', 'h')
second is value (e.g. "15", "0.5")
I created function to convert it to minutes like this:
public Float toMinutes(char type, String value) {
Float minutes = 0f;
switch (type) {
case 'd': {
minutes += Integer.parseInt(value) * 1440;
break;
}
case 'h': {
minutes += Float.parseFloat(value) * 60;
break;
}
case 'm': {
minutes += Integer.parseInt(value);
break;
}
default: {
return 0f;
}
}
return minutes;
}
I decided to refactor it, because those multiplication looks "ugly" for me. I found a better solution called TimeUnit.
public Long toMinutes(char type, String value) {
Long minutesCounted = 0l;
TimeUnit tu = TimeUnit.MINUTES;
switch (type) {
case 'd': {
minutesCounted += tu.convert(Long.parseLong(value), TimeUnit.DAYS);
break;
}
case 'h': {
minutesCounted += tu.convert(Long.parseLong(value), TimeUnit.HOURS);
break;
}
case 'm': {
minutesCounted += tu.convert(Long.parseLong(value), TimeUnit.MINUTES);
break;
}
default: {
return 0l;
}
}
return minutesCounted;
}
The problem is that this converter allow only long values, so now it works only on inputs like 15h and it will not work on inputs like 1,5h. Any ideas how to improve my solution to work with floating numbers?
Instead of using magic constants, you could use TimeUnit to figure out the conversion rate for 1 d, h, etc. to minutes like this
public float toMinutes(char type, String value) {
switch (type) {
case 'd':
return Integer.parseInt(value) * TimeUnit.DAYS.toMinutes(1);
case 'h':
return Float.parseFloat(value) * TimeUnit.HOURS.toMinutes(1);
case 'm':
return Integer.parseInt(value);
default:
return 0;
}
}

program converting infix to postfix notation [duplicate]

This question already has answers here:
Handling parenthesis while converting infix expressions to postfix expressions
(2 answers)
Closed 5 years ago.
I've been working on a school assignment that requires us to convert a string from infix notation to postfix notation. We have to do this by using a stack implementing an array.
Here is my code for the actual conversion class:
package practice;
public class Practice {
public static String infixToPostfix(String infix)
{
Practice2 operatorStack = new Practice2();
String output = "";
char curChar;
String input = infix;
boolean isOperator=false;
boolean empty=true;
int curCharPrecedence=0;
int topOfStackPrecedence=0;
for(int i =0; i<input.length();i++){
curChar = input.charAt(i);
switch(curChar){
case '+': isOperator=true;
case '-': isOperator=true;
case '/': isOperator=true;
case '*': isOperator=true;
case '(': isOperator=true;
case ')': isOperator=true;
break;
default: isOperator=false;
}
if(!isOperator){
output=output+curChar;
}
else if(isOperator){
output+=" ";
if(empty){
empty=false;
operatorStack.Push(curChar);
}
else if(!operatorStack.empty()){
switch(curChar){
case ')': topOfStackPrecedence=0;
case '+': curCharPrecedence=1;
case '-': curCharPrecedence=1;
case '/': curCharPrecedence=2;
case '*': curCharPrecedence=2;
case '(': topOfStackPrecedence=3;
}
switch((Character) operatorStack.peek()){
case ')': topOfStackPrecedence=0;
case '+': topOfStackPrecedence=1;
case '-': topOfStackPrecedence=1;
case '/': topOfStackPrecedence=2;
case '*': topOfStackPrecedence=2;
case '(': topOfStackPrecedence=3;
}
if(curCharPrecedence>topOfStackPrecedence){
operatorStack.Push(curChar);
}
else{
while(!operatorStack.empty()&&topOfStackPrecedence>curCharPrecedence){
output+= operatorStack.pop();
output+=" ";
if(!operatorStack.empty())
switch((Character) operatorStack.peek()){
case ')': topOfStackPrecedence=0;
case '+': topOfStackPrecedence=1;
case '-': topOfStackPrecedence=1;
case '/': topOfStackPrecedence=2;
case '*': topOfStackPrecedence=2;
case '(': topOfStackPrecedence=3;
}
}
operatorStack.Push(curChar);
}
}
}
}
while(!operatorStack.empty()){
output+=" ";
output+= operatorStack.pop();
}
return output;
}
public static void main(String[] args)
{
System.out.println(infixToPostfix("a+b*c"));
}
}
Then here is my code for the stack class:
package practice;
import java.util.EmptyStackException;
public class Practice2<T> extends Object{
public T[] stack = (T[]) new Object[10];
int topOfStack =-1;
public Practice2()
{
stack = (T[]) new Object[10];
}
public Practice2(int capacity)
{
stack = (T[]) new Object[capacity];
}
public T Push(Object item)
{
if(topOfStack<=stack.length-1){
T[] temporary = (T[]) new Object[stack.length];
for(int i=0; i<stack.length-1;i++){
temporary[i]=stack[i];
}
stack = (T[]) new Object[temporary.length+10];
for(int i=0; i<temporary.length-1;i++){
stack[i]=temporary[i];
}
}
topOfStack++;
stack[topOfStack]= (T) item;
return (T) item;
}
public T peek()
{
return stack[topOfStack];
}
public T pop()
{
if(topOfStack==-1){
throw new EmptyStackException();
}
else
return stack[topOfStack--];
}
public boolean empty()
{
if(topOfStack==-1)
return true;
else
return false;
}
public int size(){
return topOfStack+1;
}
}
Whenever I try to run this I get the following error message:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at practice.Practice2.peek(Practice2.java:49)
at practice.Practice.infixToPostfix(Practice.java:53)
at practice.Practice.main(Practice.java:106
It appears that the problem is my peek method in the stack class, but I'm not entirely sure.
Any help is greatly appreciated, I've spent way to much time on this program and badly need someone else to take a look at it.
The error is quite clear ArrayIndexOutOfBoundsException ....
and the reason is here:
switch((Character) operatorStack.peek()){
you are doing a peek before a push... more specific: you are trying to get the element of the array located at the topOfStack =-1 and that is the reason of the exception...

Extracting a common code fragment in Java

I am quite new to Java and I am making a string parsing calculator. I have a piece of code which has some almost identical fragments which I would like being extracted into some method or so, but I could not come up with an idea how to do it.
Here is a piece of code:
case '+':
current_priority = 1;
if (last_priority < current_priority) {
i++;
first_operand = new Add(first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
break;
case '*':
current_priority = 2;
if (last_priority < current_priority) {
i++;
first_operand = new Multiply(first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
break;
case '/':
current_priority = 2;
if (last_priority < current_priority) {
i++;
first_operand = new Divide(first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
break;
I would like to get a method or something which would copy the behavior of the following fragment:
current_priority = x;
if (last_priority < current_priority) {
i++;
first_operand = new Something(first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
The problem is that as far as I'm concerned I can't declare non-initialized objects in Java and for my program it's important not to run the constructor of Something (Add/Multiply/Divide) before making sure it's really needed, so passing an object to this method is not a way, I have to somehow create an object inside this method, but this seems to lead to making two switches with identical cases and I would like more elegant solution if possible. I also don't know how to reproduce the return/assignment behavior depending of a condition inside a method. I would really appreciate any help.
A Use a Factory
current_priority = x;
if (last_priority < current_priority) {
i++;
first_operand = myOperationFactory.createOperand(operation, first_operand, parse(expression, current_priority));
} else {
i--;
return first_operand;
}
public class OperationFactory {
public Operand createOperand(char operation, Operand firstOperand, Operand secondOperand) {
switch (operation) {
case '+': return new Add(firstOperand, secondOperand);
case ...
}
B (advanced) use enum and reflection.
public enum Operations {
ADD('+', Add.class),
MULTIPLY('*', Multiply.class)
...;
private char symbol;
private Constructor<? extends Operation> constructor;
public Operations(char symbol, Class<? extends Operation> clazz) {
this.symbol = symbol;
this.constructor= clazz.getConstructor(Operand.class, Operand.class);
}
public Operation create(Operand operan1, Operand operand2) {
return constructor.newInstance(operand1, operand2);
}
public char getSymbol() {
return this.symbol;
}
public static Operations getFromSymbol(char symbol) {
for (Operations op : Operations.values()) {
if (op.getSymbol() == symbol) {
return op;
}
}
}
}
and
current_priority = x;
if (last_priority < current_priority) {
i++;
Operations operation = Operations.fromSymbol(opSymbol);
first_operand = operation.create(first_operand, parse(expression, current_priority));
....

How can I add '^' operator into this Infix to Prefix Conversion, Infix to Postfix Conversion

Can you explain how can I Add?
My Infix is: 1^2+3/3
Prefix expression is: +1^2/33 (which is wrong)
Postfix expression is: 1^233/+ (which is wrong)
the Prefix will be: +^12/33
and the Postfix will be: 12^33/+
My Code:
import java.io.*;
class Stack
{
private char[] a;
private int top,m;
public Stack(int max)
{
m=max;
a=new char[m];
top=-1;
}
public void push(char key)
{
a[++top]=key;
}
public char pop()
{
return(a[top--]);
}
public char peek()
{
return(a[top]);
}
public boolean isEmpty()
{
return (top==-1);
}
}
class Evaluation
{
private Stack s;
private String input;
private String output="";
public Evaluation(String str)
{
input=str;
s=new Stack(str.length());
}
public String inToPre()
{
for(int i=input.length()-1;i>=0;i--)
{
char ch=input.charAt(i);
**switch(ch)
{
case '+':
case '-':gotOperator(ch,1,')');
break;
case '*':
case '/':gotOperator(ch,2,')');
break;
case ')':s.push(ch);
break;
case '(':gotParenthesis(')');
break;
default:output=ch+output;
}
}
while(!s.isEmpty())
output=s.pop()+output;
return output;
} // End to inToPre
public String inToPost()
{
for(int i=0;i<input.length();i++)
{
char ch=input.charAt(i);
switch(ch)
{
case '+':
case '-':gotOperator(ch,1,'(');
break;
case '*':
case '/':gotOperator(ch,2,'(');
break;
case '(':s.push(ch);
break;
case ')':gotParenthesis('(');
break;
default:output=output+ch;
}
}
while(!s.isEmpty())
output=output+s.pop();
return output;
} // End inToPost**
private void gotOperator(char opThis,int prec1,char x)
{
while(!s.isEmpty())
{
char opTop=s.pop();
if(opTop==x)
{
s.push(opTop);
break;
}
else
{
int prec2;
if(opTop=='+'||opTop=='-')
prec2=1;
else
prec2=2;
if(prec2<prec1&&x=='(')
{
s.push(opTop);
break;
}
else if(prec2<=prec1&&x==')')
{
s.push(opTop);
break;
}
else
{
if(x==')')
output=opTop+output;
else
output=output+opTop;
}
}
} // End While gotOperator
s.push(opThis);
} // End gotOperator
private void gotParenthesis(char x)
{
while(!s.isEmpty())
{
char ch=s.pop();
if(ch==x)
break;
else
{
if(x==')')
output=ch+output;
else
output=output+ch;
} // End Else
} // End While gotParenthesis
} // End gotParenthesis
} // End Class Evaluation
Just looking at your code quickly I can see that in the InFix analysis you are not considering a new level for the ^ operator.
The groups should be +-, */, ^. Since the ^ has higher priority.
Regards

Categories

Resources