I'm learning Java with the help of a book and don't understand the following example/statement:
For args[0].equals("Schrödinger") you need to make sure the args[0] is not null, whereas "Schrödinger".equals(args[0]) doesn't need this kind of check because "Schrödinger" can't be null.
Code:
if("Schrödinger".equals(args[0])) {
System.out.println("Hallo");
}
However I do get an error if there is no parameter in args, which also seems logical as you need to grab the value at args[0] at some point for the comparison, even if the string "Schrödinger" isn't null. I'm confused, is the example from the book wrong or am I not understanding something?
The code provided in the book only handles args[0] being null, not args having a length of 0. Assuming your program is supposed to pass some command-line arguments to it, and you do not pass any argument while executing it, the length of the following array, args will remain 0.
public static void main(String[] args)
As a result, an attempt to access an element from the first position, which is specified with the index, 0 will result in ArrayIndexOutOfBoundsException. Since the index of an array starts with 0, the maximum index can go up to the size of the array minus 1.
You can avoid the problem you have faced by checking the size of the array first before accessing an element within the maximum index e.g.
if(args.length >= 1 && "Schrödinger".equals(args[0])) {
//...
}
Similarly, if you want to access an element up the index, 1, you should check if the size is 2 or more e.g.
if(args.length >= 2 && "Schrödinger".equals(args[1])) {
//...
}
By the way, a condition like "Schrödinger".equals(args[0]) is known as Yoda conditions.
Your assumption is correct. For the main method If the array is not provided then you can not access the first element of the array. It will throw an ArrayIndexOutOfBoundsException since there are no elements.
Running any method for a null object is not allowed, and you will get an exception. You have to check if args[0] is null (or of length 0) before you do anything with it.
For args[0].equals("Schrödinger") you need to make sure the args[0] is not null.
True, since you're calling .equals("Schrödinger") on the object, which is expected to be at index 0 in the args array.
whereas "Schrödinger".equals(args[0]) doesn't need this kind of check because "Schrödinger" can't be null.
True, as "Schrödinger" is a String literal, which by definition is an Object, so you explicitly have it, and there's no even hypothetical chance it'll be null.
However I do get an error if there is no parameter in args, which also seems logical as you need to grab the value at args[0] at some point for the comparison, even if the string "Schrödinger" isn't null.
True, but to be precise here, error doesn't happen at the comparison stage, because of you can't compare something to nothing, rather, your error happens here, because you're not passing anything, hence the args array is empty, and args[0] will throw the ArrayIndexOutOfBoundsException exception.
I hope I made each and every step clear for you.
For User defined args array
Case 1: args[0].equals("Schrödinger")
When args[0] is null(no value is passed), you cannot call equals method on
null hence NullPointerException is thrown
Case 2: "Schrödinger".equals(args[0])
In this case despite args[0] being null equals is called on string literal and
no exception is thrown + the condition evaluates to false. Hence this approach
is the recommended one or use Optionals.
For args of public static void main
In case of args array of public static void main it will throw ArrayIndexOutOfBoundException. If JVM finds no command line arguments its initializes the args as String[] args = new String[0] i.e of length 0. Hence while accessing it throws exception
Related
I'm writing a Calculator exercise that takes an array of int for addition, subtraction, division and multiplication. I need to check in every method that the array is not null. Instead of repeating myself, can I write the throwException method once and then just call it in my method?
e.g. for addition
public int addAll(int[] integers) {
throwExceptionForNullArray();
int sumOfAllIntegers = 0;
for (int integer : integers) {
sumOfAllIntegers += integer;
}
return sumOfAllIntegers;
}
public throwExceptionForNullArray (int[] integers){
if (integers == null){
throw new IllegalArgumentException("Empty array is not allowed");
}
}
But Java requires a return type in a method, do you have any ideas that can make the throwExceptionForNullArray method work? What should be the return type?
Thank you
What is the return type of a Java exception?
That's like asking: "What is the colour of ennui?" - the question doesn't make sense.
Let me put it differently. Imagine this hypothetical method:
public int hello() {
while (true) {
// just loop forever and ever and ever.
}
}
The above will... actually compile. Try it!
That's a bit odd - this method is declared to return an int, and yet, the method contains no return statement at all. And yet this compiles fine. That's because it is a bit wonky in how it 'works'. It never actually exits, so there's no violation of the rules here. A return type of int means: If this method returns normally, it must do so by returning an int value.
Note, if it returns normally. There is no rule stating that all methods must necessarily always return normally, or that it could ever even return normally. The above method cannot return normally, for example.
A "normal" return occurs when your method hits a return statement, or just gets to the closing brace.
A throw statement is an abnormal condition. A method that exits by way of throwing does not return anything. It got out by throwing. That doesn't mean it "returned" the exception. It means it "threw" the exception.
A method that cannot possibly return normally (and if all ways through the method end in a throw statement, it cannot possibly return normally) can pick whatever it wants for a return type. It just won't matter. Anything will do. For a method whose stated purpose is:
If the inputs are valid, do absolutely nothing
Otherwise, throw an exception highlighting what's invalid about the input
The usual return type is void. So, do that:
public void checkInput(int[] integers) {
if (integers == null) {
throw new NullPointerException("integers");
}
}
A few notes:
Your message was dead wrong. null does not mean "empty", a very important distinction. new int[0] is an empty array. null is a null pointer. Don't conflate the two. It's possible to have a method that doesn't like an input of an empty array. In that case, the correct act to take is something like:
if (integers.length == 0) throw new IllegalArgumentException("Empty 'integers' array not allowed");
It's more appropriate to use NullPointerException for params being null when as a precondition they aren't supposed to be.
If you're dereferencing the parameter, there's really no need to do this. The JVM itself will throw the NPE for you and even name it assuming you're using a modern JVM. You dereference integers (for (int i : integers) will do that), so you can remove it all and get the same result, namely: Calling that method with null will throw an NPE whose message includes the text 'integers'.
Naming a method 'throwExceptionFor' is a bit too on the nose, it describes too much how it works and not enough what it is supposed to do. checkInput describes the why/what instead of the how, that's usually the better way to name methods.
The question is answered by rzwitserloot, use void return type. There are other ways to deal with this .
JVM handles NullPointerException for you. Also have a look at the calls provided by java.util.Objects which can be used to provide enhanced error reporting:
Objects.requireNonNull(integers, "Arg integers is not set");
Objects.requireNonNull(someField, "Member someField is not set, perhaps missing somecall() ?");
There are also handy calls which accept suppliers so the arguments can be more complex without runtime creation overhead if not used:
Objects.requireNonNull(someField, () -> "Member someField is not set for "+this);
You can also fix nulls to use a default value, using the supplier variant means the default is only constructed when needed:
integers = requireNonNullElse(integers, someDefault);
integers = requireNonNullElseGet(integers, () -> new int[0]);
This question already has answers here:
Why does Java allow arrays of size 0?
(9 answers)
Closed 9 years ago.
char[] arrNew = new char[0];
System.out.println(arrNew.length); // length = 0
arrNew[0]='c'; // ArrayIndexOutOfBoundsException .
In the above code as you can clearly see there is no point in having an array of size 0. As far as I can see there is no practical usage of 0 size array. Can someone explain why the compiler allows creation of 0 length array. And also how is a 0 length array different from an array initialized to null? (i.e, is memory allocated to it as if it were a normal array?). I am sorry if this question seems stupid.
We can return an empty array instead of null from a method, this is called Null object design pattern. Consider the following code
Person[] res = find(name);
for(String e : res) {
System.out.println(e);
}
if find() does not find anyone it returns an empty array. If find returned null then code would need to treat it as a special case.
We should keep in mind that empty array is immutable so it is logical to use a singleton instead of creating it each time
private static final Person[] NULL = new Person[0];
Person[] find(String name) {
...
if (notFound) {
return NULL;
}
...
It's best not to return null from a method that returns an array type. Always returning an array, even if the array has zero length, greatly improves the generality of algorithms. If you anticipate that your methods will return zero-length arrays frequently, you might be concerned about the performance implications of allocating many such arrays. To solve that problem, simply allocate a single array, and always return the same one, for example:
private static final int ZERO_LENGTH_ARRAY[] = new int[0];
This array is immutable (it can't be changed), and can be shared throughout the application.
So in Null Object pattern, a null object replaces check of NULL object instance. Instead of putting if check for a null value, Null Object reflects a do nothing relationship. Such Null object can also be used to provide default behaviour in case data is not available.
Compiler allows because that code its within the rules of the language.
And no, they are both not the same. If it were the same, you would get a NullPointerException rather than ArrayIndexOutOfBoundsException.
It can be of use, if you have a function returning reference to array, and if you have nothing to return then you might consider its better to return 0 length array than a null. If null were returned you would have to check this function for both null value, and if range is correct, if you return 0 length array - then you might only check the if range is correct - ie. in for loop.
Zero-length arrays are rarely "required," but are more often used simply to show that there is no data being passed to a method.
in java the memory allocation can be dynamic in nature. The java array enables the user to store values of the same type in contiguous memory allocations. Arrays are always a fixed length abstracted data structure which can not be altered when required. It just occupies the memory.
I declare my objects outside of an if statement, but initialize them inside of it. Later I try and use them but it won't allow it because they haven't been initialized. The if statements are structured so that they all will execute before the objects are used, and hence the objects will be initialized guaranteed, but java doesn't allow that. Any way around this?
If you know that all paths will ultimately initialize them, but the compiler doesn't, you can initialize them to null or 0 or false (as ajb helpfully reminds) -- or some other special initial value you define -- when declaring them. They then have a concrete initial value.
If the variable is still null (or whatever it's initial value was) by the time you use it (evidenced perhaps by an NPE in the case of an object) then you know something went wrong; you can also self-document your assumptions with asserts later.
You should post your code so we can give you better advice; the compiler is relatively smart about path analysis, although it can't, of course, handle cases that rely on external input or assumed preconditions and invariants. Still, it's always possible that you've overlooked something (perhaps an exception or unexpected condition leads to a path where the value is uninitialized - which is fine, you just have to make sure it's initialized).
The only way an object's initialization is guaranteed after a conditional expression is if there exists a branch that is always executed, such as an else statement, or default in switch statements.
To decompose that, take this example code:
String word;
String name = "Peter";
if("Peter".equals(name)) {
word = "The Bird";
}
System.out.println(word);
This will fail since the compiler identifies a branch in which word is not initialized.
If you add an else clause, then the compiler will believe that word is initialized.
String word;
String name = "Peter";
if("Peter".equals(name)) {
word = "The Bird";
} else {
word = "Nope";
}
System.out.println(word);
Java requires that a variable be initialized along all possible paths to the point of use before its value can be referenced. Eg, if you have
int x;
if (a == b) {
x = 5;
}
if (c == d) {
x = 6;
}
int y = x;
In the above case the compiler cannot know that either the first or second if statement will be true, and so it's not certain that x gets assigned a value along all paths leading to the assignment to y. So the compiler will disallow this (and, if the compiler didn't reject this, the "verifier" inside the JVM would).
The solution is to assign a value to the variable (maybe zero or -1 in this case, null for an object reference) so that it's known to have a value along all paths.
But note that you probably should not just assign a dummy value to every variable you declare, since very often the compiler message that no value is assigned can indicate a real live code bug where you've accidentally omitted assigning a value to the variable along some path.
initialize them to null
Object myAwesomesauceVariableOfAwesome = null;
if(myUnbelievablyWildBoolean){
myAwesomesauceVariableOfAwesome = getAwesomesauce();
}
doSomethingCompletelyMindBlowingWithAwesomesauce(myAwesomesauceVariableOfAwesome);
I get a NullPointerException at a line on which just a simple null check takes place.The line is the following:
if(routingTable[commonBitGroups][nextNumberOfOther-1]==null)
I verify that the array is not null just before this line.
commonBitGroups and nextNumberOfOther are both simple int types.
I should add that this line is part of an app that uses rmi and part of a class which extends UnicastRemoteObject and implements a RemoteInterface.I specify that because I am under the impression that a NullPointerException can occur when you deal with synchronization even if nothing is realy null (maybe when something is locked) ,and I deal with synchronization in this app.The method that contains the line though is not synchronized and nowhere in my code I try to use the array as a monitor (I only have some synchronized methods ,no smaller synchronized blocks so I nowhere choose a specific monitor explicitly).
If the following line throws an NPE:
if (routingTable[commonBitGroups][nextNumberOfOther - 1] == null)
then either routingTable is null or routingTable[commonBitGroups] is null.
You say that the array is initialized as follows:
routingTable = new NodeId [32][15];
Arrays.fill(routingTable, null);
"Well there's your problem!"
The first line gives you an array of 32 NodeId[]'s, with the elements initialized to non-null values ... arrays of size 15. (So far so good ...)
The second line sets routingTable[i] to null for all i .... Ooops!!
Delete the second line.
As #Gabe says, it's probably that routingTable[commonBitGroups] is null. Java does not have real multidimensional arrays: a 2-d array is an array of arrays (and a 3-d array is an array of arrays of arrays).
Incidentally you don't have to initialize references in an array to null in Java, that is their default value. In this case it's also your problem. You're setting the second level of array values to null. What you meant was
for (int i = 0; i < 32; i++) {
Arrays.fill(routingTable[i], null);
}
But as above, this is unnecessary. So just remove your call to Arrays.fill.
An array of Strings, names, has been declared and initialized. Write the statements needed to determine whether any of the the array elements are null or refer to the empty String. Set the variable hasEmpty to true if any elements are null or empty-- otherwise set it to false.
hasEmpty=false;
for (int i=0;i<names.length;i++)
if (names[i].trim().equals("") || names[i]==null)
hasEmpty=true;
Whats wrong with my code?
Calling trim() first will result in a NullPointerException should a member of the array be null. Reverse the order of the conditions - the short-circuiting nature of || will then ensure that trim is only called on a real String object.
Consider names[i].trim().
When names[i] is a String, you really have something like someString.trim() which works fine.
When names[i] is a null, however, you really have something like null.trim(). You've already discovered that null doesn't allow a trim() method. (In fact, I'm not even really sure what 'null' is.)
Therefore, you must check for null before you invoke trim().
When you have a && b, where a and b are expressions, the checks are made left-to-right and the parser stops as soon as the issue is settled. So for the logical and operator (&&), if a is false then b is never checked. This is what allows
if (a != null && a.trim().length() > 0) { ... }
to work. if a is null, the a.trim() part is not executed since it would be pointless from a logical point of view; the value of the conditional has been decided.
Similarly for
if (a == null || a.trim().length() == 0) { ... }
if a is null then the a.trim() part is never performed and we don't get an error.
You can use the Apache Commons Lang's isBlank() to check a String:
if (StringUtils.isBlank(names[i]) {
...
}
StringUtils.isBlank is checking if the String is null or empty (i.e. if it is equals to "" when all blank characters are removed).
It's throwing a Null Pointer Exception because you're trying to run a method on a null object:
if (names[i].trim().equals("") || names[i]==null)
So, anytime that names[] has ONE name that's null, it will throw the exception. One way to solve the problem is to switch the boolean statements in this if statement:
if (names[i]==null || names[i].trim().equals(""))