I create a method that casts an aging spell upon people and decreses their age by two:
public class Wizard {
void agingSpell (Person x) {
x = new Person(x.age);
x.age -=2;
}
}
Here's the class describing those people:
public class Person {
int age;
int weight = 90;
String name = Max;
Person (int x){
this.age = x;
}
}
I create an instance of Person and Wizard:
Person max = new Person(26);
Wizard albus = new Wizard();
Then, I call the method agingSpell and source max as its argument:
albus.agingSpell(Person max);
Then, as I see it, the reference value inside max is assigned to x inside the method:
Person x = max;
Now we have one more reference to the created object. Next, a new object is created and (again, I might be wrong), is saved inside the x:
x = new Person(x.age)
I understand the old object to be substituted by the new one, so there has to be no trace of the old one inside the method. BUT, if I compile the code the age of the new object would also be 26 . Furthermor, I can easily access all the other fields of the older object (which was supposed to be unaccessible the moment we assigned his x reference to another object).
I know I'm definitely missing something. Could you, please, help me figure it out?
Here's the executing portion of the code:
public class Wizard {
}
public static void main (String [] args){
Wizard albus = new Wizard();
Person max = new Person(26);
albus.agingSpell(max);
System.out.println(max.age);
}
}
You reassign x in the spell method, so it points to the new person, then you change that new person's age, and then you throw that person away. So the net result is nothing changed. It's the same as doing this:
void agingSpell(Person p) {
Person throwaway = new Person(p.age);
throwaway.age -= 2;
// when this method returns, "throwaway" literally gets thrown away.
}
A better question is "why are you generating a new person at all, if the intent is to decrease a person's age?". Have the spell directly update the person you pass in:
class Wizard {
final int DEFAULT_AGE_DECREASE = 2;
...
void agingSpell(Person p) {
this.agePerson(p, DEFAULT_AGE_DECREASE);
}
void agingSpell(Person p, int years) {
// let's keep a person's age a protected field
p.setAge(p.age - years);
// and you'll probably need logic for age hitting/dropping below zero
}
...
}
Define agingSpell as follows:
void agingSpell(Person x) {
x.age -= 2;
}
-OR-
Return the new object you are creating. Note that the scope of the new object you are creating inside agingSpell is limited to this method only i.e. as soon as the control comes out this function, the new object will cease to exist.
class Wizard {
Person agingSpell(Person x) {
x = new Person(x.age);
x.age -= 2;
return x;
}
}
class Person {
int age;
int weight = 90;
String name;
Person(int x) {
this.age = x;
}
}
public class Main {
public static void main(String[] args) {
Wizard albus = new Wizard();
Person max = new Person(26);
System.out.println(albus.agingSpell(max).age);
}
}
Related
Quite new to this so I hope I have the terminology in the title right.
I am trying to figure out how to create an instance method that will do the following:
--An ID number is returned.
--As each object is created from the class constructor(instantiated?), a unique integer ID number is assigned to it. The first ID number is 1, and as new objects are instantiated, successive numbers will be assigned.
I am able to find examples of class/static methods that do the above however I am unable to figure out how to do this with an instance method. My attempt is below:
class Coordinates
{
private int iD = 0;
private float xCoordinate;
private float yCoordinate;
public Coordinates()
{
//Asks for input and assigns it to the two variables below
Scanner keyboard = new Scanner(System.in);
System.out.println("Please enter the X Coordinate followed by the return key");
xCoordinate = keyboard.nextDouble();
System.out.println("Please enter the Y Coordinate followed by the return key");
yCoordinate = keyboard.nextDouble();
iD++;
}
public getiD()
{
return iD;
}
}
My main method is as follows:
public class Machine
{
public static void main(String[] args)
{
Coordinates c1 = new Coordiantes();
Coordinates c2 = new Coordiantes();
Coordinates c3 = new Coordiantes();
System.out.println("ID: " + c1.getID());
System.out.println("ID: " + c2.getID());
System.out.println("ID: " + c3.getID());
}
}
Please note I have not included my entire code for the sake of simplicity and easiness to follow. I hope I have added enough.
I also don't want to use java.util.UUID.
The problem right now is that your 'id' is an instance variable, meaning it belong to the objects you create.
Think of it that every time you create an object a new and fresh copy of your instance variable is made.
So every time you create an object the id is first set to 0, then post incremented once (thus all objects have an id=0).
If you want to create a variable that, say, automatically counts all objects you have created in a class or has the id, you need to make a class variable.
These variable belong to all the objects you create from a class and the keyword used for that is 'static'.
Note: I have used a static variable BUT not a static method. If you don't want to use static at all, it is a different question
class Coordinates
{
private static int count = 0;
private int id=0;
private float xCoordinate;
private float yCoordinate;
public Coordinates()
{
//Asks for input and assigns it to the two variables below
Scanner keyboard = new Scanner(System.in);
System.out.println("Please enter the X Coordinate followed by the return key");
xCoordinate = keyboard.nextDouble();
System.out.println("Please enter the Y Coordinate followed by the return key");
yCoordinate = keyboard.nextDouble();
id=count++;
}
public getiD()
{
return iD;
}
}
A simple change of keyword will make your program correct. You dont have to do too much complicated stuff.
It is difficult to grasp the concept of class and objects, static and instance variables at first. Let me know if you'd like more explanation :)
In the context of your current code, the simplest thing to to do is as below:
import java.util.concurrent.atomic.AtomicInteger;
public class Coordinates {
//static id generator shared among all instances of Coordinates
private static final AtomicInteger idGenerator = new AtomicInteger(1000);
private final Integer id;
public Coordinates() {
//assign unique id to an instance variable
id = idGenerator.getAndIncrement();
}
public int getId() {
//return instance variable
return id;
}
}
Test
public class Test {
public static void main(String[] args) {
for(int i = 0; i < 10; ++ i){
System.out.println(new CoordinatePoint().getId());
}
}
}
Output
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
Maintaining an ID sequence is a separate responsibility from the rest of what your object does, and doesn't belong to any one instance of the Coordinates class, so it belongs in a different object. Make a separate object to maintain the sequence and hand out numbers, something like
public class MySequence {
private AtomicLong currentValue = new AtomicLong(0L);
public long getNextValue() {
return currentValue.getAndIncrement();
}
}
then use that sequence to initialize your objects:
new CoordinatePair(mySequence.getNextValue(), x, y);
By the way keeping user input separate from the model makes things simpler, you may want to instantiate your Coordinates class in cases where the input doesn't come from the user. Console input doesn't go in a constructor. You might have a Coordinate class like
public CoordinatePoint {
private long id;
private float x;
private float y;
public CoordinatePoint(long id, float x, float y) {
this.id = id;
this.x = x;
this.y = y;
}
public String toString() {
return "id=" + id + ", (" + x + ", " + y + ")";
}
}
and a main method like
public class Example {
public static void main(String ... args) {
MySequence seq = new MySequence();
Scanner keyboard = new Scanner(System.in);
System.out.println("Please enter the X Coordinate followed by the return key");
float xCoordinate = keyboard.nextDouble();
System.out.println("Please enter the Y Coordinate followed by the return key");
float yCoordinate = keyboard.nextDouble();
CoordinatePoint c1 = new CoordinatePoint(seq.getNextValue(), xCoordinate, yCoordinate);
System.out.println(c1.toString());
}
}
You can either make that ID static, or you could just make a Parent class called "Coordinate" (with that ID again being static) with "Point" children, and increment the ID in the constructor of each "Point" object.
Static would seem like the way to go.
I've looked all over the internet, but I can't figure out what I'm doing wrong. I'm trying my hand at using private variables from another class using get/set methods. Something's going wrong, but I can't figure it out.
public class Character
{
private int atk = 0;
private int def = 0;
private int spd = 0;
public void setStat(String stat, int n)
{
stat = stat.toLowerCase();
if(stat.equals("def") || stat.equals("defence") || stat.equals("defense"))
{
def = n;
}
if(stat.equals("atk") || stat.equals("attack"))
{
atk = n;
}
if(stat.equals("spd") || stat.equals("speed"))
{
spd = n;
}
}
public int getStat(String stat)
{
stat = stat.toLowerCase();
int n = -1;
if(stat.equals("def") || stat.equals("defence") || stat.equals("defense"))
{
n = def;
}
if(stat.equals("atk") || stat.equals("attack"))
{
n = atk;
}
if(stat.equals("spd") || stat.equals("speed"))
{
n = spd;
}
return n;
}
public Character(int a, int d, int c)
{
atk = a;
def = d;
spd = c;
}
}
This is my first class, Character which will be used as the template for the object, complete with get/set methods.
public class newCharacters
{
Character person1 = new Character(2, 4, 3);
person1.getStat("atk");
}
This is my second class, which constructs a character object and then tries to get a variable. Problem is, whenever I compile, it says that the object method needs an identifier. Exact quote: <identifier> expected
I can't figure out what it means, or what I'm doing wrong? I made get/set methods for each class, created the object in both classes, even constructed and called the object method within the Character class. Same problem every time. Can someone help?
public class newCharacters
{
Character person1 = new Character(2, 4, 3);
person1.getStat("atk");
}
This should not be in a class. This does not mean anything. A class can have bunch of instance variables and methods.
Please study the basics well ;)
Put it in a main method inside the Character class
public static void main(String [] args) {
Character person1 = new Character(2, 4, 3);
person1.getStat("atk");
}
public class NewCharacters
{
public static void main(String[] args) {
Character person1 = new Character(2, 4, 3);
person1.getStat("atk");
}
}
A program starts a main method like above.
Inside a class, at the top level only fields and methods may be declared (and constructors and initializer blocks, and other classes).
I need an array to be public (accessible to other methods in the class) but the array needs an input value "T" to create it. How do I instantiate a "global" variable that requires user input?
My code is as follows:
public class PercolationStats {
**private double myarray[];**
public PercolationStats(int N, int T) {
**double myarray = new double[T];**
for (i=0;i<T;i++) {
Percolation percExperiment as new Percolation(N);
//do more stuff, make calls to percExperiment.publicmethods
myarray[i] = percExperiment.returnvalue;
}
}
public static void main(String[] args) {
int N = StdIn.readInt();
int T = StdIn.readInt();
PercolationStats percstats = new PercolationStats(N, T);
//do more stuff, including finding mean and stddev of myarray[]
StdOut.println(output);
}
Another example in pseudocode:
class PercolationStats {
Constructor(N, T) {
new Percolation(N) //x"T" times
}
Main {
new PercolationStats(N, T) //call constructor
}
}
class Percolation {
Constructor(N) {
**new WQF(N)** //another class that creates an array with size dependent on N
}
Main {
**make calls to WQF.publicmethods**
}
}
In the second example, it seems to me that I need to have the new instance of class WQF made in the constructor of the Percolation in order to accept the parameter N. However, WQF would not be accessible to the Main method of Percolation.
Help!
Don't include the type declaration in your constructor. You are creating a local variable that masks the field. It should look like this:
public class PercolationStats {
public double myarray[];
public PercolationStats(int n, int y) {
myarray = new double[t];
for (i=0; i<t; i++) {
Percolation percExperiment = new Percolation(n);
//do more stuff, make calls to percExperiment.publicmethods
myarray[i] = percExperiment.returnvalue;
}
}
public static void main(String[] args) {
int n = StdIn.readInt();
int t = StdIn.readInt();
PercolationStats percstats = new PercolationStats(n, t);
//do more stuff, including finding mean and stddev of myarray[]
StdOut.println(output);
}
}
There's certainly no problem using a variable as the length when creating a new array.
Tedd Hopp's answer corrects the bug in your code.
I'd just like to point out that myarray is NOT a global variable.
Java doesn't have global variables,
the closest it has is static variables, and
myarray isn't one of those either. It is an instance variable, as you have declared it.
(And an instance variable is the right way to implement this ... IMO)
I have a problem
I have some classes of objects, they are called "cat" "dog" etc..
Within these classes I have assigned each cat and dog object their own integer energy level (so when they "move" through a 2dimensional array they loose and gain energy).
I reference it by saying this.energylevel.
Because "energylevel" it is specific to each object I cannot make it static.
how can I let the "dog class" see the energy level of the cat objects that is stored non statically within the "cat class"?
and I cannot instantiate Cat c = new Cat(); within the dog class it is already done within the main method.
This is all part of a massive project so forgive me if I have not explained it clearly enough
You can add a static method inside the Cat object that will return the non-static variable based on the Cat's ID. You'll need to keep a list of Cats in a static map inside the Cat object.
private static HashMap<String,Cat> cats = new HashMap<String,Cat>();
...
public static int getEnergy(String catId) {
Cat myCat = cats.get(catId);
return myCat.getEnergy();
}
public int getEnergy() {
return this.energy()
}
Alternatively as requested, if you want to search by X,Y:
private static ArrayList<Cat> cats = new ArrayList<Cat>();
private int energy = 100;
private int x = 0;
private int y = 0;
...
public static int getEnergy(int x, int y) {
//Energy of -1 being the error (not found) state.
int energy = -1;
for(Cat cat : cats) {
if(cat.getX() == x && cat.getY() == y) {
energy = cat.getEnergy();
}
}
return energy;
}
public int getEnergy() {
return this.energy()
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
Can we swap two numbers in Java using pass by reference or call by reference?
Recently when I came across swapping two numbers in Java I wrote
class Swap{
int a,b;
void getNos(){
System.out.println("input nos");
a = scan.nextInt();
b = scan.nextInt(); // where scan is object of scanner class
}
void swap(){
int temp;
temp = this.a;
this.a = thisb;
this.b = this.a;
}
}
In the main method I call the above mentioned methods and take two integers a,b and then using the second method I swap the two numbers, but relative to the object itself....
Does this program or logic come under pass by reference?
And is this correct solution?
Yes and no. Java never passes by reference, and your way is one workaround. But yet you create a class just to swap two integers. Instead, you can create an int wrapper and use pass it, this way the integer may be separated when not needed:
public class IntWrapper {
public int value;
}
// Somewhere else
public void swap(IntWrapper a, IntWrapper b) {
int temp = a.value;
a.value = b.value;
b.value = temp;
}
As the comments show, I might not have been clear enough, so let me elaborate a little bit.
What does passing by reference mean? It means that when you pass an argument to the method, you can change the original argument itself inside this method.
For example, if Java was pass-by-reference, the following code will print out x = 1:
public class Example {
private static void bar(int y) {
y = 10;
}
public static void main(String[] args) {
int x = 1;
bar(x);
System.out.println("x = " + x);
}
}
But as we know, it prints 0, since the argument passed to the bar method is a copy of the original x, and any assignment to it will not affect x.
The same goes with the following C program:
static void bar(int y) {
y = 1;
}
int main(int argc, char * argc[]) {
int x = 0;
bar(x);
printf("x = %d\n", x);
}
If we want to change the value of x, we will have to pass its reference (address), as in the following example, but even in this case, we will not pass the actual reference, but a copy of the reference, and by dereferencing it we will be able to modify the actual value of x. Yet, direct assignment to the reference will no change the reference itself, as it is passed by value:
static void bar(int &y) {
*y = 1;
y = NULL;
}
int main(int argc, char * argc[]) {
int x = 0;
int * px = &x;
bar(px);
printf("x = %d\n", x); // now it will print 1
printf("px = %p\n", px); // this will still print the original address of x, not 0
}
So passing the address of the variable instead of the variable itself solves the problem in C. But in Java, since we don't have addresses, we need to wrap the variable when we want to assign to it. In case of only modifying the object, we don't have that problem, but again, if we want to assign to it, we have to wrap it, as in the first example. This apply not only for primitive, but also for objects, including those wrapper objects I've just mentioned. I will show it in one (longer) example:
public class Wrapper {
int value;
private static changeValue(Wrapper w) {
w.value = 1;
}
private static assignWrapper(Wrapper w) {
w = new Wrapper();
w.value = 2;
}
public static void main(String[] args) {
Wrapper wrapper = new Wrapper();
wrapper.value = 0;
changeValue(wrapper);
System.out.println("wrapper.value = " + wrapper.value);
// will print wrapper.value = 1
assignWrapper(w);
System.out.println("wrapper.value = " + wrapper.value);
// will still print wrapper.value = 1
}
}
Well, that's it, I hope I made it clear (and didn't make too much mistakes)
import java.util.*;
public class Main
{
int a,b;
void swap(Main ob)
{
int tmp=ob.a;
ob.a=ob.b;
ob.b=tmp;
}
void get()
{
Scanner sc=new Scanner(System.in);
System.out.println("Enter a and b: ");
a=sc.nextInt();
b=sc.nextInt();
}
public static void main(String[] args) {
Main ob=new Main();
ob.get();
ob.swap(ob);
System.out.println(ob.a+" "+ob.b);
}}