I'm making a game in java and consistenetly get the strangest bug. I have a class called weapon. Then I create an instance of it called primary. After I create an instance and call it secondary. for some strange reason, primary gets overwritten with secondary's values. My instructor and I both looked at it and couldn't figure it out. Here's the code:
public class weapon {
static String type;
static String name;
static int weight;
static int damage;
static int dodge;
weapon(String c, String n, int w, int da, int dod) {
type = c;
name = n;
weight = w;
damage = da;
dodge = dod;
}
//getters
String getType(){
return type;
}
String getName(){
return name;
}
Integer getWeight(){
return weight;
}
Integer getDamage(){
return damage;
}
Integer getDodge(){
return dodge;
}
//setters
void setType(String c){
c=type;
}
void setName(String n){
n=name;
}
void setWeight(Integer w){
w=weight;
}
void setDamage(Integer da){
damage=da;
}
void setDodge(Integer dod){
dodge=dod;
}
}
/*At the top of my main class I create both instances like this because the instances are created in if statements and I need to access them.*/
weapon primary;
weapon secondary;
//I create primary like this earlier in the code like this
primary = new weapon("primary","sword", 8, 6, -1);
//and then when I run this I get the output "sword" "Heavy Sword".
System.out.println(primary.getName());
secondary = new weapon("secondary", "huge sword", 9, 7, -2);
System.out.println(primary.getName());
All your member variables are defined as static :
static String type;
static String name;
static int weight;
static int damage;
static int dodge;
That's why the values of the second instance override the first (since static members are class veriables - there is a single copy of them across all instances of the class).
Removing the static keyword would solve the problem.
All the properties of your Weapon class are static, which means they are shared among all instances you create.
Remove static to make them instance variables instead, and you should be fine.
You have created a class with class wide variables rather than variables that are different for each object created.
Instead use:
public class weapon {
private String type;
private String name;
private int weight;
private int damage;
private int dodge;
weapon(String c, String n, int w, int da, int dod) {
I would suggest you use the following pattern when you define classes to help ensure your "class fields" and "object fields" are well described
public class <name-of-class> {
// Class fields
<private|public|protected> [final] static ....
// Object fields
private ...
All the member variables are declared as static. When you declare a member variable as static all the objects of that class shares the same copy of those variables. If one object changes value on a variable, it changes for other objects as well.
Simply remove the static keyword.
Weapon appears to be a bean class, it' better to encapsulate if properly with private member variable and public getter/setters.
Related
I have problem with my Java program. Class Wolumin is responsible for giving unique ID for the objects in Object tab, but it always gives same number to every object. I tried giving variety of acces privilages to it, but nothing seems to be working. In this case each tab object have ID=4, but i want it to be in order :1,2,3,4...
public class First {
public static void main(String args[]){
Object[] tab = new Object[4];
tab[0]=new Ksiazka("Malysz","Homies");
tab[1]=new Ksiazka("Pudzian","Malta");
tab[2]=new Czasopismo("Bravo","420");
tab[3]=new Czasopismo("Grzyby","2137");
System.out.println(tab[0].toString());
System.out.println(tab[1].toString());
System.out.println(tab[2].toString());
System.out.println(tab[3].toString());
}
}
abstract class Wolumin{
static int id;
Wolumin(){id++;};
}
class Ksiazka extends Wolumin{
String autor,tytul;
Ksiazka(String x, String y){
this.autor=x;this.tytul=y;
}
public String toString(){
return (Ksiazka.id+","+autor+","+tytul);
}
}
class Czasopismo extends Wolumin{
String tytul,numerWydania;
Czasopismo(String x, String y){
tytul=x;
numerWydania=y;
}
public String toString(){
return (Czasopismo.id+","+tytul+","+numerWydania);
}
}
Your id is marked static, so all instances of Wolumin will have the same value of that variable. You need to have an additional instance variable that is unique to each instance. For example:
abstract class Wolumin{
static int id;
private final int myId;
Wolumin(){
myId = id++;
};
int getMyId() {
return myId;
}
}
And then:
class Ksiazka extends Wolumin{
String autor,tytul;
Ksiazka(String x, String y){
this.autor=x;this.tytul=y;
}
public String toString(){
return (getMyId()+","+autor+","+tytul); // use myId instead
}
}
class Czasopismo extends Wolumin{
String tytul,numerWydania;
Czasopismo(String x, String y){
tytul=x;
numerWydania=y;
}
public String toString(){
return (getMyId()+","+tytul+","+numerWydania); // use myId instead
}
}
How to fix the issue?
Re-arrange the System.out.println statements to print immediately after an object is created.
Working code:
tab[0]=new Ksiazka("Malysz","Homies");
System.out.println(tab[0].toString());
tab[1]=new Ksiazka("Pudzian","Malta");
System.out.println(tab[1].toString());
tab[2]=new Czasopismo("Bravo","420");
System.out.println(tab[2].toString());
tab[3]=new Czasopismo("Grzyby","2137");
System.out.println(tab[3].toString());
Output of the working code:
$ java First
1,Malysz,Homies
2,Pudzian,Malta
3,Bravo,420
4,Grzyby,2137
Have a look at java.util.concurrent.atomic.AtomicInteger if you need a threadsafe solution beyond QBrute's approach.
This class has the methods incrementAndGet() and getAndIncrement(), which both do what you need.
I have been tasked to declare variables in a constructor but I am not sure how I can go about with this. The request states:
"In the constructor, create the Startrek Asteroids Resort given in the Appendix(see below)"
Lucozade,3,10
Fanta,5,2
Sprite,1,100
Coco,1,1
And here is my constructor:
public Asteroid(String nam, int rat, int cap)
{
name = nam;
rating = rat;
capacity = cap;
}
I had considered creating a text file and creating a method to read the data but I'm not sure if this is what they want.
If you want to save the parameters that are passed in you can just have variables that are declared in your class before hand and save them to these variables.
public class Asteroid {
private String name;
private int rat;
private int cap;
public Asteroid(String name, int rat, int cap) {
this.name = name;
this.rat = rat;
this.cap = cap;
}
}
Below is part of my code for class Range, and a constructor in a separate class called Tree. In this constructor, I am trying to instantiate the objects in class range over to my tree class. When I try to compile my constructor in the tree class, it says the methods I am trying to call cannot be referenced from a static context. Am I going about this the right way? I'm pretty sure this is quite an easy fix but I can't figure it out. Thanks
public class Range{
int low, high;
public Range(int plow, int phigh){
low = plow;
high = phigh;
}
public int getLow(){
return low;
}
public int getHigh(){
return high;
}
public class Tree {
String name;
public Tree(String pname, int plow, int phigh) {
name = pname;
Range.getHigh() = phigh; <---where error message is
Range.getLow() = plow;
}
}
Your code has two problems: first, getLow() and getHigh() are instance methods, not class methods. However, you call them by Range.getLow() and Range.getHigh(), meaning that you call them on the class Range. This is not allowed. First you have to create an instance of the class:
ran = new Range(...)
and then you call the methods on this instance:
ran.getHigh();
ran.getLow();
The other problem with your code is that you are trying to assing values to method calls:
Range.getHigh() = phigh;
This is not possible in Java. Java methods return values and you cannot assign to a value. That is, the method getHigh() and getLow() are meant to read the high and low value of a range, not set them. Setting these values is, in the case of the class Range, only possible by calling the constructor.
What you probably wanted to do, is add a member variable of type Range to the Tree class, and then set that variable in the constructor:
ran = new Range(plow, phigh);
You have to make an Object of Range before you can call its methods
public Tree(String pname, int plow, int phigh){
name = pname;
Range ran = new Range(phigh, plow);
}
use setter to set variable
public class Range{
static int low, high;
public Range(int plow, int phigh){
low = plow;
high = phigh;
}
public static int getLow(){
return low;
}
public static int getHigh(){
return high;
}
public static void setLow(int low) {
Range.low = low;
}
public static void setHigh(int high) {
Range.high = high;
}
and then call static methods to set values or get
public class Tree{
String name;
public Tree(String pname, int plow, int phigh){
name = pname;
Range.setHigh(phigh); //---where error message is
Range.setLow(plow);
}
}
VERY new to Java, so I am feeling like a child right now. The joys of learning a new language I guess.
Here is my Invoice Class:
public class Invoice {
//member inits
private int numberOfInvoices = 0;
private String companyName;
private double amountDue;
private String chargeDate;
private static int invoiceNumber = 0;
//constructor
public Invoice(String _companyName, double _amountDue, String _chargeDate)
{
numberOfInvoices++;
companyName = _companyName;
amountDue = _amountDue;
chargeDate = _chargeDate;
invoiceNumber = numberOfInvoices;
}
//getters
public String getCompanyName()
{
return companyName;
}
public double getAmountDue()
{
return amountDue;
}
public String getChargeDate()
{
return chargeDate;
}
public int getInvoiceNumber()
{
invoiceNumber = numberOfInvoices + 1;
return invoiceNumber;
}
//setters
public void setCompanyName(String _companyName)
{
companyName = _companyName;
}
public void setAmountDue(double _amountDue)
{
amountDue = _amountDue;
}
public void setChargeDate(String _chargeDate)
{
chargeDate = _chargeDate;
}
//helpers
public int incrementInvoices()
{
return numberOfInvoices++;
}
}
And here is the main method where I am trying to create three of these invoices, but increment the invoice number each time a new one is created.
public class InvoiceCreator {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Invoice invoice1 = new Invoice("Amazing Software", 5000.00, "January 18, 2009");
System.out.println(invoice1);
Invoice invoice2 = new Invoice("Best Programs", 4000.00, "February 18, 2009");
System.out.println(invoice2);
Invoice invoice3 = new Invoice("Champion Code", 3000.00, "March 18, 2009");
System.out.println(invoice3);
}
}
I'm also new to the IDE (netbeans), but through debugging and looking at each of the classes I created, all the fields are being initialized correctly, but the invoiceNumber = 1 on every one of them.
What am I doing incorrectly here?
You need to use a static field to generate incremental invoice numbers, not store the individual invoice numbers.
Try this:
public class Invoice {
//member inits
private static int nextInvoiceNumber = 0;
private String companyName;
private double amountDue;
private String chargeDate;
private int invoiceNumber = 0;
//constructor
public Invoice(String _companyName, double _amountDue, String _chargeDate)
{
invoiceNumber = nextInvoiceNumber;
nextInvoiceNumber++;
companyName = _companyName;
amountDue = _amountDue;
chargeDate = _chargeDate;
}
....
Declare numberOfInvoices to be static, so that there is a single value for the entire class, rather than a separate value for each instance.
private static int numberOfInvoices = 0;
You declared invoiceNumber as static, but numberOfInvoices is not static. In your constructor you are incrementing the number of invoices - which, being non-static, is initialised to 0 every time you create an instance of it. Then you assign this value to your invoice number.
The simple fix for your case is to declare the numberOfInvoices as static and invoiceNumber as non static:
private static int numberOfInvoices = 0;
private int invoiceNumber;
then you'll get the desired behaviour.
At the same time, it's worth noting that this implementation is ok for the purpose of learning the language, however it will not work for a production system, because the number will still be reset to 0 when the application exits and is restarted. In a production system, you would want to keep this number in a database or external file somewhere. You would then need to ensure that it's incremented in a thread-safe manner. In a production system, your logic would be something like this:
private int invoiceNumber;
private Object sync;
public Invoice(...) {
synchronised(sync) {
invoiceNumber = loadLastInvoiceNumberFromStorage();
invoiceNumber++;
writeLastInvoiceNumberFromStorage(invoiceNumber);
}
...
}
numberOfInvoices should be static. invoiceNumber should not be static. And you should synchronize the access to this field. See also: What is the best way to increase number of locks?
numberOfInvoices isn't the static member.
You currently increment an instance property and set it to the static property.
I suspect you want the opposite.
You could use a static field numberOfInvoices in your class, and increment it in the constructor.
Then you could have a static getter for the field.
numberOfInvoices will always be 0 when a new object is created. So, everytime you increment it and assign it to invoiceNumber, invoiceNumber gets the value 1. Instead, why dont you directly increment invoiceNumber .
use
private static int numberOfInvoices = 0;
Reason:
Static variables are related to class while nonstatic variables are related to object. As in this case you are storing the count of the object of the class so this is related to class. Thus you have to store it as static variable ( also called class variable)
For more details see here
You should declare your numberOfInvoices member as a static member :
private static int numberOfInvoices = 0;
This way all Invoice instance will share this member. If you don't declare it each Invoice instance will have their own value.
I have been experimenting with Classes in Java over the last few days, learning about them from "TheNewBoston" on youtube and from the java docs.
I have created the following scenario and seek your guys' (girls too) professional criticism and in depth knowledge regarding a few questions I have.
There are two classes, person and person_financial, a base class and sub class respectively.
person class:
public class person {
private String name;
private String sex;
private int age;
private double height;
private double weight;
private double intelligence;
// person constructor arguments order: name, height, weight, age, sex, intelligence
public person(){
this("noname",0,0,0,"undefined",5);
}
public person(String n){
this(n,0,0,0,"undefined",5);
}
public person(String n, double h){
this(n,h,0,0,"undefined",5);
}
public person(String n, double h, double w){
this(n,h,w,0,"undefined",5);
}
public person(String n, double h, double w, int a){
this(n,h,w,a,"undefined",5);
}
public person(String n, double h, double w, int a, String s){
this(n, h, w, a, filterSex(s), 5);
}
public person(String n, double h, double w, int a, String s, double i){
name = n;
height = h;
weight = w;
age = a;
sex = filterSex(s);
intelligence = i;
}
public void setName(String n){
name = n;
}
public void setHeight(double h){
height = h;
}
public void setWeight(double w){
weight = w;
}
public void setAge(int a){
age = a;
}
public void setSex(String s){
sex = filterSex(s);
}
public void setIntel(double i){
intelligence = i;
}
public String getName(){
return name;
}
public double getHeight(){
return height;
}
public double getWeight(){
return weight;
}
public int getAge(){
return age;
}
public String getSex(){
return sex;
}
public double getIntel(){
return intelligence;
}
public String getInfo(){
return String.format("Name: %s,\nSex: %s,\nAge: %d,\nIntelligence: %.2f,"
+ "\nHeight: %.2f,\nWeight: %.2f\n", name, sex, age,
intelligence, height, weight);
}
private static String filterSex(String s){
return ((s.equalsIgnoreCase("male") ||
s.equalsIgnoreCase("female")) ? s : "undefined");
}
}
person_financial class:
public class person_financial extends person {
private double monies = 0;
public void definePerson(String n, int a, String s, double i, double h, double w){
setName(n);
setAge(a);
setSex(s);
setIntel(i);
setHeight(h);
setWeight(w);
}
public person_financial() {
this(0);
}
public person_financial(double m) {
monies = m;
}
public void depositMonies(double m) {
monies += m;
}
public void withdrawlMonies(double m) {
if (m <= monies) {
monies -= m;
}
}
public double getBalance() {
return monies;
}
}
and then in the main class I have this:
public class Main {
public static void main(String[] args) {
person p1 = new person("I have no Name", 180, 72, 38, "Alien", 7.2);
System.out.println(p1.getName());
person_financial pf1 = new person_financial(100.00);
pf1.depositMonies(50.02);
System.out.printf("%s has %.2f monies.\n", pf1.getName(), pf1.getBalance());
pf1.definePerson("some_name", 42, "male", 10, 180, 72);
System.out.println(pf1.getInfo());
}
}
in the person_financial class, I have made a method called "definePerson()" which I use to define all the characteristics that would otherwise have been defined from the 'person()' constructor from the 'person' class. I'm sure there is a more professional way for assigning values to variables in a base class from a sub class, I just dont know of any...
Also, is there any way to call the constructor from the "person" class to define characteristics for 'pf1'? rather than having to, for example, manually set each attribute, i.e. pf1.setName("something"); , or pf1.setAge(1000000); etc... or have a method do it for me, as in 'definePerson()'.
Any help is much appreciated,
Thanks =).
You use the super() call to call the constructor of the parent class. It has to be the first call in the constructor of the derived class, but you call it (and pass in arguments) like any other function and it will call the constructor that way.
It's common to declare a class 'abstract' to prevent creation of generic objects - based on your usage-code at the bottom you seem not to want that and that's fine. Just remember that you can declare declare a class abstract.
The best way to use class hierarchy is to ensure that (buzzword alert) any class in a useful hierarchy should be declarable as anythin in the hierarchy (i.e. you should be able to access any methods in your concrete object from the base-class (person in this case).
Your financial_person object extends person, but the ideal is to have a class that you can declare at a high level and call methods polymorphically. Consider for a minute that all people are able to draw and deposit money (different from your classes, but bear with me for a minute).
drawMoney method would exist in person, but be marked abstract - forcing the subclasses financial_person and regular_person to implement draw_money, deposit_money etc.
each class would have an implementation that suits their reality (financial person would have access to all kinds of special accounts, discounts etc., and regular_person would have a simpler set of - but still the same external behavior).
Then you could declare like this:
Person finPerson = new FinancialPerson(... etc.);
Person regPerson = new RegularPerson(....etc);
note now that you are able to do this code below:
finPerson.drawCash(12300.0);
regperson.drawCase(100.0);
The identical behavior.
You could have a List of thousands of people, and would not have to do if-then-else or switch statements to execute the finer-tuned behaviors of each.
The acid-test for class-hierarchy is this: "my (sub-class) really 'a kind of' (superclass)?"
In other words, "does my subclass have behaviors of the superclass?"
If not, you should think carefully about class hierarchy. There's a buzzword for this : Liskov Substitution Principle, and I cannot do a better job of this than Robert. C. Martin - one of the software-design gurus:
http://www.objectmentor.com/resources/articles/lsp.pdf
In this article he shows what happens when you have inadvisable hierarchy, using the "a square is a kind-of rectangle" example.
Google "template method pattern" for a summary of another aspect of effectively using inheritance. You will see that it is much more powerful than the simple inheritance that most people dismiss it as being.
Also remember that no single pattern is a silver-bullet for everything. Some people will call class-hierarchy evil and tell you to use interfaces only; others will say the reverse. There are choices to make, and sometimes they will not be obvious.
There are many pitfalls, and missing LSP is just one of them. Others are (examples only) overriding concrete methods, having concrete classes not marked final, enabling mutability of "identifying" fields (eg fields used in equals/hashcode, etc.) Imagine if "customer" objects at bank allowed resetting of first-name, or account-number at runtime, once these fields were already set).
My answer is more generally related to OO design, inheritance etc. than specific coding questions - hope it's of some use to you.