How does a class referenced to itself work? - java

Let's say we have a class like this one:
class XCopy {
public static void main(String[] args) {
int orig = 42;
XCopy x = new XCopy();
int y = x.go(orig);
System.out.println(orig + " " + " y);
}
}
I know the go method is missing but never mind. Should this work? It appears so, but I just can't picture in my head how that self-reference inside the class works; does it have any side effects? Why does this work? Isn't that some sort of infinite recursive loop?
Anyway, I just can't figure out exactly how this works; thanks in advance.

I gather you are looking at this and thinking it is a chicken and the egg type issue, but it's not at all.
If this is your first OO language you are probably confused about Java's terminology. Java has something called "static methods". You're main(String[]) method is a static method. These static methods are really just plain old functions. Object Oriented methods on the other hand are called "instance methods" or just "methods". People are often sloppy about the terminology.
In Java, a function (i.e. static method) must be defined in the same place as a class and uses that classes' name identify it. But, it is still just a plain old function. Sometimes a class just has nothing but a bunch of loosely related functions/static methods. Like the Math class has a bunch of functions about math. Sometime a more OO class like string will have some static methods/functions thrown in with the OO methods.
In your program your main function has nothing to do with your class. But it's still perfectly fine to put it there for a small example.
When Java starts in ALWAYS starts in a main function somewhere (you can tell it what class the main function is in).
So when your program runs the JVM selects your main function as a valid main function. It runs the function. Its just a function it doesn't need any objects. Calling main does not create any objects.
Now, when your are in main(String[]) you happen to create an Object here:
XCopy x = new XCopy();
Now you have a new object of type XCopy pointed to by the reference (object pointer) x in the local scope of the main function. If XCopy had a constructor it would have been called.
So if you want to picture it in your head let me write it in a fictitious language for you that has a clear more visual syntax!
here it is:
Namespace XCopy
{
function void main(String[])
{
int orig = 42;
XCopy x = new XCopy();
int y = x.go(orig);
System.out.println(orig + " " + " y);
}
}
Class XCopy
{
method int go(int i)
{
....
return whatever;
}
}
In this same program in this other languages' syntax you can see that you have one function, one class with one method, and you have one instance of that class.
Hope that helps!!

By calling
XCopy x = new XCopy();
you are actually calling XCopy's empty constructor, not main method again.
So, the calls look like:
JVM calls XCopy.main();
main method creates new instance of XCopy by calling XCopy's empty constructor
XCopy constructor ends
main method ends -> program ends

Why would it recurse? main() isn't called anywhere within itself, so it wouldn't recurse. A class is in scope of its own members, so you can create instances of it.
Take for instance a makeCopy() method; it would need to create an instance of another object of its own type.
Don't think of methods as being "inside" a class/object and the action of calling a method from within itself as anything awkward; a method is just a function with an implicit this parameter.

The main method is static, meaning that its code can be accessed independently of the fact that there is an instance of Xcopy. Hence, there is no conflict or recursive loop. It has its own memory space which is different than the memory space allocated for each class instance.

main() is static, therefore you can consider it part of the class, but not of an instance. It gets called by OS+JVM and creates an instance of a class. That class happens to be the class where main() is defined, but that really doesn't matter.

Imagine a different class:
public class Person {
private String name;
private Person favorite;
public Person(String name) { setName(name); }
public void setFavorite(Person favorite) {this.favorite = favorite;}
public Person getFavorite() { return favorite; }
public void setName(String name) {this.name = name;}
public String getName() { return name; }
public static void main(String args[]) {
Person a = new Person("Alex");
Person b = new Person("Becky");
Person c = new Person("Chris");
Person d = new Person("David");
a.setFavorite(b);
b.setFavorite(c);
c.setFavorite(c);
}
}
So, Alex's favorite person is Becky. Becky's favorite person is Chris. But Chris is a narcissist; his favorite person is himself. David doesn't have a favorite person. Sadly, nobody thinks David is their favorite person.
When you apply the concept of self-references to something with real-world semantics, doesn't it make sense that such a structure is possible? Note, setting a self-reference doesn't create a copy. There is still only one Chris in this program.
As long as you don't make the move of saying, "I'm going to ask each person who their favorite person is. Then I'm going to ask that person who their favorite person is. I'm not going to stop until I find David. Because then, you do have a chance at looping forever.

Related

How to call an entire class from another class in Java?

I am a beginner in Java. I have two packages in my current project. Each of the packages have two classes called the "packageClassOne" and "packageClassTwo".
The packageClassTwo has a constructor and other public methods.
I want to call the PackageClassTwo from an if statment located in the PackageClassOne. My code looks something like this
packageClassOne:
public class packageClassOne {
public void selectComponent(boolen) {
if(/* check condition*) {
packageClassTwo value = new packageClassTwo();
}
}
}
packageClassTwo:
public class packageClassTwo {
public packageClassTwo(String name){ //Constructor
int length = name.length();
}
public String CreateWord(){
/*functionality ofthis method*/
}
public String CreateSentence(){
/*functionality ofthis method*/
}
}
The problem is that everytime I call the packageClassTwo from my packageClassOne it tries to call the constructor instead of calling the class itself. I want to call the entire packageClassTwo instead of just the constructor.
Can somebody help me please? Thank you in advance for your help
Since Java is an object oriented language, you have to have a mindset of dealing with instances that are realizations of the classes you defined. These are the objects.
So if you want to call a method from packageClassTwo class, you first create an object of packageClassTwo. You seem to be trying to do just this. Once you have the object, you can call its methods. For example
//Instantiate an object by calling the constructor
packageClassTwo object = new packageClassTwo(string);
//Now call its methods
String val = object.CreateWord()
There is no such thing as "calling a class". You call methods of objects of a class.
Occasionally, there might be a well founded need to call methods of a class without initializing objects. Look into static methods and classes for further reading.
If you want to call all methods of packageClassTwo you have to do it explicitly
packageClassTwo pct = new packageClassTwo("");
pct.CreateWord();
pct.CreateSentence();
If you allways want the 2 methods to be called when you create a new packageClassTwo object, than you can just add the calls to the constructor
public packageClassTwo(String name) {
int length = name.length();
pct.CreateWord();
pct.CreateSentence();
}
Edit:
Note that in the second case, if you end up only calling the 2 methods from inside the constructor, it is better to make them private.
As a sidenote, it is a general convention in java to have class names start with a upper case letter : PackageClassTwo not packageClassTwo, and method names to start with lower case createWord not CreateWord. This wll make your code more readable.
If you want to call all the methods from the packageClassTwo, call them from the packageClassTwo constructor
public packageClassTwo(String name)
{
int length = name.length();
CreateWorld();
CreateSentence();
}
I don't think your code will run without compiling errors.because you did not declare the constructor packageClassTwo().

Inheritance and this keyword in Java

Hello guys I have question related to 'this' keyword in Java.
(1)
Lets say Computer extends from Machine and we have the current code:
public class Machine {
private String name = "Machine";
public void test()
{
System.out.println(this.name);
}
public void test2()
{
System.out.println(this);
}
}
public class Computer extends Machine {
public void test()
{
System.out.println(this);
}
}
public class main {
public static void main(String[] args) {
Machine c = new Computer();
c.test();
c.test2();
}
}
Its prints:
Computer#1db9742
Computer#1db9742
It means the 'this' in Computer refers to Computer and this is I understood but the 'this' in Machine also refers to Computer and this is what I didn't understand.
How this happened and why..???
(2)
So if Machine m = new Computer() this is true?
So to all that answered me, i can understand that this is related to the new or what we say what our Type pointing for...?
The keyword this refers to the current object, that is an instance of a class, not to a class itself. You have created a single object (with new Computer()), which is an instance of Computer. Since Computer is a subclass of Machine, it is also an instance of Machine, but the default toString() method will return a string containing the most precise type, in this case Computer.
Computer#1db9742 is just a name for your object. It is the same object, even if each method is defined in a different class.
"this" refers to the object, not to the class.
Computer extends Machine, so Computer inherits all the methods of Machine, making them their own.
When you instantiate Computer you're running all of it's methods.
You cannot access private variables from the class, you have to either create getter method or make the variable public, moreover this in System.out.println() calls toString() method, and if undefined, it prints something like that you have in results (type of object and location in memory).
Just create method in Machine class:
public String getName() {
return name;
}
And in main method make add following:
System.out.println(c.getName());
It's the instanciated type that counts. Not the reference.
Take this example:
class Animal{
void makeSound(){
System.out.println("wut ? Don't know what to do :(");
}
}
class Cat extends Animal{
void makeSound(){
System.out.println("Miaw !");
}
}
when you create for example:
Animal a = new Cat();
You're actually creating a cat. And still, a Cat is always an animal ? (Am I right ? :D)
a.makeSound() will result in printing Miaw !. But !
Animal a= new Animal();
a.makeSound();
will result in printing : wut ? Don't know what to do :( . What's the sound of an animal after all ? You see ?
If someone asks you to bring an animal, you can always bring a cat. Right ?
Well, this is the case with methods asking for an Animal parameter:
take this function:
void doSomething(Animal param){
// some code
}
you can call it using a Cat object as a parameter:
//...
doSomething(new Cat());
//...
Etc.. (you can push the analogy.. for a wider level)
Java VM takes the responsibility to make a type resolution at run time to decide which method to call. And that's some of the sweetness of OOP.
this is a pointer to the current object, and objects know what type they are.
this references the context that you are in. In your case, you are using it on the Machine and the Computer class.
To understand this, you need to first understand that the variable Machine m, is not the object itself, but it does reference to the object in the memory.
An then, you are calling from the same object, two different methods, one that is implemented on the objects class(Computer), and other that is implemented on its superclass(Machine).
Indifferently witch method is called, the object where you make the method call is the same, and the this keyword, will reference this same object, and then, the result of your test will be exactly the same object:
Computer#1db9742
Computer#1db9742

One variable clobbers another

I have a very weird situation. I have a class that has a couple of members, like this:
public class myMainClass
{
public aClass myObject = new aClass();
private int numberOfUpdates = 0;
public anotheClass.memberClass anotherObject = new anotheClass.memberClass();
Note that the anotherClass has a class defined within it. (Not sure if that enters into the problem I'm having).
Both aClass and anotheClass.memberClass have a member with the same name, ThisMember.
I also have a method within myMainClass that does some modifications to the members of the myMainClass object:
public void Update(double aPassedInNumber)
{
anotherObject.ThisMember = aPassedInNumber;
//etc
}
I'm only modifying that one member. However, when I do that, myObject.ThisMember also gets modified to the same value! It's as though (??) both member variables occupy the same location in memory. Or that one is somehow a reference to the other.
It's as if I had done:
public void Update(double aPassedInNumber)
{
anotherObject.ThisMember = aPassedInNumber;
myObject = aPassedInNumber;
//etc
}
BUT I'M NOT. I'm only doing the first assignment, yet both of those variables get modified.
I've traced this and printed out diagnostics and used a watch window and it clearly modifies both variables.
How can that be? What am I doing wrong? How can I fix it?
Oh, man. It looks like I still don't have a handle on the reference concept in JAVA. That one variable is indeed simply a reference to the other object.
Now it seems I have to implement a copy method for the class.
Aaaargh!!

I do not understand 'this' being used with a superclass

I have two classes and an interface shown below.
Quick summary: Interface Winterface, Class Big, Class Little that extends Big and implements Winterface.
public interface Winterface {}
public class Big {
public int hello = 88;
public Big() {}
public void theMethod() {
System.out.println ("Big was here: " + (this instanceof Winterface) + ", " + this.hello);
}
}
public class Little extends Big implements Winterface{
private boolean hello = true;
public Little(){}
public void theMethod() {
super.theMethod();
System.out.println("Little was here: " + hello);
}
public static void main(String [] args) {
Little l = new Little();
l.theMethod();
}
}
When I execute the main in Little, I get the following output
Big was here: true, 88
Little was here: true
my question is, how can
1) (this instanceof Winterface) return true but
2) this.hello be 88?
If this.hello = 88, then this = Big, which isn't an instance of Winterface.
I do not understand how this is possible, thanks in advance
EDIT: THANKS everyone I understand now that 'this' refers to little, which is a Big and implements Winterface. Since the method is being called as super.theMethod(), the variable 'hello' available is the one in Big even though 'this' refers to little.
this can only be one class. However this.hello is the field accessible to that class.
As this can only be one class it is a Little which has a parent Big and implements Winterface When you call a method in its parent which can only see hello that is what it sees.
i.e. Java supports polymorphism for methods but not fields.
l is Little but Little is a Big and also implements the behavior of Winterface.
The super is a call to the parent class so the hello member of the parent class (i.e. Big) is used.
You are not doing this.hello but super.theMethod() that uses the parent's class member variable hello.
UPDATE:
The super.theMethod() invokes the corresponding method in the parent class. In the parent class you access the fields of the parent (which also belong to the derived class since Little is also a Big). So the this.hello at that point is accessing the part of the code that is of the parent class.
You can imagine the memory print of Little as follows:
++++++++
+ Big +
--------
+Little+
++++++++
So Little has all the members variables of the parent i.e. Big and when the code runs inside super.theMethod() it is running inside the "code area" of Big.
As Peter states in his answer, polymorhism is not supported for methods and I hope that this overly simplistic description helps understand this
This is because the this instanceof ... check does not use the static (i.e., compile-time) type (which is Big), but the object's (this') dynamic run-time type (i.e., this.getClass()), which is Little in your example. If it would use the static type, the operator would be pretty pointless, since we would have:
Object obj = "foo";
if (obj instanceof Object) { /* always entered */ }
/* but */ if (obj instanceof String) { /* never entered */ }
statically, at compile-time. The purpose of the instanceof operator is to enable run-time type testing, for example:
Object obj = /* whatever */;
if (obj instanceof String) {
String str = (String)obj; // Cast cannot fail
...
} else if (obj instanceof Long) {
Long val = (Long)obj; // Cast cannot fail
...
}
Note, that this technique should only be used sparingly.
Your variable is an instance of Big and of Little. It's a direct instance of Little, but since Little inherits from Big the instanceof operator will return true for Big too.
Little l = new Little();
System.out.println(l instanceof Little); // true, l is an instance Little
System.out.println(l instanceof Big); // true, l is an instance of Little which inherits from Big
Your other misunderstanding (I'm assuming) is how the 'method lookup' works. When you call theMethod the it picks Little's implementation of that method. When you call super.theMethod though, you've explicitly said "call Big's version of this method", and then inside that method it's using Big's hello variable rather than Little's hello variable.
What is happening here is that when you are defining your variable hello in Little you are not overwriting the variable hello that is inside Big you are defining a new variable hello within Little that is hiding the variable hello within Big. Thus within the scope of Big, hello will refer to the integer value of 88 and within the scope of Little, hello will refer to true. These are different variables both contained within your object, the only difference is the scope by which you refer to them.
Like others here have said, instanceof is an operator that compares the runtime type of your object (what is returned by this.getClass()). When in Big even though the scope of the variables within your object will refer to Big, this is still of runtime type Little which is why it is an instance of Winterface.

OOP Java : can return an child class to parent class?

I'm a newcomer of OOP, so I has one silly question about when a class extends another class.
Here my example:
public class Test {
public Monitor getMonitor(){
return new LCD();
}
class LCD extends Monitor { NO-ERROR
class LCD { ERROR at line `return new LCD`
//some other method or function not in Monitor Class. Example:
boolean isSamsung;
public LCD whatkindLCD(){
}
}
}
I have one question for above code : because LCD is extended from Monitor and LCD has some other properties/methods that Monitor does not. So, LCD is child of Monitor, right ?
It means you try to put a "big box" to a "small box". So, why when I return new LCD, Eclipse don't notice error as when I just use class LCD {.
Thanks :)
In your second (error) case, you've forgotten to declare that LCD does in fact extend Monitor. You're just defining a "normal", standalone class - and so a new LCD() is not an instance of Monitor.
The compiler should be happy if you declare the LCD class like this:
class LCD extends Monitor {
//some other method or function not in Monitor Class. Example:
boolean isSamsung;
public LCD whatkindLCD(){
}
}
Edit (in response to comment): It's not a problem at all that the LCD class has extra properties/methods compared to Monitor. The code that's going to call getMonitor(), only really cares that it gets a Monitor back - that is, something that has all the methods and properties and behaviour of a Monitor.
So if you had turnOff and displayBitmap(int[][] data) methods on your Monitor class, then your LCD class will also have these methods. Any instance of LCD can behave as a Monitor when one is needed - this is the basic principle of subclassing in OO languages. So whenever something wants a Monitor, you can give it an LCD, or an instance of CRT or SamsungLCD instead if you had those, and the compiler can be satisfied that the right methods/properties will exist and can be called.
(Technically this is the Liskov substitution principle if you like formal definitions, but you don't need to understand it in that level of detail.)
The box analogy is wrong, think of an is a relationship instead.
In the first example, LCD extends Monitor, that is LCD is a Monitor, therefore anywhere where Monitor is expected, LCD is fine. When you think about in real-world terms instead of looking at the code, you realise this is correct. Everything that you can expect a monitor in general to do (e.g. display a picture), an LCD monitor will do.
In the second example LCD is not a Monitor, so you get an error message.
Understand Inheritance as a "is a" relationship. Here is a simple example I used to understand inheritance during my novice years.
class Employee
{
String name;
int salary;
Employee()
{
name = "Employee";
salary = 5000;
}
public String getName()
{
return name;
}
public int getSalary()
{
return salary;
}
}
class Manager extends Employee
{
int bonus;
int salary;
Manager()
{
bonus = 1000;
salary = 6000;
}
public int getBonus()
{
return bonus;
}
public int getSalary()
{
return salary;
}
}
class Test
{
public static void main(String[] args)
{
Employee e = new Employee();
System.out.println(e.getName());
//System.out.println(e.getBonus());
System.out.println(e.getSalary());
System.out.println();
Manager m = new Manager();
System.out.println(m.getName());
System.out.println(m.getBonus());
System.out.println(m.getSalary());
System.out.println();
Employee em = new Manager();
System.out.println(em.getName());
//System.out.println(em.getBonus());
System.out.println(((Manager)em).getBonus());
System.out.println(em.getSalary());
}
}
Compiler looks for reference type before calling any operations on it.
em.getBonus() doesn't work because Employee doesn't have a bonus method.
But using a cast we can make it work.
((Manager)em.)getBonus()
Reason why compiler looks for the reference type before calling any operation on it is as follows:
Manager[] managers = new Manager[10];
It is legal to convert this array to an Employee[] array:
Employee[] staff = managers; // OK
Sure, why not, you may think. After all, if manager[i] is a Manager, it is also an Employee. But actually, something surprising is going on. Keep in mind that managers and staff are references to the same array.
Now consider the statement
staff[0] = new Employee("John Eipe", ...);
The compiler will cheerfully allow this assignment.
But staff[0] and manager[0] are the same reference, so it looks as if we managed to smuggle a mere employee into the management
ranks.
That would be very bad — calling managers[0].setBonus(1000) would try to access a
nonexistent instance field and would corrupt neighboring memory.
To make sure no such corruption can occur, all arrays remember the element type with
which they were created, and they monitor that only compatible references are stored into
them. For example, the array created as new Manager[10] remembers that it is an array of
managers. Attempting to store an Employee reference causes an ArrayStoreException.
Your method getMonitor returns a "Monitor" type.
When you extend your class LCD with Monitor, you are saying the complier that LCD is a Monitor.
When you remove the extends, the LCD class becomes a plain class and not a Monitor type.
If you modify your getMonitor to
public LCD getMonitor(){
// code here
}
The error will go.

Categories

Resources