I am new to Java and trying to learn it. I wrote two class as follows, and I expect to print as 1, 2, 3 but it prints 3, 3, 3. I read a java book about I couldn't figure out the above behavior and print 1, 2, 3.
public class Student{
private static int indexNumber = 0;
Student(){
indexNumber=indexNumber+1;
}
public void test() {
System.out.println(this.getIndexNumber());
}
public int getIndexNumber(){
return indexNumber;
}
}
public class College {
public static void main(String args[]){
Student student1 = new Student();
Student student2 = new Student();
Student student3 = new Student();
student1.test();
student2.test();
student3.test();
}
}
Can anyone help?
indexNumber is static, so it's "shared" between every instance of the class.
If you want a unique, incrementing ID, do the following:
static int nextID = 1;
int indexNumber;
Student() {
indexNumber = (nextID++);
}
This makes indexNumber an instance field, so that each Student gets its own copy. The static variable is used to keep track of the next ID to be assigned.
You get 3,3,3 because you have defined the variable indexNumber as static. So when instantiating three student objects the indexNumber gets value 3.
To increment define the indexNumber as instance variable and pass the value for it as parameter.
Your field is static.It will be shared by all objects.
private static int indexNumber = 0;
s1-------->indexNumber<------s2
^
|
|
|
s3
Instantiating each time,the constructors gets called,which increments the indexNumber by 1.
indexNumber is declared as static and its common to all objects. Hence you got 3,3,3
Static members are associated with the class, rather than with any object.
Static members are shared with all objects. You not indexed, you counted with your test.
Since you have declared the INDEX NUMBER as static, therefore it will be shared by every instance you create for the class. The answer which you were expecting will come in the case you remove the static keyword. That's why for all three objects you get the same value for index number. I hope it's clear to u now. Thank you.
Related
I am learning Java, so I understand this is a very simple question, but I still want to understand it.
I want to let my code automatically generate soldiers, and the number automatically increases, but I failed.
the Soldier.class:
package com.mayer;
import java.util.Random;
public class Soldier {
private int number=0;
private int ATK;
private int HP;
Random ra = new Random();
public Soldier(){
this.number++;
this.ATK = ra.nextInt(10)+90;
this.HP = ra.nextInt(20)+180;
}
public void report(){
System.out.println("number:"+this.number+"\t"+
"ATK:"+this.ATK+"\t"+
"HP:"+this.HP);
}
}
the main.class
package com.mayer;
public class Main {
public static void main(String[] args) {
Soldier[] soldiers = new Soldier[5];
int i = 0;
while(i<5){
soldiers[i] = new Soldier();
i++;
}
for(Soldier sol:soldiers){
sol.report();
}
}
}
That's what I get:
number:1 ATK:94 HP:187
number:1 ATK:94 HP:181
number:1 ATK:96 HP:193
number:1 ATK:90 HP:183
number:1 ATK:95 HP:193
So you see,each of this number is 1.
You have added number field which is instance field. It will initialize per instance. You are looking for static type variable. Please check static into java.
Instance Variables (Non-Static Fields) Technically speaking, objects
store their individual states in "non-static fields", that is, fields
declared without the static keyword. Non-static fields are also known
as instance variables because their values are unique to each instance
of a class (to each object, in other words); the currentSpeed of one
bicycle is independent from the currentSpeed of another.
Class Variables (Static Fields) A class variable is any field declared with the static modifier; this tells the compiler that there
is exactly one copy of this variable in existence, regardless of how
many times the class has been instantiated. A field defining the
number of gears for a particular kind of bicycle could be marked as
static since conceptually the same number of gears will apply to all
instances. The code static int numGears = 6; would create such a
static field. Additionally, the keyword final could be added to
indicate that the number of gears will never change.
The constructor is changed to:
public Soldier(int number){
this.number = number;
this.ATK = ra.nextInt(10)+90;
this.HP = ra.nextInt(20)+180;
}
As others have said, each Soldier instance has its own separate number field which starts with 0. You can use a static field to count the instances:
public class Soldier {
private static int counter = 0;
private int number;
// other fields left out for clarity
public Soldier(){
Soldier.counter++; // field shared among all Soldier instances
this.number = counter; // number belongs to this instance only
// ...
}
// ...
}
However, I wouldn't recommend doing it this way. When you get more advanced, you'll learn that using a static field like this can cause problems in a multi-threaded application. I would instead advise passing the number to the Soldier constructor:
public class Soldier {
private int number;
// ...
public Soldier(int number){
this.number = number;
// ...
}
// ...
}
And then:
public static void main(String[] args) {
Soldier[] soldiers = new Soldier[5];
int i = 0;
while(i<5){
soldiers[i] = new Soldier(i);
i++;
}
Soldier.class
all-uppercase field names tend to be used for constants.. basic fields use headless camel-case.. They should also be descriptive, i.e. you should look at them an it should be apparent what they represent - for example a variable "number" is not a good idea, because it's ambiguous
Random can be converted to a local variable, no need to keep it on the class level
The mechanism by which soldiers are assigned IDs should be on a higher level - it can't be managed by the soldier object itself, hence the constructor with an argument
overriding the toString method is the traditional way of transforming the object to string for debugging purposes.. also most IDEs can generate it with a press of a button so no space for human error
You will obviously need getters and setters for your variables, if you wish to read or change them from elsewhere, but I don't think that's necessary to post here.
private int soldierID;
private int attack;
private int health;
public Soldier(int id){
this.soldierID = id;
Random random = new Random();
this.attack = random.nextInt(10) + 90;
this.health = random.nextInt(20) + 180;
}
#Override
public String toString() {
return "Soldier{" +
"soldierID=" + soldierID +
", attack=" + attack +
", health=" + health +
'}';
}
Main.class
it's perfectly fine and actually preferred to use a List instead of an array, because it's more comfortable to work with
this way it's even much easier to add them dynamically and use the iterator for ID
you can "report" in the creation cycle
This even shortens the method a bit, not that it's that important here.
public static void main(String[] args){
List<Soldier> soldiers = new ArrayList<>();
for(int i=0; i<5; i++){
Soldier newSoldier = new Soldier(i);
soldiers.add(newSoldier);
System.out.println(newSoldier.toString());
}
}
This way when you define the soldier IDs it's not from within the Soldier class but rather from something that is "observing" all the soldier classes and knows which is which.
I want to build a method that when it is called in main, automatically increment the value of variable.If first value is 0 when its called increment it to 1 , when I call for second time from 1 to be incremented at 2 and so on.
Notes: The method is part of a class and it called via object in main.
you can use the static variables. Static variables are initialized only once, at the start of the execution. These variables will be initialized first, before the initialization of any instance variables.
Create a static variable whose value can be updated in a function.
let this be your class
class Student {
static int b; //initialized to zero only when class is loaded not for each object created.
public void update(){
//incrementing static variable b
b++;
}
public void showData(){
System.out.println("Value of b = "+b);
}
}
and this be your main class
public class Demo{
public static void main(String args[]){
Student s1 = new Student();
s1.update();
s1.showData();
Student s2 = new Student();
s2.update();
s1.showData();
}
}
output:
Value of b = 1
Value of b = 2
Well, you kinda left a lot up for interpretation here, assuming the "value of variable" is part of the object the code would be something like this:
public class MyClass {
public int myVariable = 0;
public MyClass() {}
public void incrementMyVariable() {
myVariable++;
}
}
How you would handle this depends on where the variable your referring to is located ie. main method, object variable, etc... Additionally, if the variable needs to be kept constant across all the objects created for the class you would need it to be static.
class Thing {
public static int count = 0;
public int id = 0;
public Thing() {
id = count;
count++;
}
public void ID() {
System.out.println("This object has id: " + id);
}
}
public class wth {
public static void main(String[] args) {
Thing thing1 = new Thing();
Thing thing2 = new Thing();
Thing thing3 = new Thing();
thing1.ID();
thing2.ID();
thing3.ID();
}
}
Shouldn't this code print 1
1
Here is what I understand of the code:
First of all, the thing1 object is created and the constructor Thing runs thus making id=0 and count=1. Then thing2 is created and again the constructor runs making id=1 and count=2.
Now thing1.ID() runs printing the value of id which should be 1 but instead its 0 please explain how is it 0.
public static int count=0;
This line means that the variable count is linked to the class, not the object. So every time a new Thing is created, the incrementation of this variable is applied across all the objects instantiating the class, including new instances that are made.
You can find more info in the official doc/tutorial here.
This code illustrates the way static works. count is shared among all objects of the class, so it gets incremented each time a new Thing object is instantiated.
Note: This will break in concurrent environments: if you run this from multiple threads, some objects may get the same id. A better implementation would use AtomicInteger:
class Thing{
public static AtomicInteger count = new AtomicInteger(0);
public int id;
public Thing(){
id=count.incrementAndGet();
}
...
}
count is static, which is why it gets incremented each time you create a new instance of Thing but id isn't. That means that each instance of Thing, being thing1and thing2 will each have their own id.
In your question:
value of id which should be 1 but instead its 0 please explain how is
it 0.
What I understood, you asking for first time you create object it's value should be 1 and next time increment by 1. If it is asked for,
Reason:
When you create first object(thing1) you are calling default constructor(Thing()), which you have implemented. And in the first line you assigning count variable value to id variable which is 0. Then you increment count by one. It is not affecting to id variable first time. Then, you call the ID() method, it will print, value that it hold 0.
Solution:
public Thing() {
id = count;
count++;
}
move the count++; to first line. Should be:
public Thing() {
count++;
id = count;
}
Output become:
This object has id: 1
This object has id: 2
This object has id: 3
Because of static each time you create new object count will increment.
If you want to get outputt as 1 every time:
First you want to know about static keyword:
Attributes and methods(member of a class) can be defined as static.
static members do not belongs to an individual object.
static members are common to all the instances(objects of the same class).
static members are stores in static memory(a common memory location which can by everybody).
The static modifier indicates that the count variable(attribute) are common to all the Thing in the whole class rather than to an individual object.
To answer your question:
public static int count = 0;
As I mention above this count variable common for all the objects. That means when you create a different objects it's value not changed.
remove the static modifier, should be:
public int count = 0;
When you removed static modifier count variable become individual for all the objects that you are creating. And for each object it will print as follows:
This object has id: 0
This object has id: 0
This object has id: 0
If you move the count++; to first line.
public Thing() {
count++;
id = count;
}
Output become:
This object has id: 1
This object has id: 1
This object has id: 1
class Person {
public static int age = 10;
}
public class Application {
public static void main(String[] args) {
Person p = new Person();
p.age = 100;
System.out.println(Person.age);
Person.age = 22;
System.out.println(p.age);
}
}
I got 100 and 22 printed. Was I wrong in assuming that instances of a class cannot access/modify class/static variables.
I think the part your confused by is the meaning of static. the age variable in class Person will be shared across all instances of Person, and can be accessed with no instance at all via:
Person.age = 100;
Changing it for any instance:
Person p = new Person();
p.age = 100;
changes it for everyone, and is the same as calling
Person.age = 100;
Changing it in a non static way, meaning via some instance only makes the code misleading by making people think they are changing an instance variable at first glance. You will get a compiler warning about this.
Yes, they can. From the docs:
Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class
Of course an instance of a class can access and modify a static field, if it's accessible to that scope.
What cannot happen is a static statement/method body modifying an instance it does not "know about", e.g. a static method using this.
Example
public class Main {
private static int meh = 0;
int blah = 0;
public static void main(String[] args) {
// ugly but compiles fine
// equivalent to Main.meh = 1
meh = 1;
// Will NOT compile - main method is static,
// references instance field "blah" out of scope
// Equivalent to this.blah = 1
blah = 1;
}
}
Say I wanted to make a class to hold a set of integers that would be accessed from multiple other classes and instances. I don't want them reverting to the value they had when the code was compiled. Does that mean they have to be static, in order to keep them from going back their original value? For example
The original stats holding class here:
public class Stats() {
public static int numOne = 0;
public static int numTwo = 5;
public static int numThree = 3
//etc...
}
It is called on in two places. Here:
public class exampleClass() {
private Stats stats = new Stats();
stats.numOne += 5;
//More variable changes.
}
Also here:
public class exampleClassTwo() {
private Stats stats = new Stats();
stats.numOne -= 3;
//More variable changes.
}
Will these calls reset the variables to their original class value if the variables are not static? If so, does that mean they should always be static?
No, the variables will maintain state without the static modifier
No. You would use static key word for using those values without initializating them.
public class Stats() {
public static int numOne = 0;
public static int numTwo = 5;
public static int numThree = 3
//etc...
}
public class exampleClass() {
int a = 0;
a += Stats.numThree;
System.out.println(a);
}
>>> 3;
No need for static attributes in your case indeed, each class instance will contain a private copy of attributes initialized at instance creation time, and records all subsequent modifications until object is deleted (in java it means no longer referenced).
Main usage for static is either to store constants or global state (e.g. a singleton instance).
Doing,
private Stats stats = new Stats();
stats.numOne += 5;
Kind of defeats the purpose of having numOne as static.
The static field numOne should be accessed in a static way i.e as follows: Stats.numOne
static variables are Class variables and are used when we want to maintain a value across instances of the class. So modifying the value of numOne across various functions will keep on changing the value of class variable numOne. Run the following code to see the effect of having a class variable in a class:
public class StaticVarDemo {
public static int staticCount =0 ;
public StaticVarDemo(){
staticCount++;
}
public static void main(String[] args) {
new StaticVarDemo();
StaticVarDemo.staticCount +=5;
System.out.println("staticCount : " + StaticVarDemo.staticCount);
new StaticVarDemo();
new StaticVarDemo();
System.out.println("staticCount : "+staticCount);
}
}
It will give the output:
staticCount : 6
staticCount : 8
Yes, when you instantiate an object, variables will be initialized to the class values when they are not static.
When a variable has the static keyword, that variable value persists over all instances: the two places you called it each create an object, both objects have the same values for their static variables (even if they are changed).
Variables without the static keyword are unique to the instance: changing it on one object doesn't affect its value on the other.
See here for more info:
What does the 'static' keyword do in a class?
It seems after some research a singleton did the job. Creating one singular instance but calling on it more then once.
See Here:
http://www.tutorialspoint.com/java/java_using_singleton.htm