I have a class called AgendaFunctions, a class called Main, and a class called ReadFiles. Main has a reference variable for Agenda Functions and ReadFiles. AgendaFunctions has an array of reference variables. I have code to instantiate the array, but i need to instantiate it from ReadFiles. If I instantiate it from main, it works fine. But if i call the method from ReadFiles, it doesn't work. I get a java.lang.NullPointerException error.
Here is the code for Main:
public class Main {
public static void main(String[] args) throws Exception {
ReadFiles fw = new ReadFiles(); fw.read();
agendafunctions link = new agendafunctions();
AgendaFunctions:
public class agendafunctions {
int amount = 20;
public void setamount(int data) {
}
static String input = "true";
agendaitem item[] = new agendaitem[amount];
int counter = 0;
public void instantiate() {
item[1] = new agendaitem();
item[2] = new agendaitem();
item[3] = new agendaitem();
}
public void createobject(String name, Boolean complete, String Comments) {
item[counter].name = name;
item[counter].complete = complete;
item[counter].comments = Comments;
counter++;
}
ReadFiles:
public class ReadFiles {
public void read() throws IOException {
agendafunctions af = new agendafunctions(); af.instantiate();
int readitem = 1;
BufferedReader data = new BufferedReader(new FileReader("C:/Agenda Dev Docs/data.txt"));
int filestoread = Integer.parseInt(data.readLine());
while (readitem <= filestoread) {
String name;
String complete;
String comments = null;
String line;
Boolean bc = null;
BufferedReader read = new BufferedReader(new FileReader("C:/Agenda Dev Docs/"+readitem+".txt"));
readitem++;
name = read.readLine();
complete = read.readLine();
comments = "";
while((line = read.readLine()) != null) {
comments = comments + line;
}
if(complete.equals("Complete")) {
bc = true;
} else if(complete.equals("Incomplete")) {
bc = false;
}
af.createobject(name, bc, comments);
}
}
If I call the method instantiate from ReadFiles, i get a NullPointerException. If I call it from Main, everything works. But further development requires me to call the method from ReadFiles. How would i fix this? Thanks.
You have this
int counter = 0;
public void instantiate() {
item[1] = new agendaitem();
item[2] = new agendaitem();
item[3] = new agendaitem();
}
public void createobject(String name, Boolean complete, String Comments) {
item[counter].name = name;
item[counter].complete = complete;
item[counter].comments = Comments;
counter++;
}
where item is an array with 20 indices, ie 20 elements, but your instantiate method only initializes elements at indices 1 through 3, missing 0 and 4 through 19.
In your ReadFiles#read() method, you do
agendafunctions af = new agendafunctions(); af.instantiate();
which instantiates one agendafunctions object and calls instantiate() which initializes elements at indices 1, 2, and 3 in your item array.
You then loop in the while and call
af.createobject(name, bc, comments);
a bunch of times on the same object.
The reason it fails the first time is because you haven't initialized the element in item at index 0. Arrays always start at 0, not 1.
Another cause for error (which you'll see if you fix the above problem), is that if your while loop loops more than 3 times, you'll again get a bunch of NullPointerExceptions because counter keeps growing, but you aren't initializing the elements that you'll then try to access at counter index.
item[counter].name = name; // if counter is 4, you'll get NullPointerException because
// the element there hasn't been initialized as 'new agendaitem();'
#SotiriosDelimanolis explained why you are getting NPE, to fix that you just can get rid of the instantiate() method and add item[counter] = new agendaitem(); as first line in your createobject method. Also you have to make sure your while loop does not exceed amount. To avoid these worries better use an ArrayList for agendaitem
Related
My program is suppose to take a text file, read the first four names, create a random number between 1-4, and then assign the names to 4 different teams based on what the random number was. For instance, if the number was 3, then the first name would go to team 3, second name to team 4, etc. etc.(repeat process until there are no more names) I believe I have all of the code for that correct, the problem is I can't figure out how to return all the names I have put into the arrays that were brought into the method. Here is my code:
public static void main(String args[]) throws IOException
{
BufferedReader girlFile = new BufferedReader(new FileReader("girls40.txt"));
PrintWriter teamFile = new PrintWriter(new FileWriter("xxxxxxx-teamlist.txt"));
String team1[] = new String[20];
String team2[] = new String[20];
String team3[] = new String[20];
String team4[] = new String[20];
int n;
n = loadTeams(team1,team2,team3,team4,girlFile);
girlFile.close();
teamFile.close();
}
public static String[] loadTeams(String team1[],String team2[],String team3[],String team[],BufferedReader girlFile)
{
int n;
int random;
String name1;
String name2;
String name3;
String name4;
while((name1=girlFile.readLine())!=null)
{
name2=girlFile.readLine();
name3=girlFile.readLine();
name4=girlFile.readLine();
random = 1 + (int)(Math.random() * 4);
if(random==1)
{
team1[n]=name1;
team2[n]=name2;
team3[n]=name3;
team4[n]=name4;
}
if(random==2)
{
team1[n]=name4;
team2[n]=name1;
team3[n]=name2;
team4[n]=name3;
}
if(random==3)
{
team1[n]=name3;
team2[n]=name4;
team3[n]=name1;
team4[n]=name2;
}
if(random==4)
{
team1[n]=name2;
team2[n]=name3;
team3[n]=name4;
team4[n]=name1;
}
n++;
}
return team1[],team2[],team3[],team4[];
}`
The main method was given to me, so it cannot be changed.
If there is more code in main method than you've posted here. You'll have to mention what is the variable n and how is it being used else follow the answer.
main Method can't be changed
In your main method,
int n;
n = loadTeams(team1,team2,team3,team4,girlFile);
girlFile.close();
teamFile.close();
} // End of Main Method
You have not used returned value n for nothing. So it really doesn't matter what you return from method loadTeams() as long as it is an int.
Also, here loadTeams() returns an String[] which can't be assigned be int n, you'll have to change return type of loadTeams() to int as
public static int loadTeams(String team1[],String team2[],String team3[],String team[],BufferedReader girlFile) {
/*
...
*/
return 0; // whatever, it isn't being used
}
This the solution if you can't change the main method.
The call to loadTeams() expects a return value of type int. Not an array or multiple arrays. If you can't change the main method then loadTeams should return an integer.
// ...
int n;
n = loadTeams(team1,team2,team3,team4,girlFile);
// ...
you don't have to return anything, arrays created in main() will be passed to your method by reference, you can fill them there, and after execution of your method, values will be kept in these arrays
The loadTeams should return an int and not String[].
There is no need to return arrays. Changes made in the arrays in the loadTeams methods will be reflected back to the array in main method.
I've read a text from file into an array. I'd like to iterate through this array in another class (to reverse an array and find every 5th element). I have a problem with use this array in another class - this class cannot see array. Could anyone help me?
package iterators;
import java.util.*;
import java.io.*;
import iterators.*;
public class Dunno{
int i = 1;
String[] something() throws IOException {
BufferedReader read = new BufferedReader(new FileReader("file.txt"));
StringBuilder sb = new StringBuilder();
String text = read.readLine();
while (text != null) {
sb.append(text);
sb.append("\n");
text = read.readLine();
}
String all = sb.toString();
String film = all;
String znak = ",";
String[] tab;
tab = film.split(znak);
for (i = 0; i < tab.length; i++) {
System.out.println(tab[i]);
}
return tab;
}
}
And 2nd class:
public class Dunno1{
Dunno dunn=new Dunno();
dunn.something();
public String dunn(){
//Iterate
}
}
In your second class you're calling the first class method in class scope, you're not calling it in a method or in main. Here is how you should do it:
public class Dunno1 {
public static void main(String[] args) throws IOException {
Dunno1 d1 = new Dunno1();
Dunno dunn = new Dunno();
String[] d = dunn.something();
d1.dunn(d);
}
public String dunn(String [] d) {
return null;
// Iterate
}
}
You need to construct an object of your second class as well so that you can call the dunn method and pass it the String array you're getting from your first class (That's why the signature of the method in my answer is different).
public class Dunno1{
Dunno dunn=new Dunno();
dunn.something();
public String dunn(){
//Iterate
}
}
The above doesn't compile, because you can't execute instructions directly inside classes. Classes must contain field declarations, constructors and methods. But not instructions.
The following would compile:
public class Dunno1{
public void foo() {
Dunno dunn = new Dunno();
String[] array = dunn.something();
// iterate over the array.
}
}
This is realy basic stuff that you should learn by reading a Java book, or a tutorial. Not by asking questions on StackOverflow.
I am getting a null exception error from this segment of code and I am not sure what causing it. The array itemcatalog has being populate for i =0 to 8. I am new to java so any assistance will be greatly appreciated. The error message points to the line of the while statement. Thanks
public class ItemCatalog {
private static ItemCatalog instance = new ItemCatalog();
private Item itemCatalog[] = new Item[9];
private ItemCatalog(){
};
public static synchronized ItemCatalog getInstance() {
return instance;
}
public void populateCatalog()
{
itemCatalog[0] = new Item("bb","Baked Beans",new BigDecimal("0.35"));
itemCatalog[1] = new Item("cf","Cornflakes",new BigDecimal("1.00"));
itemCatalog[2] = new Item("s0","Sugar",new BigDecimal("0.50"));
itemCatalog[3] = new Item("tb","Tea Bags",new BigDecimal("1.15"));
itemCatalog[4] = new Item("ic","Instant Coffee",new BigDecimal("2.50"));
itemCatalog[5] = new Item("b0","Bread",new BigDecimal("0.50"));
itemCatalog[6] = new Item("s0","Sausages",new BigDecimal("1.30"));
itemCatalog[7] = new Item("e0","Eggs",new BigDecimal("0.75"));
itemCatalog[8] = new Item("m0","Milk",new BigDecimal("0.65"));
}
public BigDecimal getPrice(String itemCode)
{
int i = 0;
while (!itemCode.equals(itemCatalog[i].getItemCode()))
{
i++;
}
BigDecimal itemPrice = itemCatalog[i].getItemprice();
return itemPrice;
}
}
I solved the issue. I was populating the catalog in the main class which was giving the null exception error. I instantiate it in the jframe instead and it works. The follow code solved the issue, but is this the best place to populate the catalog?
private void saleButtonActionPerformed(java.awt.event.ActionEvent evt) {
String itemCode = this.itemCodeinput.getText();
int itemQuantity =Integer.parseInt(this.itemQuantityinput.getText());
ItemCatalog catalog = ItemCatalog.getInstance();
catalog.populateCatalog();
BigDecimal price = catalog.getPrice(itemCode);
itemCostoutput.setText(price.toString());
}
If your itemCode doesn't match any entries in your itemCatalog, then eventually
while (!itemCode.equals(itemCatalog[i].getItemCode()))
{
i++;
}
will increment i to 11, in which case itemCatalog[11] is either empty or out of bounds.
If addition, you should use a for loop to iterate through the itemCatalog:
for (int i = 0; i < itemCatalog.length; i++) {
if (itemCode.equals(itemCatalog[i].getItemCode()) {
return (BigDecimal) itemCatalog[i].getItemprice();
}
}
return null // you can change this from null to a flag
// value for not finding the item.
From the comments, it's clear the design isn't sound.
Here's a possible solution :
public BigDecimal getPrice(String itemCode) {
for (int i=0; i<itemCatalog.length; i++) { // not going outside the array
if (itemCatalog[i].getItemCode().equals(itemCode)) { // inversing the test to avoid npe if itemCode is null
return itemCatalog[i].getItemprice();
}
}
return null; // default value
}
This supposes your array is correctly filled with itemCatalogs having an itemCode.
How do you end your loop?
Seems that the loop will keep going until i is 10. Then your will have exceeded the limit.
Unless this is a uni assignment where you have to use arrays, I'd also suggest using a map, rather than an array. This way your lookup will be the same time, whether your collection has 100,000 entries or 10.
You will also reduce risk of NPE or ArrayOutOfBounds exception
See http://docs.oracle.com/javase/1.4.2/docs/api/java/util/HashMap.html
When adding the object use the item code as the key. Then lookup by the key.
The cost of using a map is increased memory usage.
public class J {
public Integer method(Integer x)
{
Integer val = x;
try
{
return val;
}
finally
{
val = x + x;
}
}
public static void main(String[] args)
{
J littleFuzzy = new J();
System.out.println(littleFuzzy.method(new Integer(10)));
}
}
It will return "10".
Now I just replace Return type Integer to StringBuilder and Output was changed.
public class I {
public StringBuilder method(StringBuilder x)
{
StringBuilder val = x;
try
{
return val;
}
finally
{
val = x.append("aaa");
}
}
public static void main(String[] args)
{
I littleFuzzy = new I();
System.out.println(littleFuzzy.method(new StringBuilder("abc")));
}
}
OutPut is "abcaaa"
So, Anybody can explain me in detail.?
what are the differences.?
Just because integer in immutable so after method returns even if value is changed in method it does not reflect, and does reflect in StringBuilder Object
EDIT:
public class J {
public String method(String x) {
String val = x;
try {
return val;
} finally {
val = x + x;
}
}
public static void main(String[] args) {
J littleFuzzy = new J();
System.out.println(littleFuzzy.method("abc"));
}
}
The principal operations on a StringBuilder are the append and insert methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string builder. The append method always adds these characters at the end of the builder; the insert method adds the characters at a specified point.
For example, if z refers to a string builder object whose current contents are "start", then the method call z.append("le") would cause the string builder to contain "startle", whereas z.insert(4, "le") would alter the string builder to contain "starlet".
In general, if sb refers to an instance of a StringBuilder, then sb.append(x) has the same effect as sb.insert(sb.length(), x). Every string builder has a capacity. As long as the length of the character sequence contained in the string builder does not exceed the capacity, it is not necessary to allocate a new internal buffer. If the internal buffer overflows, it is automatically made larger.
Instances of StringBuilder are not safe for use by multiple threads. If such synchronization is required then it is recommended that StringBuffer be used.
In above method, finally block is calling everytime.
When an object is passed, the copy of its reference gets passed and you can change the contents if it is mutable.
I am writing a program that has two final variables that I wish to use, I need these to be set at the time that I actually run the class because they are likely to be different each instance.
I have the initialization the same as any other class variable I wish to use where I initialize a name and type but not a value.
public final String filename, filepath;
In the Constructor I set the values as follows
public myClass(String value) {
this.filename = value;
this.filepath = anotherPartOfValue;
}
When I do this, I get a warning that "The final field [x] may have already been assigned"
Is there a way to avoid this warning and still keep the final state and set the value in the constructor?
I am using eclipse btw.
Edit:
This is the exact code that gives me the error
import java.io.*;
public class Dirt {
private String[] tables;
private int numTables;
private final String filename, filepath;
public Dirt(String file) {
this.tables = new String[0];
this.numTables = 0;
for (int i = file.length(); i < 0; i--) {
if (file.charAt(i) == '/') {
this.filename = file.substring(i);
this.filepath = file.substring(1, i-1);
}
}
}
}
The problem is that you are assigning to the final variables in a loop. There's nothing to prevent the loop from looping more than once and the if condition being satisfied more than once. (What happens if there are two '/' characters in file? Or none?)
One way around this is to use temporary String variables in the constructor and then assign them to filename and filepath at the end:
public Dirt(String file) {
this.tables = new String[0];
this.numTables = 0;
String name = null;
String path = null;
for (int i = file.length(); i < 0; i--) {
if (file.charAt(i) == '/') {
name = file.substring(i);
path = file.substring(1, i-1);
// need a break here?
}
}
this.filename = name;
this.filepath = path;
}
It's ugly, but it's a straightforward way to know for sure that filename and filepath will definitely be assigned and definitely be assigned only once.
Completely compileable and runnable:
public static void main(String[] args) {
Foo f = new Foo("abc");
System.out.println(f.filename);
System.out.println(f.filepath);
}
static class Foo {
public final String filename, filepath;
public Foo(String value) {
this.filename = value;
this.filepath = value.substring(1);
}
}
And the "warning" you mention isn't just a warning. It's an error. But it's not coming from here.
Edit: Your newly posted code has the assignments in a loop. By definition, statements in a loop can execute multiple times, and therefore you have the potential for assigning the final variables multiple times.