How does Object Oriented Programming work? - java

I am not sure about some things in OOP.
If I have Class1, which has some private field, for example private Field field1, and make
getField1 () {
return field1;
}
then I have some class with constructor
public Class2 (Field field) {
someMethod(field);
}
And then I call constructor of Class2 in Class3 like:
Class2 cl = new Class2(instanceOfClass1.getField1());
And now the question: Am I working with field1 of instanceOfClass1 in someMethod(field)?

This depends on whether field is a value or a reference.
Value types are copied when passed as parameters. Reference types are not; the function is simply handed a "reference" that points back to the original value, and any changes that it makes are reflected in the original value.
Whether a given type is value or reference depends on your particular programming language. Generally speaking, basic integer and boolean types are usually value types, and everything else is up in the air -- some languages make strings values, and others treat them as references, etc.
Edit: Since you mentioned you're using Java, here's a short program that demonstrates value and reference types:
class ClassOne {
public int myInt;
}
class ClassTwo {
public int myInt;
public ClassTwo(ClassOne c)
{
myInt = c.myInt;
c.myInt = 3;
}
}
public class main
{
public static void main(String[] args)
{
ClassOne c = new ClassOne();
c.myInt = 1;
System.out.println("C1: " + c.myInt);
ClassTwo c2 = new ClassTwo(c);
System.out.println("C2: " + c2.myInt);
System.out.println("C1: " + c.myInt);
}
}
Running this program will give the output:
C1: 1
C2: 1
C1: 3
In this program, both ClassOne and ClassTwo contain an integer field -- a value type. ClassTwo takes a ClassOne parameter -- a reference type -- in its constructor, and sets its own integer field based on the value of the ClassOne object it is given, and then changes the ClassOne object's value.
Because classes are reference types, changing the ClassOne object in the ClassTwo constructor causes the original object to be changed. (In the main function here, that's c.) But because integers are value types, even though c2 changes the value of c.myInt in its constructor, because it sets its own value beforehand, c2.myInt isn't affected: it retains the original number, because it was copied rather than referenced.
Hopefully this helps clear things up a bit.

You're working with the value contained in it. If it is a mutable object then yes, it is possible to change the state of the instance of Class1 from outside, which violates data protection principles. This is why you should copy mutable types before returning them.

I had to reread your question two or three times to make sure I understood what you're asking.
To recap:
There is Class1 which contains an field attribute (of type Field?) which is sent back by it's getField1() method.
There is then Class2 which is apparently has a constructor that accepts an object parameter of Field type and contains a method that uses an instance of Field to trigger a local method in this class.
You then use a third class to instantiate Class2 and initialize it using an instance of Field using the getField1() method from an instance of Class1.
In the case of Java, providing you've done the necessary instantiation this would mean that the Field instance in Class1 is being used throughout the process. You can verify this using a System.out.println() (this will give you an # symbol with a series of weird numbers) or using the a.equals(b) method common to all objects.
Here is an interesting link about passing objects by value:
http://www.javaranch.com/campfire/StoryPassBy.jsp

Related

How to set value without setter method?

In the below code snippet how can I set the value of a and b without using the setter method? Is it possible? Can I call the private constructor in the public constructor?
public class ABC {
private int a;
private int b;
public ABC() {
}
private ABC(int a, int b) {
this.a = a;
this.b = b;
}
}
ABC abc = new ABC();
You can use Java reflection, but this is considered to be bad practice and should be avoided. However, if you really need to:
ABC abc = new ABC();
Field abc_a = abc.getClass().getDeclaredField("a");
abc_a.setAccessible(true);
abc_a.set(abc, 20);
Explanation
Field abc_a = abc.getClass().getDeclaredField("a");
In java, there is a set of tools called Reflection, whose intended use is to allow for fields in classes to be dynamically set. A practical use of this is the GSON library, which reads JSON and automatically fills in the corresponding values in a class.
Every class has a Class object to assist with reflection, and every instance of an object has a method called getClass(). Calling this method will give you the Class object representing that class and using that, you can then invoke the getDeclaredField(fieldName) method which will return a Field object that allows you to do a variety of things to that field, one of which is setting the value.
abc_a.setAccessible(true);
Because the field being referenced to is private, this must be invoked to allow it to be accessed. If it was public, this step could be omitted.
abc_a.set(abc, 20);
This finally changes the value of the field a in the ABC class. The first parameter is the object you wish to change the value of, and the second parameter is the new value. Note that Field objects don't store class information, so if you wished to change the value of a different instance of ABC, you could use the same Field object and just change the first parameter.
If I understand you correctly, your actual question is
Can I call the private constructor in the public constructor?
and nothing really related to setters.
Yes, you can call one constructor from another. In your example code this would look like this:
public ABC() {
this(0, 0); // initialze a and b via the private constructor
}

How does upcasting works in Java?

I was going with the concept of upcasting and downcasting in java, which are also referred as widening and narrowing.
UpCasting (Widening) happens automatically from derived class to base class. i.e if it has a is-a relationship.
Downcasting has to be done explicitly for run time check.
Okay, I got the concept and everything. But, how its working in this case?
public class ObjPair {
Object first;
Object second;
public ObjPair(Object first, Object second) {
this.first = first;
this.second = second;
}
public Object getFirst() {
return first;
}
public Object getSecond() {
return second;
}
public static void main(String[] args) {
ObjPair objPair = new ObjPair("A",2.2); // Goes widning conversion
System.out.println(objPair.getFirst());
System.out.println(objPair.getSecond());
}
}
ObjPair objPair = new ObjPair("A",2.2);
This is going through upcast, String to object and Double to object and the state gets store in the objPair. Great..!!!
Now,when i do objPair.getFirst() and objPair.getSecond(). It returns me A and 2.2.
How does it remember the string and double, widening/upcast is supposed to remember the super-class states and methods.
How is it able to access sub-class types and values?
Casting of object references does not change the object. It simply allows assigning it into a reference of a different type. The object itself remains the same.
In your case, it needs two Object references, it checks compatibility (no problem there), and then the references are set in variables of type Object. The instances themselves do not change. If they have methods that override those of Object, then the overriding methods will be called.
Thus, when it comes to the part where it prints the object, it simply uses String.valueOf, which calls the object's toString() method. The instance accessed from the Object variables is actually a String object, and String overrides toString() to return itself. Double also overrides toString. These overrides are called, as the instance is still an instance of String and an instance of Double. Only the reference is Object.
Note that you also have a cast from double to Double there. This implicit boxing does change the object - it takes a primitive and creates a new Double from it.
If you simply test this code:
public class Main {
public Object first;
public Object second;
public static void main (String[] args){
Main a = new Main();
a.first = new String("foo");
a.second = 5;
System.out.println(a.first.getClass().toString());
}
}
It outputs class java.lang.String. You can see that it isn't stored as an Object. This is achieved through the use of metadata.
Keep in mind: the object in memory is what it is. If you create a Double object, then it is a Double object resembling the numerical value.
The fact that the variable that holds the reference uses a super type doesn't affect the object referenced to at all!
In your example, the auto-boxing create a Double object under the cover, andgetSecond() returns a reference to that Double object.
That is all there is to this.
Okay so here it is, lets take an example. You have a big square box,named Object and another small box. If you keep this small box inside your big box,all the properties of small box and big box are in the big box.
Then inside the small box,there are two sticks,you are labeling the first stick as 'A' and second as '2.2'.
Now the big box can see what is inside of small box. Now for that instant, the small box is having two sticks and labelled as the way they are.
(Rememeber the Object class is always the super class/parent of every classes in java).

Why we do not create object for static method in java?

Sometimes we call className.methodName() without creating object for it, I mean without using syntax as className objectName = new constructor() and then call as object.methodName()
When to use className.methodName()?
When to call method using object as object.methodName()?
Explanation of above two cases with example will be appreciated.
What you're referring to is a static method.
Assume that I have this :
public class A {
public static void foo(){
System.out.println("Hooray! I work!");
}
}
You can now do this anywhere else in any other class :
A.foo();
This is because the method is static, which means that it can be called on by the CLASS.
This means that it doesn't require an instance of that class in order for the method to be called.
However, even though it isn't required, you can still do this :
A a = new A();
a.foo();
But since the method foo() is static, instantiating an object A is not required in order to run the foo() method.
First. When you're create at least one static method of a class, you can use this method without creating an instance of class. This is useful, for example, for the creation of methods with independent logic. For example:
public class Checker {
public static Boolean month(int value) {
return (value >= 1 && value <= 12);
}
}
You need check correct value of month many times. But what to do each time to create the object. It is much effective to use a static method.
Second. When you create the object, the object is stored in the memory and you get a link to it. Then the object can be used for example to save at the list.
Method at this object is specific. You can save class data and do specific operation with member of this class. For example:
List<Animals> animalsList = new ArrayList<>();
Animal animal = new Animal("dog");
int legs = animal.getCountLegs(); // specific function for object
animalList.add(animal); //save if you need
// use list of object
For every class, we have a Object called as class object which is YourClass.class object. static methods are invoked based on meta-data on those objects. For instances of a class, methods are invoked on the actual instances. Both static and non-static methods are present on method area.
There is no different between 1 and 2 point, because in during compilation compiler makes ClassName.staticMethod() instead of instance.staticMethod().
Static methods in java belong to the class (not an instance of it). They use no instance variables and will usually take input from the parameters, perform actions on it, then return some result. Instances methods are associated with objects and, as the name implies, can use instance variables.

confusion in inheritance - value of "this" when printed in constructor

I have the following code.
class Test {
int i = 0;
Test() {
System.out.println(this);
System.out.println(this.i);
}
}
public class Demo extends Test {
int i = 10;
Demo() {
super();
System.out.println("calling super");
System.out.println(this);
System.out.println(this.i);
}
public static void main(String[] args) throws IOException {
Demo d = new Demo();
}
}
O/P : Demo#2e6e1408
0
calling super
Demo#2e6e1408
10
When I execute the program and print the value of "this", in both super class constructor as well as in child class constructor, the value of this (address location) is displayed as childClassName#someValue .. My question is, why dont I get the value of Test i.e, Test#someVal (Super class) when I print value of "this" in the super class.. ASAIK, Super class will also have a place/location in memory, so, why am I not getting Test#someValue in the first SOP...
PS : I know variables are referenced based on the reference type (LHS) and methods are called based on the object type (RHS)..
When I execute the program and print the value of "this", in both super class constructor as well as in child class constructor, the value of this (address location)...
The output of System.out.println(this) with the default Object#toString is not the address of the instance in memory. It's just the name of the class and the instance's hash code, nothing more. From the documentation:
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
It's true that the hashCode documentation says
This is typically implemented by converting the internal address of the object into an integer...
but it also says
...but this implementation technique is not required by the JavaTM programming language.
...and of course the JVM is free to move instances around in memory as necessary, but isn't allowed to change the hashCode.
...why dont I get the value of Test i.e, Test#someVal (Super class) when I print value of "this" in the super class.
There is one instance. That instance is of the subclass. When you do System.out.println(this), it doesn't matter whether you do that in the base class or the subclass, it's still the same object instance you're using. That one object has features it gets from the subclass and also features it inherits from the superclass, but there aren't two separate instances; there's one instance with a combined set of features. super isn't an object reference, although it looks a bit like one; it's a syntax mechanism for specifically asking the compiler to use a feature the instance inherits from the superclass rather than the equivalent feature of the instance (in case they're different).
Demo is a composition of 3 classes: itself, Test and Object. But an instance of Demo is one object, in memory it consists of fields of its super class + its own fields: Test.i + Demo.i (Object has no fields).

Java object reference/scope question

If I have a member variable such as this (declared in the body of a class)
private Dot[] dots=new Dot[numDots];
I loop through all members of this array, and:
1) Pass every Dot object to a function of another class, which:
2) Passes it to yet another function of a 3rd class, if some conditions are met
3) And the 3rd class changes some properties of the Dot object
then when this object is returned to the original/parent class, would those changes to its properties have retained? Or would it be treated like a local variable by the 2nd/3rd functions?
Yes, the changes to the properties are retained. Java is 100% pass-by-value, however, when you pass an object, the "value" passed is truly a pointer to the object. Thus, when you change an object in a method, you're changing the actual object passed in.
That is, if you have the following method, then the calling method will see the changes:
private void updateMyDot(final Dot aDot) {
aDot.dotColor = new Color(255,255,255);
}
but if you do the following, then the calling method will not see the changes.
private void updateMyDot(/* not final */ Dot aDot) {
aDot = new Dot();
aDot.dotColor = new Color(255,255,255);
}
In the second example, the caller will not see any changes and will not see the newly created Dot object.
Objects are passed by [reference value where the value is the reference] (things that inherit from Object), primitive values (int, long, double, etc.) are passed by value.
This means that when a primitive is passed from a caller to method it is copied, whereas with an object a [value of the] reference is passed.
Which in turn means that when an object is mutated by a method the caller sees those changes because it has a reference to the same object.
Conversely when a method mutates a primitive the caller does not see the changes as the method is working on a copy.
[reason for the edits]
If Java had pass by reference then you could do this:
Object x;
x = new Integer(42);
foo(x);
System.out.println(x.getClass()); // pass by reference would have it print out java.lang.Float
where foo is defined as:
void foo(Object o)
{
o = new Float(43);
}
Since Java passes the reference by value o = new Float(43); is allowed - but the value in the caller will remain as the new Integer(42);

Categories