I am really new to java and just trying to get my head around how everything works. I have a method like this:
public assignmentmarks(String name, int mark1, int mark2, int mark3)
{
}
and the question asks to create the constructor that uses all the fields (courseName, assignment1, assignment2, assignment3)
This is what I have tried
import java.util.Scanner;
public class assignmentmarks {
private String courseName;
private int assignment1;
private int assignment2;
private int assignment3;
int average;
int mark;
Scanner scanner = new Scanner(System.in);
public void AssignmentMarks(String name, int mark1, int mark2, int mark3)
{
assignment1 = mark1;
assignment2 = mark2;
assignment3 = mark3;
courseName = name;
AssignmentMarks assignmentMarks = new AssignmentMarks(mark1, mark2, mark3, name);
}
I have a method like this:
public assignmentmarks(String name, int mark1, int mark2, int mark3)
{
}
That is not a method. It is a constructor!!
A constructor is a "method-like thing" that has no return type, and the same name as the enclosing class.
All you need to do is add some statements that will assign the parameters to the fields of your class.
Having said that, assignmentmarks is a bad choice for a class name. The Java style rules say that a class name should:
Start with a capital letter
Use camel case; i.e. each embedded word should start with a capital letter.
Thus ... AssignmentMarks would be a better name.
(Yes ... this kind of stuff really does matter. Conforming to standard style makes your code readable, which makes it more maintainable, which will save you and your future colleagues time and hair-tearing.)
Also note the names (identifiers) in Java are case sensitive. So you need to be consistent. Don't use assignmentmarks in one place and AssignmentMarks in another. That is likely to lead to compilation errors ... or worse.
There are few ways to go around that.
Firstly the thing you aimed to create is called an "All-arguments-constructor" meaning you want to have a declared way to create an instance(entity) of a class and while doing so you want to have all properties(fields\parameters) of it filled with values specified on the call of the said constructor.
There is a hack way to do so using lombok and just annotating your class with #AllArgsConstructor, but I recommend you continue learning how those things are made by hand and then revisit mentioned syntaxis sugar later.
With that being said you want to create something like a method that neither has return type nor "void" written in its signature, then refers to every property(field\parameter) of an instance trough this (which literally means "I want to work with this particular entity") and then assigns them values that you passed through constructor.
In your case, it would look like that:
// We have passed all the values that we need trough constructor.
public AssignmentMarks(String name, int ass1, int ass2, int ass3, int mark, int average) {
// Now we assign them to the properties of an instance we creating.
// "courseName" of the created instance becomes "name" we passed.
this.courseName = name;
// "assignment1" of the created instance becomes "ass1" we passed
this.assignment1 = ass1;
// I bet you are getting the hang of it now.
this.assignment2 = ass2;
// And so on.
this.assignment3 = ass3;
// And so forth.
this.mark = mark;
// Until you have assigned values to all properties you want to assign in the constructor.
this.average = average;
}
Now that you have this constructor you could just simply create a new instance like so:
AssignmentMarks instance = new AssignmentMarks("programming", 1, 2, 3, 17, 20);
Where we also declared all the values we want to be assigned.
This how you could have done it with lombok:
//This is an entire class
#AllArgsConstructor
public class AssignmentMarks {
private String courseName;
private int assignment1;
private int assignment2;
private int assignment3;
int average;
int mark;
}
Now it already has "All argument constructor" because of #AllArgsConstructor annotation.
P.S. I double the previous writer on naming your class in CamelCase it is important.
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'm new to Java, so forgive me if it's a stupid question. I tried to find a clear answer on this forum but with no joy.
I know what 'this' is. It know it refers to an actual instance and helps narrow the context when targeting a variable, but I found that it is possible to execute the code without any issues despite not using 'this' phrase. Turns out it depends on how you name your parameters when you declare methods. As you can see below, code returns 'null' if my parameter is named the same as the state I'm initialising/modifying.
This works only in the class where the variables are declared. You'd still have to use 'this' in any sub-class, if it tried to access/modify a variable declared in its parent class.
Now, would this be considered incorrect and should it be avoided even though it seems to be working fine?
Thanks!
class Student {
protected String name;
protected int age;
protected String course;
public Student(String passName, int passAge, String course) {
name = passName;
age = passAge;
course = course; // here my parameter is named the same as the state and it will return 'null' unless we use 'this'
}
public void update(String newName, int newAge, String newCourse) {
name = newName;
age = newAge;
course = newCourse; // here I set the name of my parameter to be different and it works
}
public void display() {
System.out.println("Name: " + name + "\n Age: " + age + "\n Course: " + course + "\n");
}
public static void main(String[] args) {
Student s1 = new Student("John", 20, "Java 101");
s1.display();
s1.update("Johnny", 21, "Java 101");
s1.display();
}
}
Output:
Name: John
Age: 20
Course: null
Name: Johnny
Age: 21
Course: Java 101
As you noticed, if you give an instance variable the same name as a constructor argument, the assignment such as
course = course;
doesn't initialize the instance variable, since the constructor's argument course, which is a local variable, hides the instance variable of the same name. You are assigning the local variable to itself.
Hence the instance variable remains null.
You'll have to write
this.course = course;
in order for the assignment to work.
If, on the other hand, the name of the instance variable is different from the constructor argument's name, you can assign the constructor's argument to the instance variable without using the this prefix.
both
course = newCourse;
and
this.course = newCourse;
would work fine.
Note that using the this prefix even when it's not mandatory has an advantage of spotting bugs.
For example, if you wrote by mistake
newCourse = course;
the compiler will not complain, but your course instance variable won't be initialized.
On the other hand, if you wrote by mistake
this.newCourse = course;
the compiler will give a compilation error, since newCourse is not an instance variable.
I think you should read official documantation about "this" keyword.
Using this with a Field The most common reason for using the this keyword is because a field is shadowed by a method or constructor
parameter.
For example, the Point class was written like this
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int a, int b) {
x = a;
y = b;
}
}
but it could have been written like this:
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Each argument to the constructor shadows one of the object's fields —
inside the constructor x is a local copy of the constructor's first
argument. To refer to the Point field x, the constructor must use
this.x.
About you question:
Now, would this be considered incorrect and should it be avoided even
though it seems to be working fine?
It is depends for code style do yoy have in your projects or teams. Technically, both ways are possible and correct, using name = newName is shorter, and using this.name = name is more safe to avoid mistakes.
It's the variable name that counts. Java always uses the variable in the closest scope available, so if you use a parameter with the same name, it will use the parameter. To avoid that, you need to qualify the field with this.
Here (irrelevant code removed):
public Student(String course) {
course = course;
}
you assign the value of course to the parameter course, so the field course remains unchanged. For instance, if you do this:
public Student(final String course) {
course = course;
}
it will not compile because the final keyword means you're not allowed to assign a new value to the variable (in this case, parameter course).
So you need to use this to assign to the field.
public Student(final String course) {
this.course = course;
}
It's never "incorrect" to use this, but you might consider it good practice to not name parameters the same as fields anyway (and there are warnings to activate in IDEs if you do, to prevent exactly that).
In my assignment, I'm given a Food class like this:
class Food {
private String name; // name of food
private int calPerServing; // calories per serving
// must be >= 0
// min storage temperature // must be >= 0.
// max storage temperature // must be <= 100.
private float minTemp; private float maxTemp;
int getCalories() {
return calPerServing;
}
}
And I'm having trouble with this part of the assignment:
Write a constructor method for the Food class, to set the default name to "Pie", the default calPerServing to 500, the default minTemp to 25, and the default maxTemp to 75.
How do I set default values for name, calPerServing, etc.?
(I'm surprised to get to page three of search results without finding a simple version of this question to point to.)
You have two choices for setting the default value of an instance variable (sometimes called an "instance field"):
Using an initializer on the declaration.
Using an assignment in a constructor.
Say I have a class Example and an instance variable answer whose default should be 42. I can either:
// Example of #1 (initializer)
class Example {
private int answer = 42;
// ...
}
or
// Example of #2 (assignment within constructor)
class Example {
private int answer;
Example() {
this.answer = 42;
}
}
Initializers (#1) are processed during construction just before any other logic in your constructor (but after calling the superclass constructor).
Which you use depends on the class and, to an extent, personal style. If the class is going to have multiple constructors but I want answer to default to 42 regardless of which constructor is used, using initialization makes sense because then I just put it in one place instead of putting it in every constructor. If the default for answer will vary depending on which constructor is used, or depending on a parameter the constructor(s) receives/receive, setting it in the constructor makes sense.
In your specific case, the assignment tells you to use a constructor.
If you are setting default values, you simply assign a value when you declare the variable like so:
private String name = "Pie";
private int calPerServing = 500;
and so it. If you want to overwrite those variables, you can. Alternatively, you can do it in the constructor like so:
class Food {
private String name; // name of food
private int calPerServing; //
public Food(){
this.name = "Pie";
this.calPerServing = 500;
}
}
Sorry if the title was worded incorrectly, please change it if it's not quite what I describe here.
So I am creating a program to simulate some fictitious creatures, and I need many objects that all store different statistics about each individual creature with values that can all be checked at the same time. What would be the correct way to go about doing this?
For reference, here is the code that I have right now.
public class Model {
static int mfood;
static int mdefense;
static int mattack;
static int mhealth;
static int msize;
static int magg;
static boolean update = false;
public Model(int food, int meat, int defense, int attack, int health, int agg) {
mfood = food;
msize = size;
mdefense = defense;
mattack = attack;
mhealth = health;
magg = agg;
}
The problem is, of course, that I have variables that store the values that are put into the constructor that are changed each time the constructor is called. This works well if I have only one object running at a time, but I will have around a dozen, most likely. These values need to be called in other methods as well, such as
public void Attack() {
mhealth = (mhealth + mdefense) - mattack;
}
The mattack variable would be a different object from the mhealth and mdefense variables.
Thanks for any help I can get, I'm sure this is a simple fix, but I can't find the answer anywhere.
Your variables are static, meaning they exist at the class level, not the individual object level. This means no matter how many objects you create (new up), they all share the same variables. Remove the static keywords and each object will have it's own copy of the variables.
I have a task to operate on complex number. Each number consists of double r = real part, double i = imaginary part and String name. Name must be set within constructor, so I've created int counter, then I'm sending its value to setNextName function and get name letter back. Unfortunately incrementing this 'counter' value works only within costructor and then it is once again set to 0. How to deal with that?Some constant value? And second problem is that I also need to provide setNextNames(char c) function that will change the counter current value.
The code :
public class Imaginary {
private double re;
private double im;
private String real;
private String imaginary;
private String name;
private int counter=0;
public Imaginary(double r, double u){
re = r;
im = u;
name = this.setNextName(counter);
counter++;
}
public static String setNextName(int c){
String nameTab[] = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N",
"O","P","Q","R","S","T","U","W","V","X","Y","Z"};
String setName = nameTab[c];
System.out.println("c: "+c);
return setName;
}
public static String setNextName(char c){
//
//don't know how to deal with this part
//
}
It's hard to tell what you're doing, but I suspect this will solve your immediate problem:
private static int counter = 0;
You should make counter static.
You should also make nameTab a private static field, then in setNextName(), you can iterate through it to find the name corresponding to the given character, and get its index. (in the plain ASCII world, of course one could simply calculate the index by subtracting the numeric value of 'A' from the given character, but I am not quite sure how it would work out with Java, in Unicode, with crazy inputs - iteration is on the safe side.)
In OO languages there are typically two types of variables that go into a class:
instance variables that are unique to each instance
class variables that are shared by all instances of the class
Given a class like:
public class Person
{
// class variable
private static int numberOfEyes;
// instance variable
private String name;
// other code goes here
}
If you were to do something like:
Person a = new Person("Jane Doe");
Person b = new Person("John Doe");
and then do something like:
a.setName("Jane Foe");
the name for Person "a" would change, but the one for Person "b" would stay the same.
If you woke up one morning and decided you wanted 3 eyes:
Person.setNumberOfEyes(3);
then Person "a" and Person "b" and every other Person instance out there would suddenly have 3 eyes as well.
You want to put "static" in your counter declaration.
is your code being used by multiple threads than i would suggest that making counter static won't solve ur problem.
you need to take extra care by implementing thread synchronization use lock keyword as shown below.
private static readonly obj = new Object();
private static int counter =0;
public Imaginary(double r, double u)
{
re = r;
im = u;
lock(obj)
{
name = this.setNextName(counter);
counter++;
}
}
this will ensure thread safety also while incrementing your counter (there are another ways also to provide thread security but this one is having least code).
Because the field counter is not static, every object has its own counter.