I want to know how do you access an attribute in a class inside an array like an example below:
import java.util.*;
public class DogTest{
public class Dog {
int Quantity;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Dog dogs[] = new Dog[15];
for ( int i = 1; i <=15; i++){
System.out.println("Enter number of Dogs ");
dogs[i].Quantity = scan.nextInt();
}
}
}
The code above does not seem to work. dogs[i].Quantity is derived from my C++ knowledge by the way.
Error msg:
Exception in thread "main" java.lang.NullPointerException
Is my structure wrong? Or there is another way to do it?
Arrays start at position 0. So at end of your loop you try to access dogs[15] which does not exist. Essentially an array of size 15 is accessed by numbers 0-14. This may be the problem.
Try starting loop like this
for(int i=0;i<15;i++)
{
}
First of all declare a class for itself, not as an inner class like you did.Never give fields first uppercase letter, that is naming convention.
public class Dog{
int quantity;
}
And, your actual problem is that when you declare an array of dogs, you declared an array of size, in your case, 15 but it doesn't contain any objects. You just initialised and array which holds 15 nulls and can be filled with Dog objects. And because that you get a null pointer exception.So, first you should fill your array with the dog objects, something like this:
for (int i = 0; i < dogs.length; i++){
dogs[i] = new Dog(); // calls a constructor for Dog object
}
And, after that, you can access your objects trough for loop to change a field quantity
for(int i = 0; i < dogs.length; i++){
dogs[i].quantity = i;
}
Also, I would recommend to make your fields private and make getter and setter methods for accessing and changing their value.
Edit: And yes, mikekane was right about the array size, you would get an ArrayIndexOutOfBoundsException just after you fix this problem with the code you've tried to solve it...
Related
Situation (new in java):
I would like to store random values into an array of objects of a class i created.
I created the following class:
private double color;
private double size;
// default constructor
public Example() {
color = 0.0;
size = 0.0;
}
// second constructor taking two arguments
public Example(double color, size imaginary){
this.color=color;
this.size=size;
}
// mutators
public void setColor(double c){
color=c;
}
public void setSize(double s){
size=s;
}
Now in my driver class:
I created the following
import java.lang.Math;
int num = 4;
Example[] array;
array = new Example[num];
for(int i=0;i<num-2;i++)
{
randomColor = Math.random();
randomSize = Math.random();
array[i].setColor(randomColor);
array[i].setSize(randomSie);
}
When i run the program i get the following error message:
Exception in thread "main" java.lang.NullPointerException
Im assuming that the content in each element of the array is null. But why is that? and how do i make the logic above work ?
Obviously i want to stay within the boundaries of my knowledge which is around the complexity of this code.
Thank you
You have only created an array of Example objects, but every element of it is null since you haven't created any Example object instances.
Arrays of "reference types" (anything that is a class, interface, enum or array, basically) start out with having null references in every element, and you still need to create the objects to put in the array.
Change your code to :
array[i] = new Example(randomColor, randomSize);
which will create new Example objects, and assign the random values to its properties.
This question already has answers here:
Why doesn't Java initialize Array Objects?
(2 answers)
Closed 6 years ago.
class checker
{
public checker()
{
System.out.println("In the constructor");
}
}
public class StringTesting {
static String string1;
static String string2;
public static void main(String[] args)
{
checker[] obj;
obj=new checker[10];
}
}
What can i do to call the constructor of all the 10 objects of class checker?obj=new checker[10] statement doesn't call the constructor i want to know why?
Your current code doesn't create any objects of type checker - it just creates an array which is capable of holding references to objects of type checker. Initially every element in the array has a value of null. It's important to understand that the array element values aren't checker objects - they're just references. Multiple elements could hold references to the same object, for example, just like multiple variables of type checker could have values referring to the same object. (You can think of an array as a collection of variables.)
If you want to call the constructor, you need to do so explicitly. For example:
// Names fixed to be more conventional
Checker[] checkers = new Checker[10];
for (int i = 0; i < checkers.length; i++) {
checkers[i] = new Checker();
}
obj=new checker[10]; means you are creating an array that can hold 10 instances of checker. This does NOT create 10 instances of checker. So the checker constructor will not be called.
What can i do to call the constructor of all the 10 objects of class
checker?
Create new instances of checker in a loop (or in some other way) and add them to your array.
obj=new checker[10] just sets obj to an array of checker objects. It does not fill the array with new checkers. To do that, you will need to do something like this:
obj=new checker[10];
for (int i = 0; i < obj.length; i++) {
obj[i] = new checker();
}
To answer your question more generally, to call the constructor, you must invoke the new keyword explicitly.
You are creating ten empty boxes(null references) to hold references of ten objects. For calling constructor for ten objects, you have to loop through these ten empty boxes and store reference of a new object in each box. i.e.
Checker[] chkArray = new Checker[10];
for (int i = 0; i < checkers.length; i++) {
chkArray[i] = new Checker();
}
i am copying object tt to ttt and i want to make change to ttt only but when i update ttt dunno why it update my tt along???? it's my makechange() function got problem?
this is main class:
package test;
public class Test {
public static void main(String[] args) {
Solution sol;
sol= new Solution();
sol.add();
sol.copy();
//this makechange function only update ttt only!!
sol.makechange();
sol.disOld();
System.out.println("===============");
sol.disNew();
}
}
this is new class:
package test;
import java.util.ArrayList;
import java.util.List;
public class Solution {
Object[][] tt=new Object[2][2];
Object[][] ttt=new Object[2][2];
List l = new ArrayList<>();
public void add(){
l.add(100);
tt[0][0]=l;
l = new ArrayList<>();
l.add(123);
tt[0][1]=l;
l = new ArrayList<>();
}
public void disOld(){
for(int i=0; i<tt.length; i++){
for(int j=0; j<tt[i].length; j++){
System.out.println(tt[i][j]);
}
}
}
public void copy(){
ttt=tt;
}
public void makechange(){
l.add(99);
ttt[1][0]=l;
}
public void disNew(){
for(int i=0; i<ttt.length; i++){
for(int j=0; j<ttt[i].length; j++){
System.out.println(ttt[i][j]);
}
}
}
}
this is my output:
[100]
[123]
[99]
null
===============
[100]
[123]
[99]
null
this is my expected output should be like this:
[100]
[123]
null
null
===============
[100]
[123]
[99]
null
Because = just copies the reference (pointer), not the object, so the real object you're referencing is the same. I suggest you use a copy constructor as explained here.
You can read a more extended explanation here (it's about ArrayList, but you can extrapolate to any other object).
Extract from that answer:
b = a
Keep in mind this lines DOES NOT copy the whole list a to b, but only
copies the reference to the list. Now both a and b reference (point)
to the same List. So it doesn't matter if you use a.add() or b.add(),
you'll be modifying the same List.
To help you understand the above, check the following diagram
The left diagram corresponds to when you do Object[][] tt=new Object[2][2];. You can see that you create an Object[2][2] instance in memory, which is the circle, and you assign a pointer (reference) to it called tt, which is the rectangle.
The right diagram corresponds to when you do ttt = tt. This means: "make ttt point to same object as tt". It does not copy anything for you. So now both tt and ttt point (reference) the same object instance in memory. So if you use tt or ttt, you will be modifying the same object instance.
I hope this clarifies what you're doing. As for fixing it, you should copy each element of the array one by one as explained in Duncan's answer. More generically, you should use a copy constructor to copy objects as I linked above.
The = just makes both references point to the same object. If you want to make a copy(in general), then have a look at Cloninng(Not Recommended) in Java or consider a Copy-Constructor.
To solve your problem, change your copy method to the following:
public void copy(){
for(int i=0; i<tt.length; i++)
for(int j=0; j<tt[i].length; j++)
ttt[i][j]= tt[i][j];
}
This is not how you copy an array:
public void copy(){
ttt=tt; // booo, hisss, etc.
}
After this method executes, ttt points at exactly the same array as tt. Changes made to that array are visible through both variables.
You need to properly copy the array, e.g. using a technique from How do I copy a 2 Dimensional array in Java?.
Lets say we have these two different constructors.
What is the different between the first one and the second one.
How is the way to do it? Explain the difference please!
(I know you cant have these two constructors in the same class, this is just to show what i mean.
public class StackOverFlow {
private int[] x; // instance variable
StackOverFlow(int[] x) { // constructor
this.x=x;
}
StackOverFlow(int[] x) { // constructor
this.x = new int[x.length];
for(int k=0 ; k < x.length; k++) {
this.x[k]=x[k];
}
}
The first constructor assigns a reference of an existing int array to the member variable. The caller of the constructor can later change the array and the change would be reflected in the instance.
The second constructor copies the array, so later changes in the passed array wouldn't change the copy stored in the instance.
int[] intArray = new intArray {1,2,3};
StackOverFlow so1 = new StackOverFlow(intArray); // assume we are using the first constructor
intArray[1]=5; // changes the array stored in `so1` object
StackOverFlow so2 = new StackOverFlow(intArray); // assume we are using the second constructor
intArray[1]=8; // doesn't change the array stored in `so2` object
In the first case you tell your instance variable to refer to the given x, so when you change data in one of these variables, that changes also affect the second variable.
And in the second case you create a copy of an object, so your instance variable and variable you pass to constructor will need independent from each other in your further code.
This will not work since you got an ambiguity issue as both constructors receive the same type of parameters. So when you try to create an instance :
StackOverflow instance = new StackOverflow(new int[]{});
There is no way to know which constructor should be called.
You need to decide which behavior is good for you.
I would recommend using the second constructor and create a setter method if you want to set the array from an initialized one :
public class StackOverFlow {
private int[] x; // instance variable
StackOverFlow(int[] x) { // conctructor
this.x = new int[x.length];
for(int k=0 ; k < x.length; k++) {
this.x[k]=x[k];
}
}
public void setTheArray(int[] x) {
this.x = x;
}
}
I have this code but when I run it it just gives me a NullPointerException
import javax.swing.JOptionPane;
public class System {
public static void main(String[] args) {
int a=Integer.parseInt(JOptionPane.showInputDialog("How many planets"));
Planet p[]=new Planet[a];
for (int i=1;i<=a;i++){
** p[i].setName("romain"); **
//line bugging is above
}
//for info the .setName method of the Planet class is
/*public void setName(String Na){
name=Na;
}*/
}
}
So my question is: can you use the incrementor as the array reference
You have not initialized any of your Planet references. That's why you are getting a NullPointerException.
Planet p[]=new Planet[a] creates an array of Planet references, but the contents are all initialised to null. You need to have something like this:
Planet p[] = new Planet[a];
for (int i = 0; i < a; ++i) {
p[i] = new Planet();
p[i].setName("whatever");
}
Yes, you can use your loop variable to index into the array. You can use the loop variable for whatever you want: it's just an ordinary variable that happens to be scoped to the loop.
Note that in Java arrays are always zero-based, not one-based. The first element is at index zero.
Your array doesn't say it's going to start at index 1 and it's not initialized to start at 1. Given your input style, you are setting number of plants as the array length.
start your loop at 0.
int a=Integer.parseInt(JOptionPane.showInputDialog("How many planets"));
Planet p[]=new Planet[a];
for (int i=0;i<a;i++)
{
// -------------------------------------------------------------------
p[i] = new Planet(); // initializing object reference
// -------------------------------------------------------------------
p[i].setName("romain");
}
EDITTED
*THE QUESTION CONTENTS ARE EXPLAINED IN COMMENTS*