this keyword as a reference variable - java

this is a variable which holds the reference ID of the current object.
So why it cannot be used as a reference variable ?
Temp t = new Temp(); //Temp be any class
t.show(); //show() be any method in Temp
this.show(); // error

That will only throw an error if the class you're in does not have a show() method or if you are trying to do that from a static context.
this hold the reference ID of the current object so it depends where you are and not what objects you've just created.

Current object is not an object you referred last. Here is example of this usage:
public class Temp {
private int x = 3;
public void show() {
this.x = 4;
this.show(); // same as show();
}
}

The "this" keyword in java is to reference the object the code is running in.
It is mostly useful you are comparing the object within itself. Example:
public boolean equals(Object object) {
return object == this;
}
Here is another snippet of code to help you understand:
public class Test {
public Test() {
}
public static void main(String... args) {
Test test = new Test();//original test object
Test test2 = new Test();
test.equals(test);//returns true
test.equals(test2);//returns false
}
public void equals(Test testParameter) {
// in this particular case "this" refers to the
// original test object (defined in the main method)
// as it is the only object calling this method.
return testParameter == this; // "this" is the object that is calling the method
}
}

Related

Any tips on getting around the pass-by-value issue?

In the code below I have a classic Java pass-by-value issue (written in processing; setup() == main).
void setup()
{
A a = new A();
a.makeTheB(a.b);
System.out.println(a.b); //Returns null
}
class A
{
B b;
public void makeTheB(B tempB)
{
tempB = new B();
}
}
class B
{
float x; //not used
}
Anyone have any clever tricks they use to assign a new object to a reference passed as a parameter?
I can describe my intent if needed, but I would love a generalized answer if one exists.
EDIT: Looks like I need to describe my intent.
I'm using the Composite pattern to create a recursive hierarchy of objects. I have an object outside that hierarchy that I would like to reference one of the objects within the hierarchy. I would like to pass that object though the composite, Chain of Responsibility style, and then have that object reference whichever object took responsibility for it.
I can find a way to achieve this though return values I'm sure, but being able to assign the parameter I passed down the hierarchy would sure be nice if there's any cleaver way to do it.
You can try returning the object of B that you create in class A4
Illustrated below.
public class A {
B b;
public B makeTheB(B tempB) {
tempB = new B();
return tempB;
}
}
public class B {
float x; //not used
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = a.makeTheB(a.b);
System.out.println(b); //Returns nu
}
}
Output: B#7852e922
You can do this, but perhaps you need to provide a better description of what you want to achieve.
void setup()
{
A a = new A();
a.makeTheB(a);
System.out.println(a.b);
}
class A implements Consumer<B>
{
B b;
public void accept(B b) {
this.b = b;
}
/**
* Create a B, and give it to a Consumer which knows where it needs to be stored.
*/
public void makeTheB(Consumer<B> consumer)
{
consumer.accept(new B());
}
}
class B
{
float x; //not used
}

Overriding methods and weird behavior

I have 2 classes, one which extends the second one and overrides some of the methods of the parent. When I call fs.m(ff) I got a weird result, and I can't figure out why does it happen. type First fs shouldn't have access to class Second methods, even if we assigned a new Second object to them, unless we casted it like that - (Second) fs.m(ff). Could anyone please explain why does this code produce output "override"?
public class Main {
public static void main(String[] args) {
First ff = new First();
First fs = new Second();
Second ss = new Second();
System.out.println( fs.m(ff));
}
}
public class First {
public String m(First x){
return "default";
}
public String m(First x, First y){
return "default";
}
}
public class Second extends First{
public String m(Second x){
return "overload";
}
public String m(First x){
return "override";
}
public String m(First x, Second y){
return "???";
}
}
The method invoked for fs.m(ff) is determined by the runtime type of fs. That runtime type is Second, and since Second overrides the public String m(First x) method, that method is executed.
fs has access do the methods declared in First class, since it is of type First, but during runtime, the actual methods that get executed depend on whether those methods are overridden by the run-time type of the instance assigned to fs, which is Second.
Fs is actually pointing a Second Object (fs is a reference to an object of type Second).
So when you call fs.m(ff) it is actually calling the object on Second due to dynamic binding (override).

Change boolean Values?

I have a question about boolean values in Java. Let's say I have a program like this:
boolean test = false;
...
foo(test)
foo2(test)
foo(Boolean test){
test = true;
}
foo2(Boolean test){
if(test)
//Doesn't go in here
}
I noticed that in foo2, the boolean test does not change and thereby doesn't go into the if statement. How would I go about changing it then? I looked into Boolean values but I couldn't find a function that would "set" test from true to false. If anyone could help me out that would be great.
You're passing the value of a primitive boolean to your function, there is no "reference". So you're only shadowing the value within your foo method. Instead, you might want to use one of the following -
A Holder
public static class BooleanHolder {
public Boolean value;
}
private static void foo(BooleanHolder test) {
test.value = true;
}
private static void foo2(BooleanHolder test) {
if (test.value)
System.out.println("In test");
else
System.out.println("in else");
}
public static void main(String[] args) {
BooleanHolder test = new BooleanHolder();
test.value = false;
foo(test);
foo2(test);
}
Which outputs "In test".
Or, by using a
member variable
private boolean value = false;
public void foo() {
this.value = true;
}
public void foo2() {
if (this.value)
System.out.println("In test");
else
System.out.println("in else");
}
public static void main(String[] args) {
BooleanQuestion b = new BooleanQuestion();
b.foo();
b.foo2();
}
Which, also outputs "In test".
You named your parameter the same as an instance variable. Here, the parameter is the one referenced, not the instance variable. This is called "shadowing", where the simple name test as a parameter name shadows the instance variable also called test.
In foo, you changed the parameter test to true, not the instance variable test, which was unchanged. That explains why it doesn't go into the if block in foo2.
To assign the value, get rid of the parameter on foo, or use this.test to reference the instance variable.
this.test = true;
and
if (this.test)
You need to be aware that:
In Java, arguments are pass-by-value.
Boolean, the wrapper type of boolean, is immutable.
Because of 1 and 2, you have no way to change the state of the Boolean pass in the method.
You mostly have 2 choice:
Choice 1: Have a mutable holder for boolean like:
class BooleanHolder {
public boolean value; // better make getter/setter/ctor for this, just to demonstrate
}
so in your code it should look like:
void foo(BooleanHolder test) {
test.value=true;
}
Choice 2: A more reasonable choice: return the value from your method:
boolean foo(boolean test) {
return true; // or you may do something else base on test or other states
}
the caller should use it like:
boolean value= false;
value = foo(value);
foo2(value);
This approach is preferrable as it fit better with normal Java coding practices, and by the method signature it gives hint to the caller that it is going to return you a new value base on your input
Here is a good explanation.
http://www.javadude.com/articles/passbyvalue.htm
Java has pointers, and the value of the pointer is passed in. There's
no way to actually pass an object itself as a parameter. You can only
pass a pointer (value) to an object.
And my solution
public static class MutableBoolean {
public boolean value;
public MutableBoolean(boolean value) {
this.value = value;
}
}
usage:
MutableBoolean needStop = new MutableBoolean(false);
call( new Listener(needStop){
void onCallback(){
needStop.value = true;
}
})
Your foo method changed the value of test to true. It looks like what you want is to use instance variables for each function.
boolean test = false;
...
foo(test)
foo2(test)
foo(Boolean test){
this.test = true;
}
foo2(Boolean test){
if(this.test)
//Doesn't go in here
}
This way, your method only changes the value of test inside of that method, but your public test parameter stays with a false value.

NullPointerException when accessing a static field

As they say System is final class which have out of type PrintStream as a field member and println is method in PrintStream class.
I created a class UseNumber with static field no of type Number and just wanted to access a method of Number class but it is throwing NullPointerException
public class Number {
private int first;
private int second;
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
}
and for UseNumber Class
public class UseNumber {
private static Number no;
public static void main(String[] args) {
UseNumber.no.setFirst(12); //throwing nullpointer exception here
UseNumber.no.setSecond(22);
System.out.println(UseNumber.no.getFirst()+UseNumber.no.getSecond());
}
}
Re: NullPointerException
setFirst is not a static method and it requires an instance of Number. You didn't create one. You just declared a Number variable called no. Since it's initialized to null by default, you're getting a NullPointerException.
One way to fix it:
private static Number no = new Number();
The variable no being declared as static inside UseNumber simply means you will be able to access this object without an instance of UseNumber. But this static declaration won't cascade down to the methods of no. They will still require an instance, as emphasized by the error you're getting.
Re: System.out
out is a static member of System - but it's an instantiated object already.
In fact, if you view the code of System, you'll find this line:
out = com.ibm.jvm.io.ConsolePrintStream.localize(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)), true);
So when you say:
System.out
System will give you the its initialized PrintStream object called out. In essence, System.out.println is just a shortcut for this:
PrintStream p = System.out;
p.println();
A nullpointerException is thrown when you attempt to access a null object by the "." operator.
In the line you indicated the exception is thrown, the no object is null and you are trying to access its setFirst method which will of course throw a nullpointer exception.
to fix the error, initialize your no object, maybe like this :
public class UseNumber {
private static Number no;
public static void main(String[] args) {
UseNumber.no = new Number(); // Initialize here your no object
UseNumber.no.setFirst(12); //This line will no longer throw an exception.
UseNumber.no.setSecond(22);
System.out.println(UseNumber.no.getFirst()+UseNumber.no.getSecond());
}
}
Maybe you can write a interface method to get the instance of no. In the method you can check if it's null, similar to the way we do with Singleton pattern.
public class UseNumber {
private static Number no;
public static getNumberInstance() {
if(no == NULL) {
no = new Number(); //This will get executed only once, for first call.
}
return no;
}
public static void main(String[] args) {
UseNumber.getNumberInstance().setFirst(12);
UseNumber.getNumberInstance().setSecond(22);
System.out.println(UseNumber.getNumberInstance().getFirst()
+UseNumber.getNumberInstance().getSecond());
}
}

Trouble understanding why I cannot modify variable outside a method?

public class test {
public static void main(String[] args) throws Exception {
final int num = 111;
new Thread() {
#Override
public void run() {
num = 222;
}
}.start();
}
}
I want to change the value of num however I can only do that if I set it to final which would not let me modify this. In other languages such as C we can use pointers but Java cannot?
Java has neither closure nor pointers.
A solution would be to make the num static in the class :
public class test {
static int num = 111;
public static void main(String[] args) throws Exception {
new Thread() {
#Override
public void run() {
num = 222;
}
}.start();
}
}
Another solution would be to use an object like AtomicInteger. You can't change the value of the variable but you can change the content of the value :
public class test {
public static void main(String[] args) throws Exception {
final AtomicInteger num = new AtomicInteger(111);
new Thread() {
#Override
public void run() {
num.set(222);
}
}.start();
}
}
Why this isn't allowed
main is a method. As with other programming languages, when a method returns, all of the variables declared in its body go out of scope, and accessing them has undefined behavior. Under some circumstances, the memory location where they used to be will no longer be valid.
Obviously this is a problem. If you try to change num after main has returned, you might overwrite a portion of the stack that doesn't belong to num anymore. Java's response to this difficult situation is to introduce restrictions on how you can share variables: they must be final. Java can then safely locate them in such a way that reading them will produce consistent results even after the function has returned.
The C equivalent to this problem is storing and using the address of a local variable outside of its scope, something that all C programmers are taught to never do.
To get around it, declare num as a member of test, create an instance, and pass that to it. This removes the dependancy on a local variable, and thus removes the final restriction.
public class test
{
int num = 111;
public static void main(String[] args) throws Exception
{
test t = new test();
(new Thread(t) {
test mytest;
Thread(test t)
{
mytest = t;
}
#Override
public void run() {
mytest.num = 222;
}
}).start();
}
}
Well, you can access it if you declare variable outside the function. Like this:
public class test {
private static int num = 111;
public static void main(String[] args) throws Exception {
new Thread() {
#Override
public void run() {
num = 222;
}
}.start();
}
}
You are creating new Thread() { class as inner class. You can't access outer class variables without declaring them as final.
You can't change final variable references.
There are two ways you can do this,
1) Make num as static
2) Wrap num inside an object (You can update state of the object even though you define reference as final).
NOTE: Both are not thread safe.
Yep you can't win here! You need to set it final to be able to access it, but then you will not be able to modify it. You'll need to look at a different approach.

Categories

Resources