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.
Related
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;
}
}
Given this code snippet:
class Ex1{
public static void main(String args[]){
int x = 10;
int y = new Ex1().change(x);
System.out.println(x+y);
}
int change(int x){
x=12;
return x;
}
}
I understand that the x in main won't get changed by the change method and return the value 22 because Java primitives are call-by-value. However, if I change all the int to Integer, making them objects and therefore theoretically call-by-value-of-reference, why does the program still return 22?
Is it possible to modify the method change such that it also modifies the variable x in main?
EDIT: new snippet
class Ex1{
public static void main(String args[]){
Integer x = 10;
Integer y = new Ex1().change(x);
System.out.println(x+y);
}
Integer change(Integer x){
x=12;
return x;
}
}
Both value and reference types are passed by-value in Java (see the Java Tutorials). This means that the passed-in reference still points at the same object as before the call, even if the internals of a method change the reference assigned to a method's parameter variable.
The primitive wrappers are all reference types, so there is no difference between their behaviour and the behaviour of any other reference type when passed as an argument to a method.
However, you can change the values inside a reference object, and those changes will be reflected after the method call completes, in the calling method. You can't do this with the primitive wrappers though: they are immutable.
public static void main(String[] args){
Foo parentFoo = new Foo(1);
System.out.println(parentFoo); // prints "instance 1, data is now 1"
changeReferenceFail(parentFoo); // prints "instance 2, data is now 2"
System.out.println(parentFoo); // prints "instance 1, data is now 1"
mutateReference(parentFoo); // prints "instance 1, data is now 3"
System.out.println(parentFoo); // prints "instance 1, data is now 3"
}
private static void changeReferenceFail(Foo myFoo) {
myFoo = new Foo(2); // assigns a new object to the myFoo parameter variable
System.out.println(myFoo);
}
private static void mutateReference(Foo myFoo) {
myFoo.setData(3); // changes the reference variable internals
System.out.println(myFoo);
}
...
class Foo {
private static int iidSeed = 0;
private int iid = 0;
private int data;
public Foo(int data) {
this.data = data;
this.iid = ++iidSeed;
}
public void setData(int data) { this.data = data; }
public String toString() {
return String.format("instance %d, data is now %d", this.iid, this.data);
}
}
You asked: "Is it possible to modify the method change such that it also modifies the variable x in main?".
You can either pass a reference object, and modify an internal field (as per mutateReference above). Or you can return a new integer and assign it to your local variableexactly as you are doing already.
Integer change(Integer x){
x=12;
return x;
}
Because this does not change what is stored inside the object Integer x, but assigns a new value to the variable x. It is not the original argument object being changed, but a new Integer object is created assigned to the variable formerly holding the original object.
As you said, when passing an object to a function, you actually pass the value of its reference. Thus, statements like myParam = something have no effect on the object passed to the method, only method calls such as myParam.mutate() can change its state. Nevertheless, Integer is an immutable class so you will not be able by any mean, to change the value of the Integer in the main.
You are passing the value of x to your method, that applies that value to another variable x. You would need to modify the correct instance of x to change it in main. This snippet changes x, although I'm sure you knew how to do this already.
class Ex1{
int x = 10;
public static void main(String args[]){
System.out.println(x);
changeX(15);
System.out.println(x);
}
void changeX(int newVal){
x=newVal;
}
}
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).
public class NotActuallyImmutable {
private final int x;
public NotActuallyImmutable(int x) {
this.x = x;// line 1
}
public int getX() {
return x;
}
}
public class Mutable extends NotActuallyImmutable {
private int x = 123;
public Mutable(int x) {
super(x);
}
public int getX() {
return x++;
}
}
now in my main class
NotActuallyImmutable n = new Mutable(42); // line2
int x = n.getX();
System.out.println("x is"+x);
I am expecting the output as 42 but it return the output as 123. I am expecting 42 because at line 2 I am making object of class Mutable and then at line 1 I am setting value as 42. so when i do n.getX() I should get the this latest value not the default 123. I know Ii am missing something but not able to figure out the logic behind it?
The problem is that the field x in Mutable and the field x in class NotActuallyImmutable are not the same. The x that is returned by getX() is the one in Mutable (because the getX() that is invoked is Mutable.getX(), not NotActuallyImmutable.getX()).
Note that if you removed the instance field from Mutable, then you would have a compiler error because NotActuallyImmutable.x is private to NotActuallyImmutable and not accessible to any code in Mutable.
If you made NotActuallyImmutable.x a protected field, then Mutable.x would shadow it and you would still have the same behavior. If you removed Mutable.x in this case, you would still have a compiler error because you were trying to increment a final field.
If you remove Mutable.getX(), then the x that would be returned by getX() would be NotActuallyImmutable.x, despite there being another field of the same name in Mutable.
The private int x in Mutable and the private int x in NotActuallyImmutable are completely different fields that just have the same name.
This isn't a problem for the compiler because you can't access a private field from another class. So as far as the compiler is concerned, when you define Mutable, the x in NotActuallyImmutable is invisible and might as well not exist.
It is of course confusing for the programmer. If you rename one of the fields to y (and the getter method to getY) the behaviour seems much more intuitive.
NotActuallyImmutable n = new Mutable(42); // line2
This means you have an object of type NotActuallyImmutable but the instance of created object is Mutable.
so in this code your dealing with Mutable object which will return 123. as the number you passed is saved in NotActuallyImmutable not in Mutable,
n has two different x values which are visible in different contexts, the parent class's private member variable and the child class's private member variable.
NotActuallyImmutable n = new Mutable(42); // line2
Creates a new Mutable. Executes parent(x) which sets the parent class's x to 42.
int x = n.getX();
n is a Mutable instance so this calls Mutable's getX() which returns Mutable's value for x (123) rather than the parent's.
I agree with Nice explanations given in above answers. But to to just brief the final understanding. As i am doing new Mutable(42).getX(), jvm first will look in Mutable object to get the value of X not inside NotActuallyImmutable. If i remove getX() method from Mutable , i get the expected(as per my expectation) value i.e 42.
This example gets messy becoz variable name i.e X is same in parent and child class but good for understanding concept
Though I'm trying to understand why "this" is needed, I'm very confused about its purpose. For instance, I coded the following:
public static void main (String args[])
{
SandboxClass1 temp = new SandboxClass1(1,2,3);
System.out.println(temp.getX());
System.out.println(temp.getY());
System.out.println(temp.getZ());
System.out.println("----------------------------");
SandboxClass1 temp2 = new SandboxClass1(4,5,6);
System.out.println(temp2.getX());
System.out.println(temp2.getY());
System.out.println(temp2.getZ());
}
public class SandboxClass1
{
private int x = 1;
private int y = 1;
private int z = 0;
public SandboxClass1(int x, int y, int zz)
{
this.x = x;
this.y = y;
z = zz;
}
public int getX()
{
return(this.x);
}
public int getY()
{
return(this.y);
}
public int getZ()
{
return(this.z);
}
}
Why do I need to code "this.z = zz"
when I could just as well write, "z = zz"?
You don't, in this case. It's only required when you must eliminate ambiguity, like when parameters and instance variables share a name.
Some people prefer to use "this" to remove conceptual ambiguity and explicitly state that the code references an instance variable.
(On a side note, the parentheses around the return values are unnecessary and a bit noisy, IMO.)
In your SandboxClass1 constructor, you have two pairs of variables each called x and y. There's the x and y declared on the object itself ("private int x = 1"), and the separate x and y that are parameters to the constructor ("int x").
The local (parameter) variable shadows the class variable. So if in the constructor you just did
x = x;
the assignment would have no effect.
The keyword this is a reference to the object that the method/constructor was called on. In the statement
this.x = x;
you're using it to assign to the other x at class level. By qualifying the name, you can tell them apart.
It's not necessary to use this with the z/zz assignment because they have different names.
It's also not necessary in the getX/Y/Z methods because there are no local variables in those methods shadowing the relevant class variables. It does no harm though.
In the SandboxClass1 constructor two of the parameters (x and y) hide class variables because they are the same name. If you want to assign the class variable x to any value while in the code>SandboxClass1 constructor, you must address it using this.x to tell the compiler that "I want to assign the class scope variable named x, and not the method scope variable named x". The same applies to y.
Since the parameter z does not hide the class scope variable named zz you do not need to tell the compiler the scope of the zz variable, the class scope zz is the only recognized variable so that is the one that gets assigned.
It has the same effect. this is needed if there is a local variable which overrides a field of the class; then you get the local variable and not the class field.
An additional advantage you can indicate the variables better. If there is a this; it's a field; local variable otherwise.
the keyword this is used to refer to an attribute that is in the class. The keyword this was created to distinguish between class attributes and method parameters. like this:
public class human
{
public void setName(String name)
{
// the first name is a reference to the class attribute name
this.name = name;
// the second name is a reference to the method parameter name
}
// definition of the class attribute name
private String name;
}
when you use the keyword this it refers to the name variable inside the class heres an example where you don't need to use this:
public class Human
{
public void setName(String myName)
{
name = myName
}
private String name;
}
see now there is only 1 variable named name and there is only one variable named myName. In the other example there was 2 variables named name. One was a class attribute and one was a method parameter.
'this' operator just refines that property/field belongs to class you're working in. It's useful whe you have, for example, two variables with the same name:
this.zz = zz;
Unlike, say, Objective-C, "this" is optional when the method or variable is local, and there is no other conflicting use of the same name.
It comes in handy in conflicting-name cases, though, such as in methods that set instance variables such as void setOnionCount(int onionCount) where you would like to use "onionCount" for the formal parameter but still have "onionCount" as the instance variable name. In such a case you can do this.onionCount = onionCount; and everyone is happy (except, I suppose, those in the Peanut Gallery who'll object to this technique).
"this" is also absolutely necessary in cases where you need to pass a reference to the current object to some other class, of course.
hey this is use to provide reference of invoking object. That i.e say suppose ur class is box then if you want to provide it's object then you can provide it within the class box using this keyword.
class Box {
int x;
public Box(int x){
this.x = x;
}
}
here in this case if your object is ob (i.e Box ob = new Box(1)) then the reference it will be passed to the itself.
Note: you cannot use this keyword outside of the class. If you use so then it will give reference of another class.
for complete detail on this keyword refer following link
http://download.oracle.com/javase/tutorial/java/javaOO/thiskey.html