null pointer exception when accessing array with null reference [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
my method is supposed to compare a cat's name from the entire cat array.
This is because my array will have nulls between created objects.
for example [0(cat 0), 1(cat 1), 2(cat 2), 3( empty null), 4(cat 4), 5(cat 5)]
I think the reason I am getting a null pointer exception is because I try to return a null and compare it to the param (String catName).
How could I avoid this while still searching the entire array?
/**
* #param catName to search for cat name
*/
public void searchCatByName(String catName) {
if (cats[0] != null) {
if(catName != null) {
int index = 0;
while (index < cats.length) {
if(cats[index].getName() != catName) {
if(index == cats.length - 1) {
System.out.println(catName + " was not found in the cattery.");
break;
}
index++;
}
else {
System.out.println(cats[index].getName() + " is in cage " + index);
break;
}
}
}
}
}

Check if the value is equal to null. If it is not equal to null then do your condition. I made an example in the code below
String arr[] = new String[]{"tom","blake",null,"jerry"};
String fider = "jerry";
for (int i = 0; i < arr.length; i++)
{
if (arr[i] != null)
if (arr[i].equals(fider))
System.out.println(i); // Prints 3
}

You have to check if the array element is null before comparing names with String equals method so instead of :
if(cats[index].getName() != catName) { /* logic */ }
the right condition is:
Cat cat = cats[index];
if(cat != null && !cat.getsName().equals(catName)) { /* logic */ }

Use simple logic. First check the array element if null, then if not null compare the cat name. Here is an example on how you should do a null check and compare strings.
public class Cat {
public static void main(String[] args) {
String catName = "Cat3";
String[] cats = new String[] {"Cat1","Cat2","Cat3", "", "Cat4"};
searchCatByName(catName, cats);
}
public static void searchCatByName(String catName, String[]cats) {
int catCounter = 0;
for(int i=0;i<cats.length;i++){
if (cats[i] != null){
if(catName.equals(cats[i])){
System.out.println(catName + " is in cage no " + (i+1));
catCounter++;
}
}
}
if(catCounter == 0){
System.out.println(catName + " was not found in the cattery.");
}
}
}

Related

Java - object existence dilem

I wrote the following, this is a toString of a Country class that has City class in same package, and _cities is an array represents the cities within my Country:
**EDITED:**
public String toString(){
String allCitiesData = ""; //must be initialized
for(int i=0;this._cities[i] != null;i++)//run all over the cities until reach the end(null cell)
{ //concat new city to the string and adds a new line between
allCitiesData = allCitiesData.concat(this._cities[i].toString()+"\n\n");
}
return allCitiesData;
}//toString method
public String citiesNorthOf(String cityName){
String allCitiesNorthOf = "";// must be initialized
for(int i=0; this._cities[i] != null ; i++)
{
if (this._cities[i].getCityName() == cityName)
{
Point referenceCityCenter = new Point(this._cities[i].getCityCenter());
}
}
for(int i=0; this._cities[i] != null ; i++)//we don't need to exclude the comparable city itself because it will give a false
{
if (this._cities[i].getCityCenter().isAbove(referenceCityCenter))
{
allCitiesNorthOf = allCitiesNorthOf.concat(this._cities[i].toString()+"\n\n");
}
}
}//citiesNorthOf method
But, when I run it, it shows a single error only on this line:
if (this._cities[i].getCityCenter().isAbove(referenceCityCenter))
And the Eclipse says: "referenceCityCenter cannot be resolved to a variable".. any suggestions ?
Thanks !!
You have declared referenceCityCenter in a scope which is not visible to that line of your code. Try declaring it at the beginning of the method (and control too if it is null when it arrives to your validation .isAbove()! :P )
referenceCityCenter is out of scope. Put it outside of your if statement and make sure you check for null afterwards like follows:
public String citiesNorthOf(String cityName){
String allCitiesNorthOf = "";// must be initialized
Point referenceCityCenter = null;
for(int i=0; this._cities[i] != null ; i++)
{
if (this._cities[i].getCityName() == cityName)
{
referenceCityCenter = new Point(this._cities[i].getCityCenter());
}
}
for(int i=0; this._cities[i] != null ; i++)//we don't need to exclude the comparable city itself because it will give a false
{
if (referenceCityCenter !- null && this._cities[i].getCityCenter().isAbove(referenceCityCenter))
{
allCitiesNorthOf = allCitiesNorthOf.concat(this._cities[i].toString()+"\n\n");
}
}
}

How do I check if a class' return of a method equals null?

In my program, I have a while loop that will display a list of shops and asks for an input, which corresponds with the shop ID. If the user enters an integer outside the array of shops, created with a Shop class, it will exit the loop and continue. Inside this loop is another while loop which calls the sellItem method of my Shop class below:
public Item sellItem()
{
displayItems();
int indexID = Shop.getInput();
if (indexID <= -1 || indexID >= wares.length)
{
System.out.println("Null"); // Testing purposes
return null;
}
else
{
return wares[indexID];
}
}
private void displayItems()
{
System.out.println("Name\t\t\t\tWeight\t\t\t\tPrice");
System.out.println("0. Return to Shops");
for(int i = 0; i < wares.length; i++)
{
System.out.print(i + 1 + ". ");
System.out.println(wares[i].getName() + "\t\t\t\t" + wares[i].getWeight() + "\t\t\t\t" + wares[i].getPrice());
}
}
private static int getInput()
{
Scanner scanInput = new Scanner(System.in);
int itemID = scanInput.nextInt();
int indexID = itemID - 1;
return indexID;
}
The while loop in my main class method is as follows:
boolean exitAllShops = true;
while(exitAllShops)
{
System.out.println("Where would you like to go?\nEnter the number which corresponds with the shop.\n1. Pete's Produce\n2. Moore's Meats\n3. Howards Hunting\n4. Foster's Farming\n5. Leighton's Liquor\n6. Carter's Clothing\n7. Hill's Household Products\n8. Lewis' Livery, Animals, and Wagon supplies\n9. Dr. Miller's Medicine\n10. Leave Shops (YOU WILL NOT BE ABLE TO RETURN)");
int shopInput = scan.nextInt();
if(shopInput >= 1 && shopInput <= allShops.length)
{
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(allShops == null)
{
System.out.println("still null"); // Testing purposes
leaveShop = false;
}
}
}
else
{
System.out.println("Are you sure you want to leave?\n1. Yes\n2. No");
int confirm = scan.nextInt();
if(confirm == 1)
{
exitAllShops = false;
}
}
The problem is here:
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(allShops == null)
{
System.out.println("still null"); // Testing purposes
leaveShop = false;
}
}
No matter what I do, I can't get "still null" to print to confirm that I'm correctly calling the return statement of the method sellItem of the class Shop. What am I doing wrong?
After calling allShops[...].sellItem(), allShops is still a valid array reference -- there's no way it could be null! You probably want to test the return value from sellItem:
if(allShops[shopInput-1].sellItem() == null)

How to create an array in recursive function in java

I have a recursive method that prints out the values in command line. I need to create a temp array with the result an display it using Swing. how do I create the array and store the values each time it loops ?
static void listSnapshots(VirtualMachine vm)
{
if(vm == null)
{
JOptionPane.showMessageDialog(null, "Please make sure you selected existing vm");
return;
}
VirtualMachineSnapshotInfo snapInfo = vm.getSnapshot();
VirtualMachineSnapshotTree[] snapTree = snapInfo.getRootSnapshotList();
printSnapshots(snapTree);
}
static void printSnapshots(VirtualMachineSnapshotTree[] snapTree)
{
VirtualMachineSnapshotTree node;
VirtualMachineSnapshotTree[] childTree;
for(int i=0; snapTree!=null && i < snapTree.length; i++)
{
node = snapTree[i];
System.out.println("Snapshot name: " + node.getName());
JOptionPane.showMessageDialog(null, "Snapshot name: " + node.getName());
childTree = node.getChildSnapshotList();
if(childTree != null)
{
printSnapshots(childTree);
}
}//end of for
so instead of JOptionPane I have only onew window with the list of names and can reuse later.
A general tactic for building something recursively is to use a Collecting Parameter.
This can be applied in your case by:
static List<String> listSnapshotNames(VirtualMachineSnapshotTree[] snapTree) {
ArrayList<String> result = new ArrayList<String>();
collectSnapshots(snapTree, result);
return result;
}
static void collectSnapshots(VirtualMachineSnapshotTree[] snapTree, List<String> names)
{
VirtualMachineSnapshotTree node;
VirtualMachineSnapshotTree[] childTree;
for(int i=0; snapTree!=null && i < snapTree.length; i++)
{
node = snapTree[i];
names.add(node.getName());
childTree = node.getChildSnapshotList();
if(childTree != null)
{
collectSnapshots(childTree, names);
}
}//end of for
}
Of course, if you really want it in an array, you can convert it afterwards:
static String[] getSnapshotNames(VirtualMachineSnapshotTree[] snapTree) {
List<String> result = listSnapshotNames(snapTree);
return result.toArray(new String[0]);
}
With an unknown size, arrays are painful, so a List works better for this.

How to get blank cell value in apache POI XSSF

I have an issue with an Apache POI XSSF in that it is not reading blank cell value.
I hava a class that implements DefaultHandler. In that class all non-blank cells are able to read from startElement and endElement methods.
I want to read blank cells in middle of the data cells.
Can anyone provide an example of how to do so or directions as to how to debug this?
Ran into this very same problem today. I was using the XSSF event model. But XSSF wouldn't give a column element nor a value element for the blank columns. Most probably because the backing XML is that way.
The key is to check the attribute for the cell reference (you know the A1, A2, A3 that Excel uses). Attributes are passed to the startElement() callback method. We can then detect missing cell references. So if we got L1 for the previous column element and get N1 for the current column element, we know M1 is the blank/missing cell.
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if (qName.equals("c")) {
String newColRef = atts.getValue("r");
coverColumnDistanceWithNulls(currentColRef, newColRef);
And coverColumnDistanceWithNulls() simply adds nulls for each missing cell reference between currentColRef and newColRef
private void coverColumnDistanceWithNulls(String fromColRefString, String toColRefString) {
int colRefDistance = getDistance(fromColRefString, toColRefString);
while (colRefDistance > 1) {
logger.debug("Covering distance with null");
rowValues.add(null);
--colRefDistance;
}
}
private int getDistance(String fromColRefString, String toColRefString) {
String fromColRef = getExcelCellRef(fromColRefString);
String toColRef = getExcelCellRef(toColRefString);
logger.debug("fromCol: {} toCol: {}", new Object[] {fromColRefString, toColRefString});
return excelCellReferenceOrder.get(toColRef) - excelCellReferenceOrder.get(fromColRef);
}
private String getExcelCellRef(String fromColRef) {
if (fromColRef != null) {
int i = 0;
for (;i < fromColRef.length(); i++) {
if (Character.isDigit(fromColRef.charAt(i))) {
break;
}
}
if (i == 0) {
return fromColRef;
}
else {
return fromColRef.substring(0, i);
}
}
return null;
}
Building off Sab Than's answer:
private void coverColumnDistance(String fromColRefString, String toColRefString) {
int colRefDistance = getDistance(fromColRefString, toColRefString);
while (colRefDistance > 0) {
c = getRow().addCell("");
colRefDistance--;
}
}
private int getDistance(String fromColRefString, String toColRefString) {
String fromColRef = getExcelCellRef(fromColRefString);
String toColRef = getExcelCellRef(toColRefString);
int distance = 0;
if (fromColRef == null || fromColRef.compareTo(toColRef) > 0)
return getDistance("A", toColRefString) + 1;
if (fromColRef != null && toColRef != null) {
while (fromColRef.length() < toColRef.length() || fromColRef.compareTo(toColRef) < 0) {
distance++;
fromColRef = increment(fromColRef);
}
}
return distance;
}
public String increment(String s) {
int length = s.length();
char c = s.charAt(length - 1);
if(c == 'Z') {
return length > 1 ? increment(s.substring(0, length - 1)) + 'A' : "AA";
}
return s.substring(0, length - 1) + ++c;
}
private String getExcelCellRef(String fromColRef) {
if (fromColRef != null) {
int i = 0;
for (; i < fromColRef.length(); i++) {
if (Character.isDigit(fromColRef.charAt(i))) {
break;
}
}
if (i == 0) {
return fromColRef;
}
else {
return fromColRef.substring(0, i);
}
}
return null;
}
If I remember correctly if you try and read a cell value that has not been assigned a value you get a NullPointerException or similar. You could surround the code that is examining the cell in a try-catch statement and then write your own code to deal with such scenario.
If my memory does not serve me correctly and tthe error thrown is not a NullPointerException then change the catch exception class to the relevant one.

Logic of deleting in Java

I cant figure out how to start a method to delete a specific entry stored in an array...
I used to do this:
public void deleteEntry() {
SName = JOptionPane.showInputDialog("Enter Name to delete: ");
for (int i = 0; i < counter; i++) {
if (entry[i].getName().equals(SName)) {
JOptionPane.showMessageDialog(null, "Found!");
entry[i] = null;
}
}
}
but I was advised not to assign the entry[i] to null because it will ruin my entries...
I have no idea how to code it in another way...
What should I need to do is:
I need to delete a specific entry from an array
please help...
also... its output was error it says:
Exception in thread "main" java.lang.NullPointerException
at AddressBook.viewAll(AddressBook.java:62)
at AddressBook.main(AddressBook.java:36)
Java Result: 1
This is my code in my main program:
public class AddressBook {
private AddressBookEntry entry[];
private int counter;
private String SName;
public static void main(String[] args) {
AddressBook a = new AddressBook();
a.entry = new AddressBookEntry[100];
int option = 0;
while (option != 5) {
String content = "Choose an Option\n\n"
+ "[1] Add an Entry\n"
+ "[2] Delete an Entry\n"
+ "[3] Update an Entry\n"
+ "[4] View all Entries\n"
+ "[5] View Specific Entry\n"
+ "[6] Exit";
option = Integer.parseInt(JOptionPane.showInputDialog(content));
switch (option) {
case 1:
a.addEntry();
break;
case 2:
a.deleteEntry();
break;
case 3:
a.editEntry();
break;
case 4:
a.viewAll();
break;
case 5:
a.searchEntry();
break;
case 6:
System.exit(1);
break;
default:
JOptionPane.showMessageDialog(null, "Invalid Choice!");
}
}
}
public void addEntry() {
entry[counter] = new AddressBookEntry();
entry[counter].setName(JOptionPane.showInputDialog("Enter name: "));
entry[counter].setAdd(JOptionPane.showInputDialog("Enter add: "));
entry[counter].setPhoneNo(JOptionPane.showInputDialog("Enter Phone No.: "));
entry[counter].setEmail(JOptionPane.showInputDialog("Enter E-mail: "));
counter++;
}
public void viewAll() {
String addText = " NAME\tADDRESS\tPHONE NO.\tE-MAIL ADD\n\n";
for (int i = 0; i < counter; i++) {
addText = addText + entry[i].getInfo() + "\n";
}
JOptionPane.showMessageDialog(null, new JTextArea(addText));
}
public void searchEntry() {
int notfound = 0;
SName = JOptionPane.showInputDialog("Enter Name to find: ");
for (int i = 0; i < counter; i++) {
if (entry[i].getName().equals(SName)) {
JOptionPane.showMessageDialog(null, entry[i].getInfo2());
break;
} else {
notfound++;
}
}
if (notfound != 0) {
JOptionPane.showMessageDialog(null, "Name Not Found!");
}
notfound = 0;
}
public void editEntry() {
int notfound = 0;
SName = JOptionPane.showInputDialog("Enter Name to edit: ");
for (int i = 0; i < counter; i++) {
if (entry[i].getName().equals(SName)) {
entry[i] = new AddressBookEntry();
entry[i].setName(JOptionPane.showInputDialog("Enter new name: "));
entry[i].setAdd(JOptionPane.showInputDialog("Enter new add: "));
entry[i].setPhoneNo(JOptionPane.showInputDialog("Enter new Phone No.: "));
entry[i].setEmail(JOptionPane.showInputDialog("Enter new E-mail: "));
break;
} else {
notfound++;
}
}
if (notfound != 0) {
JOptionPane.showMessageDialog(null, "Name Not Found!");
}
notfound = 0;
}
public void deleteEntry() {
SName = JOptionPane.showInputDialog("Enter Name to delete: ");
for (int i = 0; i < counter; i++) {
if (entry[i].getName().equals(SName)) {
JOptionPane.showMessageDialog(null, "Found!");
entry[i] = null;
break;
}
}
}
}
Assigning the values to null is going to be the easiest practice. If you're really picky, you could resize the array, but that would be rather pointless. Just keep a separate size counter and decrement it each time you set something to null.
Another reason you're getting a null pointer exception is that you have to consider what's happening when you're replacing values in your array with null but still iterating by counter. You're going to be left with holes in your array upon deletion. The first solution would be to bypass null values altogether, and just shift your array down (somewhat of an expensive operation). The second would be to alter your methods to take those null values into consideration. Example:
public void viewAll() {
String addText = " NAME\tADDRESS\tPHONE NO.\tE-MAIL ADD\n\n";
int nonNull = 0;
for (int i = 0; i < entry.length; i++) {
if (entry[i] != null) {
addText = addText + entry[i].getInfo() + "\n";
nonNull++;
}
if (nonNull == counter) break;
}
JOptionPane.showMessageDialog(null, new JTextArea(addText));
}
I don't have a compiler on this computer, so consider it more of psuedo-code. But the idea is that the counter is only keeping track of how many non-null values you have in your address book, and that these null values could be in random places of your array. I added the nonNull integer as a local counter to keep track of how many values you've encountered that aren't null (so you aren't forced to run through the entire address book). Then, I added the if statement to ensure that the value at entry[i] isn't a null value (trying to invoke getInfo() on a null value is what's giving you that error). Lastly, I added the if statement to break the loop if you've encountered all of the non-null values you have stored. Hope this helps. (Also it may be worth considering a LinkedList to eliminate the null values all together).
Actually, for simplicity's sake, you probably are much better off using a LinkedList, unless you are required to use an array, since you would need to alter all of your methods to take null spaces in your array into account. Assuming you're familiar with LinkedLists of course.
Arrays are immutable. You can change the value for a particular index in the array but you can't change the array size itself. To "delete", you could do:
myArray[index] = null;
And just treat null values as unset/deleted entries.
Assigning to null (currently what you are doing) is the proper thing to do. That will eliminate the reference to the object at that index and allow it to be garbage collected.
Replace entry[i] = null; with this:
System.arraycopy(entry, i + 1, entry, i, counter - i - 1);
--counter;
entry[counter] = null; // optional; helps with garbage collection
--i; // required to not skip the next element
(I'm assuming here that counter is the number of valid entries in entry. This will leave no null entries among the first counter elements of entry (assuming that there weren't any to start with).
Further thought: If you need the array length to always match the number of valid entries, you'll have to re-allocate the array and copy the values over. Just use arraycopy to copy entries from 0 through i-1 and from i+1 to counter-1 into the new array and then assign it to entry. This isn't particularly efficient and is best avoided if possible.
Better to this is List which has remove() method. But if you really want use Array I recommend you change Array to List and then remove all values, after it you can always change List to Array
import javax.swing.JOptionPane;
public class Test {
private static User[] entry = new User[] { new User("Gil"),
new User("Bil"), new User("John") };
public static void main(String... args) {
final Test test = new Test();
test.deleteEntry();
for (int index = 0; index < entry.length; index++) {
User user = entry[index];
if (user != null)
System.out.println(entry[index]);
}
}
public void deleteEntry() {
String SName = JOptionPane.showInputDialog("Enter Name to delete: ");
for (int index = 0; index < entry.length; index++) {
if (entry[index].getName().equals(SName)) {
JOptionPane.showMessageDialog(null, "Found!");
entry[index] = null;
break;
}
}
}
private static class User {
private String name;
public User(String name) {
this.name = name;
}
/**
* #return the name
*/
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
}
}

Categories