I have a Java program that does many small array operations. I've run it and verified that it produces no errors, but it is slower than expected. I'm assuming a lot of this slowdown is related to checking array bounds, etc.
Is there a way to disable all error checking so I can run my program faster (at risk that it just crashes, rather then generates an intelligible error)?
No, this is not possible. The Java Language Specification describes the circumstances under which casts and array accesses throw exceptions, but makes no mention of a mechanism to disable this behaviour.
Throwing of ClassCastException is described in JLS Section 15.6:
A cast expression (§15.16) throws a ClassCastException if a cast is found to be impermissible at run time.
Array bounds checking is described in JLS Section 15.10.4:
At run time, evaluation of an array access expression behaves as follows:
First, the array reference expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason and the index expression is not evaluated.
Otherwise, the index expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason.
Otherwise, if the value of the array reference expression is null, then a NullPointerException is thrown.
Otherwise, the value of the array reference expression indeed refers to an array. If the value of the index expression is less than zero, or greater than or equal to the array's length, then an ArrayIndexOutOfBoundsException is thrown.
Otherwise, the result of the array access is the variable of type T, within the array, selected by the value of the index expression.
No this is not possible as this would break the JVM in case of error.
Related
Say I perform a simple add/concatenation statement:
variable + newInput
Without setting the calculated value to a new variable, as in:
variable = variable + newInput
or
variable += newInput
Does Java have some sort of specifier to be able to use the computed sum or concatenated string?
Apparently in Python it is automatically saved in the implicit global variable _ -which is implementable like
Print(_)
Is there anything like this in Java?
No. It does not have anything like this. You have to assign the computed value to a variable, otherwise it will be lost and consequently collected by the garbage collector.
The best option is to use a special operator so not to use an extra variable but assign the result to an old one. This is a Shorthand operator.
Variable += NewInput
More than just not saving the result, Java will outright refuse to compile your program if it contains such a line, precisely because the result would be unsaved and unusable if it was allowed:
public class Main
{
public static void main(String[] args)
{
1+2;
}
}
Result:
Main.java:5: error: not a statement
1+2;
^
1 error
Java does not allow arbitrary expressions as statements, and addition expressions are not considered valid Java statements.
The expressions that are allowed as statements by themselves are listed in the JLS:
ExpressionStatement:
StatementExpression ;
StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression
Assignment, increment, decrement, method calls, and new Whatever(), all things with side effects or potential side effects. Barring possible side effects of an implicit toString() call, + cannot have side effects, so to catch probable errors, Java forbids addition expressions from being statements.
You can for sure do:
variable + newInput
but the result of that operation must be assigned to a variable, if not, it will get lost...
the most you can get is
variable += newInput
whihch is similar to
variable = variable + newInput
The point is: the + operator in Java simply takes two operands and returns a result (either numerical, or as string concatenation).
Without assigning this result to something (like returning it from a method; or as shown in your example) ... it is like: the operation never takes place.
This operation doesn't have any side effects on its operands; and there is no way of accessing this result.
Beyond that, there is no operator overloading in Java. So it is also not possible to do some black magic that somehow stores the result of operation as side effect. You could theoretically add an agent to the JVM, that intercepts at runtime to do something upon an add operation, but that is more like: "technically possible", but nothing you would do in practical reality.
Other JVM languages, like Scala for example might use it implicitly - the last expression in a method is always returned, even when leaving out the return statement (in scala).
The statement you show is evaluated and nothing is done with it. Unless you bind a variable to the result, the evaluation occurs without effect.
This will not be flagged as an error by the compiler.
Outside of the context of an Array index, is there any exception in Java that can be thrown when the user enters a number outside the range asked for by a program?
ie. The program wants an integer between 0-100 and user enters 132, could an exception be thrown manually or does it have to be custom?
EDIT: I get that it doesn't make sense to use an exception for this, it's for an assignment and I want to know my options. Easy on the hair trigger down voters.
You can throw IllegalArgumentException
Java Language Specification, regarding Integer Operations says:
The integer operators do not indicate overflow or underflow in any way.
An integer operator can throw an exception (§11) for the following reasons:
Any integer operator can throw a NullPointerException if unboxing conversion (§5.1.8) of a null reference is required.
The integer divide operator / (§15.17.2) and the integer remainder operator % (§15.17.3) can throw an ArithmeticException if the right-hand operand is zero.
The increment and decrement operators ++ (§15.14.2, §15.15.1) and -- (§15.14.3, §15.15.2) can throw an OutOfMemoryError if boxing conversion (§5.1.7) is required and there is not sufficient memory available to perform the conversion.
I m not a fan of "exception driven architecture", ;)
Implement a check if the integer is over 100 and return an error, status code, etc as feedback for user/system etc.
If you particularly want to use exception handling for this then you should probably define your own custom exception for it rather than reuse a standard Java one. That way you can be certain you are only catching your particular case. If you do define an exception you will need to manually throw it and catch it.
Note that I am referring here specifically to an exception related to user entry that you wish to handle. Java has an excellent set of exceptions for handling errors that are internal to your code (e.g. null pointer exceptions).
Having said that this does not seem like a good use case for an exception. Your code should consider every value a user might enter as within normal use. Exception handling is best reserved for handling things that are exceptions to normal operations.
Exceptions are expensive. Should use some cheap test function or make a wrapper class that accepts only the range you want and carries an "error" variable through all calculations to the end. You check that error at end, trace it back to the source. Traveling error makes it possible to see multiple errors at the same time, not just stuck at the first error happened.
public class IntegerWithError
{
int result;
int error;
int errorSource;
// some methods to check for range, alter "error" as needed.
// some methods to sign the start point of error
}
private static IntegerWithError Test(int parameter)
{
IntegerWithError iwe=new IntegerWithError();
if(parameter>5)
{
iwe.error=1;
iwe.errorSource=iwe.hashCode();
}
iwe.result=parameter;
return iwe;
}
....
ParameterWithError p1,p2;
....
MatrixMultiplyWithError(p1,p2);
RenderWithErrors(p1,p2,b1,b1);
TraceError(p1); // finds if it was a function, a constructor or something.
In Java when passing arguments to a method and modifying the passed arguments during the method call is it guaranteed that the result is what is expected?
E.g.
a.method(++i); etc
Is it guaranteed for instance that inside method the variable i will have the updated
value?
Or a.method(i++) Will method get the value of i after incrementing or before?
Also same for all similar cases.
I kind of remember this is forbidden in C++ as implementation specific but perhaps I remember wrong.
The java language specification for prefix/postfix increment/decrement operators:
Prefix: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.15.1.
... the value 1 is added to the value of the variable and the sum is stored back into the variable ... The value of the prefix increment expression is the value of the
variable after the new value is stored.
Postfix: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.14.2
... the value 1 is added to the value of the variable and the sum is stored back into the variable ... The value of the postfix increment expression is the value of the variable before the new value is stored.
I think it's pretty clear. The function will get the incremented value in the prefix case, and not in the postfix case.
The expression ++i is evaluated before the method is called.
From the Java Language Specification's section "Runtime evaluation of method invocation":
... Second, the argument expressions are evaluated. ... Fifth, a new activation frame is created, synchronization is performed if necessary, and control is transferred to the method code.
And from the Java Language Specification's section "Prefix increment operator":
The value of the prefix increment expression is the value of the variable after the new value is stored.
No problem in Java, method will receive the updated value.
While fiddling around in Java, I initialized a new String array with a negative length.
i.e. -
String[] arr = new String[-1];
To my surprise, the compiler didn't complain about it.
Googling didn't bring up any relevant answers. Can anyone shed some light on this matter?
Many thanks!
The reason is that the JLS allows this, and a compiler that flagged it as a compilation error would be rejecting valid Java code.
It is specified in JLS 15.10.1. Here's the relevant snippet:
"... If the value of any DimExpr expression is less than zero, then a NegativeArraySizeException is thrown."
Now if the Java compiler flagged the code as an error, then that specified behaviour could not occur ... in that specific code.
Furthermore, there's no text that I can find that "authorizes" the compiler to reject this in the "obvious mistake" cases involving compile-time constant expressions like -1. (And who is to say it really was a mistake?)
The next question, of course, is 'why does the JLS allow this?'
You've need to ask the Java designers. However I can think of some (mostly) plausible reasons:
This was originally overlooked, and there's no strong case for fixing it. (Noting that fixing it breaks source code compatibility.)
It was considered to be too unusual / edge case to be worth dealing with.
It would potentially cause problems for people writing source code generators. (Imagine, having to write code to evaluate compile-time constant expressions in order that you don't generate non-compilable code. With the current JLS spec, you can simply generate the code with the "bad" size, and deal with the exception (or not) if the code ever gets executed.)
Maybe someone had a plan to add "unarrays" to Java :-)
Other answers have suggested that the compiler could / should "flag" this case. If "flagging" means outputting a warning message, that is certainly permitted by the JLS. However, it is debatable whether the compiler should do this. On the one hand, if the above code was written by mistake, then it would be useful to have that mistake flagged. On the other hand, if it was not a mistake (or the "mistake" was not relevant) then the warning would be noise, or worse. Either way, this is something that you would need to discuss with the maintainer(s) for the respective compiler(s).
I see no reason why this couldn't be flagged up at compile time (at least as a warning), since this unconditionally throws NegativeArraySizeException when executed.
I've done some quick experiments with my compiler, and it seems surprisingly relaxed about this sort of thing. It issues no warning about integer divide by zero in constant expressions, out-of-bounds array access with constant indices etc.
From this I conclude that the general pattern here is to trust the programmer.
Compiler only responsible for checking language syntax, but not the semantic meaning of you code.
Thus it is reasonable the compiler is not complaining error as there is no syntax error in your code at all.
In Java, array is allocated at runtime, which is absolutely ok. If it is allocate at compile time, then how compiler check the following code?
// runtime pass the length, with any value
void t(int length) {
String[] stirngs = new String[length];
}
When pass negative value as length to contruct array, the runtime exception will being thrown.
public class Main {
public static void main(String[] args) {
String[] v = new String[-1];
}
}
with error:
Exception in thread "main" java.lang.NegativeArraySizeException
at Main.main(Main.java:5)
Java compiler takes an integer as the length of an array. It can be a variable or a compile-time constant. The length of an array is established when the array is created. After creation, its length is fixed.
The compiler should flag a negative compile-time constant as the length of an array. It just does not do so . If the length is a negative number you will get a NegativeArraySizeException at run time.
In my Java book, it says that "an expression is a statement that can convey a return value." This is different than my traditional understanding. I thought an expression DOES return a value. Not CAN return a value.
this is from Sams Teach Yourself Java in 21 Days.
A mathematical expression always returns something, but a Java expression doesn't have to. The Java Specification defines what exactly is meant by the term expression in the Java language. Another difference is that expressions can, and often do, have side effects in Java. A side effect is pretty much anything that happens other than returning a value.
Quoting the Java Language Specification:
Much of the work in a program is done by evaluating expressions, either for their side effects, such as assignments to variables, or for their values, which can be used as arguments or operands in larger expressions, or to affect the execution sequence in statements, or both.
For example system.out.println("Hello World"); doesn't return a value, but it does print Hello World to the output stream. This process of outputting data is a side effect of calling println. Functional languages, in contrast, attempt to minimize dependence on side effects and stick more closely to the mathematical definition of an expression.
Quoting from the JLS again, here is the BNF grammar for an expression:
Primary:
PrimaryNoNewArray
ArrayCreationExpression
PrimaryNoNewArray:
Literal
Type . class
void . class
this
ClassName.this
( Expression )
ClassInstanceCreationExpression
FieldAccess
MethodInvocation
ArrayAccess
You can see that a MethodInvocation is an expansion of PrimaryNoNewArray, which is an expansion of Primary (expression).
Your understanding is incomplete. In Java, an expression could return a value, and it could terminate due to an exception. Similar situations arise in other languages which support exceptions, and more generally. (For instance, in the C language, division by zero causes the current expression evaluation to terminate without returning a value.)
Another explanation is that (according to the JLS), a method invocation expression like System.err.println("hello") can deliver a notional void value to its context, and this really means that it is delivering no value.
I don't think this second explanation is sound. We start with an "expression" that is specified as delivering a void value. Then we are argue that since the void value is in reality not a value, the expression is delivering nothing. Finally, we say it is an expression that delivers no value.
A simpler explanation for this example is that an "expression" that delivers "void" is not really an expression in the intuitive sense. Certainly, in Java you cannot use a void-delivering MethodInvocation expression where a non-void-delivering expression is required. And you can't use a non-void-delivering expression as a Statement.
Alternatively, we can stick with the JLS treatment and say that the "void" value really is a value ... even though you can't ever do anything with it. By this argument, System.err.println("Hi") is returning a value after all.
Ouch... This doesn't seem like a very good book :(
An expression either has a type and can be evaluated to yield a value of that type, or is of void type and can be evaluated to yield nothing. The JLS also says an expression can evaluate to a variable, but the variable in turn has a type and a value. For example, 1 + 1 is an expression.
A statement, on the other hand, is composed of expressions but doesn't have a type or a value itself. For example, int x = 1 + 1; has no value. It wouldn't make sense in Java to say something like System.out.println(int x = 1 + 1;);
The method public void foo(); does not return anything, thus the expression foo() does not return anything. But if the method was public int foo(), then it would. Thus it could return something, but doesn't necessarily have to. From the Java spec:
An expression denotes nothing if and only if it is a method invocation
that invokes a method that does not return a value, that is, a method
declared void. Such an expression can be used only as an expression
statement, because every other context in which an expression can
appear requires the expression to denote something. An expression
statement that is a method invocation may also invoke a method that
produces a result; in this case the value returned by the method is
quietly discarded.