I am a beginner and reading through Murach's Java Servlet and JSP... Going through the examples. Kind of stuck at this Ch11 simple shopping cart example.
I would post the whole code here but its really way to long.
I have put the full code on my dropbox link : https://dl.dropboxusercontent.com/u/36625850/Ch11-JSTL.rar
Questions:
CartServlet.java
if(quantity > 0)
cart.addItem(lineItem);
else if(quantity == 0)
cart.removeItem(lineItem);
session.setAttribute("cart", cart);
String url = "/cart.jsp";
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(url);
dispatcher.forward(request, response);
This is probably a dumb question. I notice for servlet If statement you don't need { }? Why is this? I mean regular java if statements all require { } so why is the servlet any different?
cart.java
public void addItem(LineItem item)
{
String code = item.getProduct().getCode();
int quantity = item.getQuantity();
for (int i = 0; i < items.size(); i++)
{
LineItem lineItem = items.get(i);
if (lineItem.getProduct().getCode().equals(code))
{
lineItem.setQuantity(quantity);
return;
}
}
items.add(item);
}
What I can't follow is item.getProduct().getCode();. I am not really sure what would this output.
if-else clause (and all other control structure) read by block in java.
So if you put
if(x>2)
System.out.println("a"); ==> this is the next block
System.out.println("b");
if(x<2)
{ ==> this is the next block
System.out.println("a");
System.out.println("b");
}
So testing above code if x == 1 ,
in first if statement
prints --> "b"
in second if statement
prints --> "a"
"b"
Another example
if(x>2)
for(int i=0;i<100;i++) --> next block of if
for(int j=0;j<200;j++){ --> next block of first for
if(x>0)
Sysout("a"); --> next block of if
else
Sysout("b"); --> next block of else
}
In Java it's recommended always use braces.
For your second question
item.getProduct().getCode();
item is LineItem object.
Your class sure is
public class LineItem{
private Product product;
public Product getProduct(){
return product;
}
}
Product class
public class Product{
private String code;
public String getCode(){
return code;
}
}
1) Servlet is also java code and rules that are applicable to core java are applicable to Servlet too.
{} are used to combine number of statements into single block.
ex.
if(condition)
statement 1;
statement 2;
In above example statement1 will get executed only if condition evaluates to true.Statement 2 will not be part of if statement so it gets executed as normal statement.
if(condition)
{
statement 1;
statement 2;
}
Now in above example as you have enclosed statement1 and statement 2 in {} whole block will be part of if and both statement will get executed only if if(condition) evaluates to true.
2)if (lineItem.getProduct().getCode().equals(code)
In above statement lineItem.getProduct() returns product object.
So lineItem.getProduct() becomes product.getCode().equals(code).Now product.getCode() returns code object.So product.getCode().equals(code) becomes code.equals(code) And if both are equal then if evaluates true.
if you don't use any {} in if it will execute the first statement after it. If you use a {} it will execture the all statements withing {}
For example
say condition is true
if(condition)
sttmnt1; // it will execute this only
sttmnt2; // this is out of if block
and in the following case both sttmnt will be executed
if(condition){
sttmnt1;
sttmnt2;
}
So in your example
if(quantity > 0)
cart.addItem(lineItem);
else if(quantity == 0)
cart.removeItem(lineItem);
In both if and else if condition there is only one statement. So it is not necessary to use {}
to know what item.getProduct().getCode(); will return, check what class object is returning in the getProduct method of LineItem class. in the returned objec't class type check whet is the return type of getCode()
Servlet Java code is just regular Java code. Your if without brackets would work the same way in regular Java.
Your LineItem class has a method getProduct whose return value is an object that has a getCode method. What this code snippet does is compare the value of getProduct().getCode() of all entries in items with the one of the given item. If any of them match, the function breaks and returns. So in short, this method makes sure that there is only distinct values of getProduct().getCode() are in the items collection.
What you need to understand is that {} makes multiple statements appear as one block.
Sort of like statement grouping.
So when you just have one statement you don't really need the {} but when you have multiple statements the {} are useful.
I however use the brackets all the time even for one line statements because for me it looks pretty :-)
if statement is same for all.
There is no separate (Java Servlet if statement).
If there is only one statement to execute(when [if,else if,else,while,for]) satisfies , we no need to use {}(but not recommended,readability problem occurs )
ex:
if(condition){
System.out.println("hai"); // here only one statement is there to execute
}
is same as
if(condition)
System.out.println("hai");
Similarly
int i=1;
while(i++!=10){
System.out.println("hai");
}
is same as
int i=1;
while(i++!=10)
System.out.println("hai");
In Java only switch statement requires {} even though it has single case statement
Related
I'm curious is it possible to call a method that returns a boolean value in the condition part of a while loop?
As in:
while(someMethod()!= true){
//Do stuff
}
And the method simply returns a true or false. Is this possible or not and if so is there a correct syntax or a better way?
Edit: Thanks for the quick responses. As an extension to my question is it possible to call the method multiple times for different things but require them all to be the same before exiting the loop?
For example:
while(!(someMethod(input_a) == someMethod(input_b))){
//Do stuff
}
Where both of the returned values are the returned values are equal?
Hope this will help you
public boolean functionOne(int i){
// some operation
if(i == 1) return true;
else return false;
}
public void otherFunc(){
int i = 0;
if(functionOne(i)) { // e.g: if(functionOne(i) == true)
// your code
// 0!=1 so result is fort
}
if(!functionOne(i)){ // e.g: if(functionOne(i) == false)
// your code
// 0!=1 it is false, but ! before functionOne negate so ! of false is true
}
// **for your while**
while(functionOne(i)){ // while function returns true
// code
}
// **or**
while(!functionOne(i)){ // while function returns false
// code
}
}
Yes of course!
public static boolean someMethod(){
return false;
}
public static void main(String[] args){
while(!someMethod()){
//do something
System.out.println("Hi");
}
}
Like in this code, an infinite loop will be called if the method returns false, but if the method returns true, it will just come out of the while loop. :)
Less is best:
while (!someMethod()) {
// Do stuff
}
It's never a good idea to compare to a boolean result to a boolean literal. Prefer using the result in-line, using the logical unary not operator ! as required.
Answering the now-edited version of the question, less is still best:
while (someMethod(input_a) != someMethod(input_b))
You can find the specification of the while loop in JLS Sec 14.12:
The while statement executes an Expression and a Statement repeatedly until the value of the Expression is false.
WhileStatement:
while ( Expression ) Statement
WhileStatementNoShortIf:
while ( Expression ) StatementNoShortIf
The Expression must have type boolean or Boolean, or a compile-time error occurs.
So, you can use anything which is an Expression of type boolean (or Boolean).
And if you click through the productions in the language spec:
Expression, contains
AssignmentExpression, contains
ConditionalExpression, contains
ConditionalOrExpression, contains
ConditionalAndExpression, contains
InclusiveOrExpression, contains
ExclusiveOrExpression, contains
AndExpression, contains
EqualityExpression, contains
RelationalExpression, contains
ShiftExpression, contains
AdditiveExpression, contains
MultiplicativeExpression, contains
UnaryExpression, contains
UnaryExpressionNotPlusMinus, contains
PostfixExpression, contains
Primary, contains
PrimaryNoNewArray, contains
MethodInvocation
Phew! That's pretty deeply buried! (You can read this like an inheritance hierarchy, so every MethodInvocation is a PrimaryNoNewArray, and every PrimaryNoNewArray is a Primary etc).
So, transitively, every MethodInvocation is an Expression, hence it's fine to use it as the expression in a while loop.
Addressing your edit: yes, that's fine too. If you look at the detail of the EqualityExpression:
EqualityExpression:
RelationalExpression
EqualityExpression == RelationalExpression
EqualityExpression != RelationalExpression
As already described above, you can use an EqualityExpression as the Expression in a WhileStatement. And something of the form
RelationalExpression != RelationalExpression
is an EqualityExpression by the rule shown. Since all MethodInvocations are RelationalExpressions, you can use method invocations in the while statement as you've shown:
while(someMethod(input_a) != someMethod(input_b)) {
(a != b is an easier way of writing !(a == b)).
This is the way we have done loops over java iterators. For instance:
Iterator[String] iterator = util.Arrays.asList("One", "Two", "Three").iterator();
while(iterator.hasNext()) {
println(iterator.next());
}
We have also done something similar for the JDBC ResultSet interface.
In Java it is possible to declare a variable in the initialization part of a for-loop:
for ( int i=0; i < 10; i++) {
// do something (with i)
}
But with the while statement this seems not to be possible.
Quite often I see code like this, when the conditional for the while loop needs to be updated after every iteration:
List<Object> processables = retrieveProcessableItems(..); // initial fetch
while (processables.size() > 0) {
// process items
processables = retrieveProcessableItems(..); // update
}
Here on stackoverflow I found at least a solution to prevent the duplicate code of fetching the processable items:
List<Object> processables;
while ((processables = retrieveProcessableItems(..)).size() > 0) {
// process items
}
But the variable still has to be declared outside the while-loop.
So, as I want to keep my variable scopes clean, is it possible to declare a variable within the while conditional, or is there some other solution for such cases?
You can write a while loop using a for loop:
while (condition) { ... }
is the same as
for (; condition; ) { ... }
since all three bits in the brackets of the basic for statement declaration are optional:
BasicForStatement:
for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement
Similarly, you can just rewrite your while loop as a for loop:
for (List<Object> processables;
(processables = retrieveProcessableItems(..)).size() > 0;) {
// ... Process items.
}
Note that some static analysis tools (e.g. eclipse 4.5) might demand that an initial value is assigned to processables, e.g. List<Object> processables = null. This is incorrect, according to JLS; my version of javac does not complain if the variable is left initially unassigned.
No it's not possible.
It doesn't really make too much sense either: unlike a for loop where you can set up the initial state of the "looping variable", in a while loop you test the value of an existing variable, akin to the conditional check of the for loop.
Of course, if you're concerned about variables "leaking" into other parts of your code, you could enclose the whole thing in an extra scope block:
{
/*declare variable here*/
while(...){...}
}
Alternatively, convert the while loop into a for loop.
Make a do/while:
String value;
do {
value = getValue();
...your processing
} while (value != null && !value.isEmpty());
Why this code is wrong ? When I change "else if(this.power >= p)" into only "else", it's right. Can anybody give me a hint?
public boolean useBattery(double p) {
if(this.power < p) {
this.power = 0.0;
return false;
} else if(this.power >= p) {
this.power = this.power - p;
return true;
}
}
To a human reader looking at the code it seems that either the first return will be hit, or the second, but the compiler can't be sure. To the compiler it looks like:
if (condition1) {
...
return false;
} else if (condition2) {
...
return true;
}
and it needs to know, what will the method return if neither condition1 nor condition2 is true?
Whereas if you change it to a straight else,
if (condition1) {
...
return false;
} else {
...
return true;
}
then it is certain that one of the two return statements must be hit.
In fact in your method there is a chance that neither condition will be met: if one of the numbers you are comparing is NaN (the special floating point value representing "not a number"), then both of your if conditions will be false, and the method would have no return value.
There is also theoretically a possibility that some code running in another thread might alter the value of this.power between the first if check and the second, which could lead to both conditions evaluating to false. So it is not possible for the compiler to know for certain that one of the conditions will be met, even if they were logically complementary.
What happens if we don't enter any of your conditional branches? Java can't determine that you'll be able to because else if implies that there may not be another conditional branch to check.
Phrased another way, there's an implicit else block that does nothing. Since you declare a return type, having this implicit else block do nothing is an error.
An else block is always guaranteed to execute, so you will not run into the same situation with else, which is probably what you intended to use in the first place.
Think in the case of a flowchart.
If (this.power < p), then
Set power to 0
Return false
Else if (this.power >= p), then
Subtract p from power
Return true
Else (implied)
Do nothing <- this is the error
Because if you add if into the second else there might be a condition where neither of the condition will be satisfied and method will match to no return statement.
Consider this simple example:
Consider x=5; below code will match no return statement because it doesn't satisfies any condition.
if(x>5){
return true;
}
else if(x < 5){
return false;
}
You can reproduce this error with even shorter code:
public int doSomething() {
if(true) {
return 0;
}
}
This method generates compiler error missing return statement
Compiler doesn't perform intelligent static analysis of your code. It just checks statements according to specification.
Java Language Specification 8.4.7 "Method body" states that:
If a method is declared to have a return type, then a compile-time error occurs if the body of the method can complete normally.
So, compiler just checks if these statements can complete normally.
JLS 14.9.1 "The if-then Statement":
If the value is true, then the contained Statement is executed; the if-then statement completes normally if and only if execution of the Statement completes normally.
If the value is false, no further action is taken and the if-then statement completes normally.
As you can see by specification if statement can complete normally. That's why a compile-time error occurs.
On the other hand, by JLS 14.9.2 "The if-then-else Statement":
If the value is true, then the first contained Statement (the one before the else keyword) is executed; the if-then-else statement completes normally if and only if execution of that statement completes normally.
If the value is false, then the second contained Statement (the one after the else keyword) is executed; the if-then-else statement completes normally if and only if execution of that statement completes normally.
As you can see if-then-else completes if and only if one of its blocks completes normally. In your example both of them contain return statements.
I am using Eclipse Helios IDE for our Web Application development.
Under Problems section in Eclipse, for some of lines the description is displayed as "Dead Code".
Could anybody please tell me what does Dead Code actually mean ?
Please see the screen shot for your reference.
For example this part is shown as dead code under Eclipse
else {
int length;
if (ar != null)
length = Array.getLength(ar);
else
length = 0; // This line is dead code
In Eclipse, "dead code" is code that will never be executed. Usually it's in a conditional branch that logically will never be entered.
A trivial example would be the following:
boolean x = true;
if (x) {
// do something
} else {
// this is dead code!
}
It's not an error, because it's still valid java, but it's a useful warning, especially if the logical conditions are complex, and where it may not be intuitively obvious that the code will never be executed.
In your specific example, Eclipse has calculated that ar will always be non-null, and so the else length = 0 branch will never be executed.
And yes, it's possible that Eclipse is wrong, but it's much more likely that it's not.
Dead code is code that will never be executed, e.g.
boolean b = true
if (!b) {
....
// dead code here
}
Dead code means, that there is no way that this code will be executed.
Sometimes you even can't compile it (like this case:)
private Boolean dead_code()
{
return true;
//Dead code below:
dosomething();
}
But in other cases this is not too obvious, eg this statement:
b=true;
[...]
if (b==false)
{
//Dead code
}
If you have this message, there is some major flaw in your code. You have to find it, otherwise your app won't work as intended.
There are two kinds of diagnostics that Eclipse gives out for marking code that will/may not be executed at runtime.
1) Unreachable code: These are the usual java warnings that follow the unreachability rules of the JLS, and are also given by javac. These are meant to be compile errors. Examples:
int foo() {
return 1;
int i = 1; // Unreachable
}
int foo2() {
while (true);
int i =1; //Unreachable
}
There are other more complicated examples :)
2) Dead code: This is Eclipse's own static analysis warnings, and are mostly tied out of the null analysis i.e.
void foo() {
Object o = null;
if (o == null) {
} else {
// dead code
}
The examples given above should NOT give a dead code warning. i.e.
boolean x = true;
if (x) {
// do something
} else {
// this is dead code!
}
should not give the warning, because JLS forbids the compiler to evaluate the 'value' of variables. All that we can evaluate is the 'nullness'
Hope this helps
You might be having an Null pointer exception in the lines above the "Dead Code" lines.
Make sure you check for "Null Pointer" exception.
It is possible that you have used the variable ar before. Then the compiler knows that the line in the else statement will never be executed. Either there will be a NullPointerException at the place where you used ar or the first part of the if statement will be executed.
let me give some answer for the dead code.
Eg:
public class UnreachableTest{
public static void main(){
try{
// some code
}
catch(Exception exc){
throw new NullPointerException();
System.out.println("Unreachable line"); // compile time error
}
}
}
here the System.out.println("Unreachable line"); is never executed.
Which in turn considered to be a dead code.
Another example may be:
int func(int i, int j)
{
int sum = i + j;
return i + j; // never actually using the sum
}
simple the function returns i + j; never really uses sum.
Sum is considered to be dead code here.
Some other case when this happens.
System.out.println("result :" + result + ":" + result.isEmpty());
if (result == null)
return result;
else if(!result.isEmpty())
str.append(result + " ");
1) Here as you you are printing result and checking isEmpty() eclipse assumes that result is not null so it will not go in if. So return result is dead code.
2)Now let say result is coming null so you will get NullPointerException in result.isEmpty() so again it will not go in if and return result is deadcode
To make this work just comment out System.out.println().
Eclipse gives this warning if the condition check you are giving may never be satisfied. Following are some examples
Object o=null;
if(o!=null) {
//Some code
}
Here Dead code warning will come as Object is already made null
Another example is given below
BSTTest bstTest=null;
bstTest.test=10;
if(bstTest==null) {
//some code
}
Here the code is trying to access a variable of the class. As the variable is already accessed, eclipse will give dead code warning in if(bstTest==null) as bstTest may not be null when the variable is already accessed.
Note: Here bstTest.test will give null pointer exception
Simple Example of Dead Code
public class IfTest {
public static void main(String[] args) {
if (true) {
if(false) {
System.out.println("a"); //Dead code, Never be Execute this if block.
}else {
System.out.println("b");
}
}
}
To simplify the term's Unreachable code and dead code:
Unreachable Code is a code block/statement in Java to which the control never reaches and never gets executed during the lifetime of the program. Following is the example of unreachable code. This generates compiler time error.
public void unreachableCodeExample() {
System.out.println("This will execute");
return;
System.out.println("This will not"); //This is Unreachable code
}
While A Dead code is an unreachable code, but it doesn’t generate compile time error. But if you execute it in eclipse (Or some other IDE) it gives you a warning. See below example,
public void deadCodeExample() {
if (true) {
System.out.println("This will execute");
return;
}
System.out.println("This will not"); //This is dead code
}
Dead code is the section of our code that is never going to execute runtime, its useless
EX:
if(false){ // statements }
For more example u can refer : DeadCode Examples
Try this:
while (true) {
if(false == true) break;
}
S.O.P("I will never reach here!") <-- This code will never be executed.
The code is valid as it conform to the compiler, however in reality the loop will never exit, and in effect S.O.P will never be executed.
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());