I have 3 Java classes: Class1, Class2 and Class3.
public class Class1 {
ArrayList<Class3> arrayOfObjects;
public Class1() {
if (arrayOfObjects == null){
arrayOfObjects = new ArrayList<Class3>
}
}
}
public class Class2{
public String mName;
public Class2(String name){
this.mName = name;
}
}
public class Class3 extends Class2{
public Class3(String name){
super(name);
}
}
Each instance of Class1 contains an ArrayList of Objects. My problem is, since Strings are immutable, How can i get all of the child objects of Class3 to update their "mName" Variable when it is changed in Class2? I have tried using For loops and looping through everything, which works fine, but as the lists grow larger and larger so does the time involved.
Disclaimer
This is a pretty long winded, very basic tutorial on variable shadowing, scope and static fields. With the edits to your question it doesn't really apply as much as it seemed to originally.
I started writing it though so figured I'd finish, maybe it will be of use to somebody or I'll find somewhere to migrate it to in the future...
You don't need to declare mName in Class3 as it already inherits that field from its parent, Class2.
However, if you want to be able to make changes to any Class2 and see the results in Class3 then you need to know about static variables, variable scope and variable shadowing
Variable Shadowing
If you declare another field in Class3 with the same name as one that the Parent class also has then it 'shadows' or 'hides' the original field as Java will use the first variable with the correct name that it finds.
Consider a very simple base class like this:
public class Parent {
public int myVariable = 5;
public void printMyVariable() {
System.out.println(myVariable);
}
}
Now lets define some children:
public class ChildOne extends Parent {
// nothing here
}
public class ChildTwo extends Parent {
public void printMyVariable() {
System.out.println(myVariable + 2);
}
}
public class ChildThree extends Parent {
public int myVariable = 10;
}
public class ChildFour extends Parent {
public int myVariable = 99;
public void printMyVariable() {
int myVariable = 700;
System.out.println(myVariable);
}
Now lets take a look at how all those different values get read by the JVM:
public static void main (String[] args) {
// make some objects:
Parent parent = new Parent();
ChildOne childOne = new ChildOne();
ChildTwo childTwo = new ChildTwo();
ChildThree childThree = new ChildThree();
// print some values:
parent.printMyVariable();
childOne.printMyVariable();
childTwo.printMyVariable();
childThree.printMyVariable();
childFour.printMyVariable()
}
This will print these values to your console:
5 // original parent class' base value
5 // does not try to override, mask, hide the parent's value or print
7 // printMyVariable() is defined again and the JVM uses
// the first matching method it finds which is in the ChildTwo class
10 // myVariable is defined in the class
// the class variable shadows the parent variable but the method
// still functions as expected
700 // myVariable is shadowed at the class level
// but the print method also declares a myVariable
// it is the method's version that gets found first and used
Static Variables
Now all that is about 'instance variables'. These are variables that have their own unique value for every copy or Object that exists of them.
If you change childOne's myVariable is has no affect on childTwo's value or even another instance of ChileOne that you may have assigned eslewhere.
Were you to define those fields as static however, you are saying that you want to share the same variable and value across all copies or instances of that class.
public class Parent {
public static int myStaticVariable = 25;
}
public class ChildOne extends Parent {
// nada
}
public class ChildTwo extends Parent {
public static int myStaticVariable = 99;
}
And if we now poke at the static variables:
public static void main (String[] args) {
// a few classes
Parent parent = new Parent();
ChildOne childOne = new ChildOne();
ChildOne childOneCopy = new childOne();
ChildTwo childTwo = new childTwo();
// take a peek at the values
System.out.println(parent.myStaticVariable):
System,out.println(childOne.myStaticVariable);
System,out.println(childTwo.myStaticVariable);
// let's change the value
parent.myStaticVariable = 66;
System.out.println(parent.myStaticVariable):
System,out.println(childOne.myStaticVariable);
System,out.println(childTwo.myStaticVariable);
// and the two copies of ChildOne?
childOne.myStaticVariable = 123;
System,out.println(childOneCopy.myStaticVariable);
childOneCopy.myStaticVariable = 456;
System,out.println(childOne.myStaticVariable);
}
And these results:
25 // no surprise here
25 // ChildOne does not define its own variable so it uses the Parent's
99 // As in the earlier example the variable is getting shadowed
66 // we just changed the variable value so this looks normal
66 // even though it was the Parent's variable we changed
// the Child shares it too
99 // Since ChildTwo's variable is shadowing the Parent value it has not changed.
123 // 123? But we changed the original ChildOne...
456 // Again we modified the other object but since they share
// the same static variable; changing one also changes the other.
Create a wrapper object for the String
public class MutableString
{
private String value;
public MutableString(String value)
{
this.value = value
}
public void set(String value)
{
this.value = value;
}
}
In your code, instead of storing strings, Class3 and Class2 would store references to objects of type MutableString
Related
Today a fellow learner came up with an interesting query. We know that this keyword is used to refer to the current object. But I could not explain to him how this keyword behaves as seen in the following snippet. I know what inheritance is: allows access to parent class variables and methods. But are they copied into the memory area of child instance?, because I am able to use this keyword to access the parent class property.
I was able to refer to parent class variable. I searched and found that nothing gets copied virtually to child class, but why the following behavior happens? Please explain this case of using this.
class Parent {
int a=10;
}
public class Child extends Parent{
void m1(){
System.out.println(a);
System.out.println(this.a);
System.out.println(super.a);
}
public static void main(String[] args){
new Child().m1();
}
}
https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
The property a is inherited by Child. Therefore, you can use this.a in child to reference it.
Where was the problem supposed to be?
I searched and found that nothing gets copied virtually to child class
You have the wrong example to illustrate that statement.
The way to understand that is (roughly): "instance variables are not overridden when re-declared in subclasses, so you can't declare an instance as Parent and expect to get Child.a if the instance was created with new Child()". Here's an example of the problematic case:
class Parent {
int a = 10;
}
public class Child extends Parent{
int a = 12; //not overridden
public static void main(String[] args){
Parent child = new Child();
System.out.println(child.a); //This will print 10, not 12
}
}
System.out.println(child.a); will print 10 because variables instance fields don't get overridden. You get the value based on the declared type (Parent in this case)
When you instantiate a class Child it contains all members of itself and of Parent. However, private members of Parent are not accessible from Child:
class Parent {
private int p = 10;
}
public class Child extends Parent{
void m1(){
System.out.println(p); // compilation error
}
}
Another interesting case is when one instance of Parent tries to access a private field of another instance of Parent. What do you think happens?
public class Parent {
private int p = 11;
public boolean same(Parent other) {
return other.p == p;
}
}
You might think other.p will result in a compilation error since p is a private field. However, since privacy does not pertain to object instances, but to classes. So all private fields in Parent are visible within all Parent instances, so this works!
Consider below Code:
this is a reference variable which will point to the current object.
super is used to refer to Parent's property in case you have created
the same in the child.
class Product{
String color;
public Product() {
color = "Black";
}
}
class Mobile extends Product{
String color;
Mobile(){
color = "White";
}
void showMobileData(){
System.out.println("this hashCode is "+this.hashCode());
System.out.println("super hashCode is: "+super.hashCode());
System.out.println("color is: "+color);
System.out.println("this.color is: "+this.color);
System.out.println("super.color is: "+super.color);
}
}
public class Test {
public static void main(String[] args) {
//new Mobile().showMobileData();
Mobile mRef = new Mobile();
System.out.println("mRef HashCode: "+mRef.hashCode());
mRef.showMobileData();
}
}
I want to be able to access a non static variables and non static methods from another class without creating a new object.
In the existing code of our project, its creating class instantiation issue due to new object creation.
See thew below creation both classes and their variables are non static.
Note : We have kept the variables and methods non static to support parallel tests execution using Test NG suite. Means same code must support multiple execution at a time. Hence can't alter the declaration to static as static variables can't support to execute in parallel.
Class 1
public class DataBaseQueries {
// non static Class variable
public int g_intDBNumericValue;
// non-static method
public Integer ecDBGetNumericValue(String Query){
Code logic to get numeric value from Data base.......
// returing extracted numeric value
return g_intDBNumericValue;
}
}
//Class 2
//Here inherited class Configuration is another Class say Class3 which is required and we don't have to extend Class 1 i.e., DataBaseQueries
public class CommonActions extends Configuration{
// non static Class variable
public int g_intSavedValueValue;
// non-static method to verify saved value
public Integer ecSavedvalue{
g_intSavedValueValue=ecDBGetNumericValue("Select value from tableA where ID =100")
}
}
public class Configuration{
// non static Class variables
public int g_int1....;
// non-static methods
public Integer ecSample{
g_intSavedValueValue=ecDBGetNumericValue("Select value from tableA where ID =100")
}
Try extending class, here is example
public class SuperClass {
public int getNb() {
//specify what must happen
return 1;
}
public int getNb2() {
//specify what must happen
return 2;
}
}
public class SubClass extends SuperClass {
//you can override the implementation
#Override
public int getNb2() {
return 3;
}
}
Subclass s = new SubClass();
s.getNb(); //returns 1
s.getNb2(); //returns 3
SuperClass sup = new SuperClass();
sup.getNb(); //returns 1
sup.getNb2(); //returns 2
I want to consult an issue about Java field variable inheritance. Here is the code segment:
//parent
public class Parent {
protected int a = 0;
}
//son
public class Son extends Parent{
public void demo(){
a = 1;
System.out.println(super.a);
}
public static void main(String[] args){
Son son = new Son();
son.demo();
}
}
output:
1
expect:
0
In my code the child will inherit field variable a, and we called it sonA and the field variable a of parent called parentA.
My question is whether sonA and parentA the same one (e.g there address is 0x1234)? or they represent two different variable (e.g. one address 0x1234 another 0x5678)?
They share the same address, however you did overwrite the default value 0 with 1 so it's correct behaviour. Let's check that:
Son son = new Son();
Parent parent = new Parent();
Field fieldAParent = parent.getClass().getDeclaredField("a");
Field fieldA = son.getClass().getDeclaredField("a");
You'll get an exception on the last line, because class son doesn't contain field a
It's the same one, because Son doesn't have an a of its own. If you introduce one, you'll hide Parent's a and then you'll see the behaviour you're expecting:
//parent
public class Parent {
protected int a = 0;
}
//son
public class Son extends Parent{
int a = 0; // this hides the Parent field
public void demo(){
a = 1; // this accesses the Son field
System.out.println(super.a); // this accesses the Parent field explicitly
}
public static void main(String[] args){
Son son = new Son();
son.demo();
}
}
However, this would generally not be a recommended practice, as it could lead to a lot of confusion.
I observer the behaviour that when we call a variable from a polymorphic object then it calls the parent's variable but when we call a method with the same polymorphic object then it calls child's method.Why this is the behaviour of polymorphism in Java? Why doesn't Java handle polymorphic variables and methods in same way?
class Parent{
int age =10;
public void showAge(){
System.out.println("Parent Age:"+age);
}
}
class ChildOne extends Parent{
int age = 20;
public void showAge(){
System.out.println("child one age:"+age);
}
}
class ChildTwo extends Parent{
int age = 30;
public void showAge(){
System.out.println("Child Two Age:"+age);
}
}
public class Test{
public static void main(String[] args) {
Parent parentChildOne = new ChildOne();
System.out.println("parentChildOne.age: "+parentChildOne.age);
parentChildOne.showAge();
Parent parentChildTwo = new ChildTwo();
System.out.println("parentChildTwo.age: "+parentChildTwo.age);
parentChildTwo.showAge();
}
}
Here is the output:
parentChildOne.age: 10
child one age:20
parentChildTwo.age: 10
Child Two Age:30
First of all keep in mind that Your variables are not polymorphic and the next climax thing is your this point
Parent parentChildOne = new ChildOne();
Parent parentChildTwo = new ChildTwo();
See when you are trying to call a method using Parent parentChildOne then it should call the child's method because it is overrided and according to polymorphism it should be called. Now see again Parent parentChildOne same object for variables , now here is nothing with polymorphism but jvm is dealing it now with the concept of shadowingSo thats why they both are showing their real behavioursPlease follow this tutorial of shadowing in java
Variables are not polymorphic in Java.
Instead, instance variables in child classes shadow instance variables with the same name in the parent class.
See also Can parent and child class in Java have same instance variable?
parentChildOne and parentChildTwo are of type Parent. So you are printing age of the Parent. Same happes with the showAge() method but the value of age is shadowed by the child classes.
Please see the comments into,
class Parent{
int age =10;
public void showAge(){
System.out.println("Parent Age:"+age);
}
}
class ChildOne extends Parent{
//when you extends Parent the inherited members are like
//and initialized into the default constructor
// int super.age =10;
int age = 20;
public void showAge(){
System.out.println("child one age:"+age);
}
}
class ChildTwo extends Parent{
//when you extends Parent the inherited members are like
//and initialized into the default constructor
// int super.age =10;
int age = 30;
public void showAge(){
System.out.println("Child Two Age:"+age);
}
}
public class Test{
public static void main(String[] args) {
Parent parentChildOne = new ChildOne();
// when we call like this, goes to the parent type of the variable instead of object.
System.out.println("parentChildOne.age: "+parentChildOne.age);
parentChildOne.showAge();
Parent parentChildTwo = new ChildTwo();
// when we call like this, goes to the parent type of the variable instead of object.
System.out.println("parentChildTwo.age: "+parentChildTwo.age);
parentChildTwo.showAge();
}
}
Executed Python code:
class Test(object):
item = 0
def __init__(self):
print(self.item)
def test(self):
print(self.item)
class Subclass(Test):
item = 1
s = Subclass()
s.test()
gives:
1
1
Executed analogical Java code:
public class Test {
int item = 0;
Test(){
System.out.println(this.item);
}
void test(){
System.out.println(this.item);
}
public static void main(String[] args){
Subclass s = new Subclass();
s.test();
}
}
class Subclass extends Test {
int item = 1;
}
gives:
0
0
Apparently, Java method inherited from base class (Test) uses also base class' member variables. Python method uses the member variable of derived class (Subclass).
The question: Is there any way to achieve the same or at least similar behaviour in Java like in Python?
Objects in Python are pretty much just like Dictionaries in Python. You can think of each instance of Test and Subclass as a Dictionary that is updated by the __init__ code and assignments in the body of the class you declare. You can picture the code you wrote working something like this:
class Test(object):
item = 0 # self['item'] = 0
def __init__(self):
print(self.item) # print(self['item'])
def test(self):
print(self.item) # print(self['item'])
class Subclass(Test):
item = 1 # self['item'] = 1
s = Subclass() # Test.__init__({})
s.test()
Python uses duck-typing, so item is just some property of whatever you happen to have an instance of. Notice that you don't ever actually have to declare item—you just assign a value. This is why you're able to "override" the value in the sub-class—because you're actually just overwriting the old value of the same field. So in the example you gave, the item in Subclass isn't actually overriding the item in Test; rather, they are the same field in a Python object instance.
In Java fields actually belong to specific classes. Notice how in your code you actually have two declarations of the field int item: one in Test and one in Subclass. When you re-declare the int item in Subclass you are actually shadowing the original field. See Java in a Nutshell: 3.4.5. Shadowing Superclass Fields for more info.
I'm not sure exactly what you're trying to do with your example, but this is a more idiomatic Java approach:
public class Test {
private int item;
public Test() {
this(0); // Default to 0
}
public Test(int item) {
setItem(item);
test();
}
public void test() {
System.out.println(getItem());
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.test();
}
public void setItem(int item) {
this.item = item;
}
public int getItem() {
return item;
}
}
class Subclass extends Test {
public Subclass() {
super(1); // Default to 1
}
}
Notice how the value of item is set via a constructor argument rather than by simple assignment. Also notice how item is private and that there is now a getter and setter method to access it. This is more Java-style encapsulation.
That seems like a lot of code, but a good IDE (such as Eclipse or IntelliJ) will auto-generate a lot of it for you. I still think it's a lot of boiler-plate though, which is why I prefer Scala—but that's a whole different discussion.
Edit:
My post grew so long that I lost track of why I wanted to introduce getters and setters. The point is that by encapsulating access to the field you're able to do something more like what you had in Python:
public class Test {
// Same as above . . .
}
class Subclass extends Test {
private int subclassItem = 1;
public int getItem() {
return subclassItem;
}
public void setItem(int item) {
this.subclassItem = item;
}
}
Now the item field has effectively been overridden since all access to it is done through the getter and setter, and those have been overridden to point at the new field. However, this still results in 0 1 in the output rather than the 1 1 you were expecting.
This odd behavior stems from the fact that you're printing from within the constructor—meaning the object hasn't actually been fully initialized yet. This is especially dangerous if a this reference is passed outside the constructor during construction because it can result in outside code accessing an incomplete object.
You could overload the superclass constructor to initialise the field item in Test to 0:
public class Test {
int item = 0;
Test(){
System.out.println(this.item);
}
Test(int item) {
this.item = item;
System.out.println(this.item);
}
void test(){
System.out.println(this.item);
}
public static void main(String[] args){
Subclass s = new Subclass();
s.test();
}
}
class Subclass extends Test {
public Subclass() {
super(1);
}
}
Use an initializer instead of redeclaring the fields:
public class Test {
int item = 0;
...
}
public class Subclass extends Test {
{
item = 1;
}
}
Note: depending on your package structure, you might want to declare item as protected.