Consider this:
public class Test {
public static int numberOfInstances = 0;
public int myInstanceID;
public String myInstanceName;
The static variable doesn't need to be called within an instance, it's available everywhere like this:
Test.numberOfInstances
When creating an instance, I only do this into my constructor:
public Test(int id, String name) {
myInstanceID = id;
myInstanceName = name;
numberOfInstances += 1;
}
I've recently discovered the this keyword and have noted some of its uses:
public Test() {
this(numberOfInstances + 1, "newInstance");
numberOfInstances += 1;
}
From what I've noticed, the this keyword allows you to call another one of the class' constructors. It also allows you to do this:
public Test(int x, int y) {
this.x = x;
this.y = y;
}
With java, I highly disagree with this style; same variable names, and I don't see the point of using this, especially after looking at the docs example. I look at this:
public Test(int a, int b) {
x = a;
y = b;
However, the use of the this keyword isn't necessary; In my code, I have a variables in my class (e.g. xCoordinate) where I don't use the this keyword (it's not static).
What I've been struggling to understand is what the difference is between non-static variables and this variables. Is there a difference? In one of my classes (the Paddle for Pong), I have this:
public class Pong {
public int xCoordinate;
public int yCoordinate;
and so on...
I never use the this keyword anywhere, and the data is stored within it's own instance.
Bottom line, my question is what is the difference between non-static variables and this.variables. Is it a standard coding practice? Why would I ever you the this keyword on non-static variables?
I think you may have almost answered your own question. You provided the function
public Test(int x, int y) {
this.x = x;
this.y = y;
}
However, what do you think would happen if you wrote it this way instead?
public Test(int x, int y) {
x = x;
y = y;
}
Noticed that I removed the this in the second function. Therefore, x and y would just be referring to the local x and y variables. this allows you to specify that you actually want to use the non-static class variables x and y.
If, as is typical, the parameter variable names of a constructor (say x) are the same as fields of the class, then the field names are shadowed by the parameters passed.
this is used in this case to disambiguate: this.x denotes the field x. It makes perfect sense. this means "reference to the current instance".
So, statements like this.x = x; are quite common.
If you still continue to dislike the Java style, and you adopt m_x-style notation for class fields, then you can write m_x = x; in your constructor. As you rightly point out, this is then not required.
this is also used as the notation for delegating constructors, as you point out.
The "this" keyword allows you to difference between method and instance variables:
public class Point {
private int x;
private int y;
public void add(int x, int y) {
this.x += x;
this.y += y;
}
}
There is no this variables. It's just used to tell the compiler that the variable you want to change is the declared field and not the local variable, in case they have the same name.
For the constructor part, this is just a shortcut for classes which have multiple constructors. You can write the code once and just call that from the alternative constructors.
There is also a similiarly used keyword super, which allows you to call methods and constructors of the superclass:
public SomeClass(int x) {
super(x);
super.someMethod(); // even if we would have overridden someMethod(),
// this will call the one from the superclass
}
Here's one instance where you would need the 'this' keyword:
public class Pong {
public int xCoordinate;
public int yCoordinate;
public Pong (int xCoordinate, int yCoordinate) {
this.xCoordinate = xCoordinate;
this.yCoordinate = yCoordinate;
}
}
Related
Suppose I have class with 2 fields: x and y, of type double. Is it possible to define 2 constructors so constructor1 will create object setting its x property to what parameter in constructor tell and y to default and constructor2 vice versa?
public class Test {
private int x;
private int y;
public Test(int x) {
this.x = x;
}
public Test(int y) {
this.y = y;
}
}
I'm trying something like that and I know that it wont work because of overloading rules
No, you can't do that. Typically you'd do something like:
private Test(int x, int y) {
this.x = x;
this.y = y;
}
public static Test fromX(int x) {
return new Test(x, 0);
}
public static Test fromY(int y) {
return new Test(0, y);
}
You might want to consider that pattern (public static factory methods which in turn call private constructors) even when you don't have overloading issues - it makes it clear what the meaning of the value you're passing is meant to be.
No, You cannot have two methods or constructors with the same signature. What you can do is have named static factories.
public class Test {
private int x;
private int y;
private Test(int x, int y) {
this.x = x;
this.y = y;
}
public static Test x(int x) { return new Test(x, 0); }
public static Test y(int y) { return new Test(0, y); }
}
Test x1 = Test.x(1);
Test y2 = Test.y(2);
No, x and y have identical types, so both constructors would have the same type signature and the method resolution is based on parameter type, not name; the compiler has no way of differentiation.
The compiler looks for "Test.Test(int)" regardless of what the name of the parameter is.
The language would need additional feature added, such as named parameters, to do what you want.
If Java ever gets a syntax like C# for property initialization, you'll be able to use that idiom, using a default no-args constructor.
Besides the alternatives of using explicit factory methods, you could pass in a HashMap for your parameters.
public Test(HashMap<string,int> args) {
if(args.containsKey("x"))
x = args.get("x");
if(args.containsKey("y"))
y = args.get("y");
}
But static factory methods are cleaner for most cases. If you need much more, you may need to consider why you need such an idiom in the first place, and revise your class design.
If you run the below code snippet, you will get this output for the final variable X and Y.
X = 1 Y = 2 X = 4 Y = 5
Its obvious from the output, the final variables have been reassigned.
I am wondering, if it has violated the contract of Java Final variables. Any thoughts?
public class FinalVariablesTest {
private final int x;
private final int y;
public FinalVariablesTest() {
this.x = 1;
this.y = 2;
}
public FinalVariablesTest(int xValue, int yValue) {
this.x = xValue;
this.y = yValue;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public static void main(String...strings) {
FinalVariablesTest finalVariablesTest = new FinalVariablesTest();
System.out.println(" X = "+finalVariablesTest.getX() + " Y = "+finalVariablesTest.getY());
finalVariablesTest = new FinalVariablesTest(4,5);
System.out.println(" X = "+finalVariablesTest.getX() + " Y = "+finalVariablesTest.getY());
}
}
No, this is not a violation - There are two separate instances, and each has different final values bound to x and y.
You have changed the instance referenced by finalVariablesTest.
FinalVariablesTest class is not singleton, so you can create as many object as you want and different FinalVariablesTest Object would have different set of x and y final veriable, which you cannot change the value once created, so this is not a violation.
You have defined your variables as Final.
private final int x;
private final int y;
and you are assigning values to them in the constructor which is perfectly valid. Also you are creating two different instances of FinalVariablesTest having different values which again perfectly legal and correct.
However if you would have done something like
private static final int x;
private static final int y;
you cannot even initialize it in the constructor.Final fields don't get default values, they have to be explicitly initialized. A final variable can only be initialized once, either via an initializer or an assignment statement. If a final instance variable is not assigned a value - there will be a compiler error !
you have to initialize it while declaring
private static final int x = 0;
private static final int y = 0;
So lets say you say private static final int y; and then without creating any instance of the object you do System.out.println(FinalVariablesTest.x); that would be wrong.
Hence what you have done is perfectly valid and legal however with slight variation(making it static so variables now belong to Class rather than individual instances) you cannot do what you have experimented.
System.out.println(" X = "+finalVariablesTest.getX() + " Y = "+finalVariablesTest.getY()); prints X=1 Y=2 & X=4 Y=5 too because u creating an new object and assigning to already created object.
These are not exactly variables but rather (final) instance filed. Final instance field can be assigned exactly once, per the object they belong to. Your example creates two objects (you have two new FinalVariablesTest expressions) and for each such object the instance fields are assigned with different values.
To see what finality means, try to adding this method to your class:
public vod setX(int newValue) {
x = newValue;
}
This change will yield a compilation error due to setX trying to assign to a final field after it has already been assigned (in the constructor).
I had the following code on a test for a potential job recently.
class Point {
protected final int x, y;
private final String name;
Point(int x, int y) {
this.x = x;
this.y = y;
name = makeName();
}
protected String makeName() {
return "[" + x + "," + y + "]";
}
public final String toString() {
return name;
}
}
public class ColorPoint extends Point {
private final String color;
ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}
protected String makeName() {
return super.makeName() + ": " + color;
}
public static void main(String[] args) {
System.out.println(new ColorPoint(4, 2, "purple"));
}
}
The test asked what the programmer intended to have printed out, which was [4, 2]: purple. It also asked what actually prints out, which is [4: 2]: null. What I'd like to find out is why.
In the subclass ColorPoint when the constructor of the super class Point is called, the value to the variable color is yet to be assigned. Hence when makeName() method is called, color is actually null, hence the name variable becomes [4,2]:null, and thats what you see when you print.
Observe what happens when you create a new ColorPoint instance:
memory is allocated for a ColorPoint instance
x, y and name are set to their default values
the ColorPoint constructor is called
the ColorPoint constructor calls the Point constructor
the Point constructor assigns to x and y
the Point constructor calls the makeName method.
this.makeName resolves to ColorPoint.makeName
ColorPoint.makeName calls Point.makeName
Point.makeName observes x and y already set, and acts as desired
ColorPoint.makeName observes color to be null, and acts accordingly
the Point constructor assigns to name and returns
the ColorPoint constructor assigns to color and returns. Oops, too late.
The final keyword ensures a particular field or variable will be assigned to exactly once (the compiler does that; it's still possible to change via reflection). The compiler also ensures a local variable will not be read before it's been written to. There is no such provision of write before read for class fields.
That's why, as has been noted, you should never call methods that can be overriden from the constructor.
The reason is obvious in the code.
The ColorPoint makeName method is called from the constructor of Point class. At that point the private final variable color has not been initialized.
I was wondering what the best way of documenting this potential Point class is:
public class Point {
/* the X coordinate of this point */
private int x;
/* the Y coordinate of this point */
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
My concrete concern lies with the repetition between the x and y attributes and their respective getters and setters, as well with the constructor arguments.
It's not that I'm developing a public API or anything of the likes, it's no problem for me to have a general comment regarding some variable and then having the getter and setter have just the same text, for instance. I'd just like to avoid comment repetition in my own internal code. Is there a way to tie getX() and the int x argument of the constructor to the x attribute, for instance?
Thanks
Is there a way to tie getX() and the int x argument of the constructor
to the x attribute, for instance?
No, not that I'm aware of. What I do:
don't comment getters (or setters) at all
if X needs contextual information and if it somehow represents (part of the) state of the class I document it in the class-level Javadoc only
One obvious convention would be not writing JavaDoc comments for trivial getters.
public MyLine(double x, double y)
{
MyLine p1 = new MyLine();
p1.x = x;
p1.y = y;
}
That's my code
and the error I get is
./MyLine.java:12: cannot find symbol
symbol : constructor MyLine()
location: class MyLine
MyLine p1 = new MyLine();
Don't instantiate it inside the constructor. Just assign:
this.x = x;
this.y = y;
The error tells you that you don't have a no-argument constructor, but even if you had, the behaviour won't be as you expect
The error message tells you that you don't have a no-arguments constructor in your MyLine class.
You could create one to let that code compile.
However it looks like you're trying to instantiate a MyLine object inside the MyLine constructor. You almost certainly don't want to do this.
Instead you want to take the values passed as arguments and initialize the fields of the current object with them:
public MyLine(double x, double y)
{
this.x = x;
this.y = y;
}
Provide default constructor
i.e. add
public MyLine(){}
and it doesn't makes sense you are creating local object to constructor and assigning values to is..
instead use
this.x=x;
this.y=y;
This line:
MyLine p1 = new MyLine();
should be removed. That's creating a new instance, you actually want to work with the instance you're creating (since you're in the constructor.) You're getting the error because you're calling a constructor from this line that doesn't exist, but you don't want to be doing that anyway.
You can use the this keyword to reference the current instance (which you need to do if the fields have the same name as the parameters, which in this case it looks like they do.)
So taking that into account, you'd end up with the following:
public MyLine(double x, double y) {
this.x = x;
this.y = y;
}
You're constructing an instance of MyLine inside what appears to be a constructor of MyLine. So the caller of the constructor you're writing will cause two objects to be allocated. Is that what you want?
Do you really mean to construct a new MyLine object while constructing another MyLine object?
Do you really mean to do:
public MyLine(double x, double y)
{
this();
this.x = x;
this.y = y;
}
You really shouldn't instantiate a new MyLine inside your other constructor. Why not simply do:
public class MyLine {
private double slope;
private double constant;
// creates a new line: f(x) -> m*x + b
public MyLine(double m, double b) {
this.slope = m;
this.constant = b;
}
// ...
}
The problem is that once you create a constructor yourself, like public MyLine(double x, double y) the compiler won't add the public MyLine() default constructor automatically.
If you want to make this a factory method you should return p1 and maybe make it static.