interface I {
int element = 10;
}
class A implements I
{
int element = 2;
public static void main (String[] args) throws java.lang.Exception
{
A a = new A();
System.out.println(a.element);
I i = (I)a;
System.out.println(a.element + " " + i.element);
}
}
Output:
2
2 10
Even after I cast object of type A to I the value of element in I doesn't change.
If I is a class and A extends I then I can change the value of element in A and cast it to I such that i.element has modified value (in this case A does not have element member)
So does the concept of casting exist in such cases? (class object cast to interface type)
Even after I cast object of type A to I the value of element in I doesn't change.
I i = (I)a;
That line shows that the instance of a pointing to the type I. Which means, you are accessing the variables from type I and telling that execute the methods from class a.
Polymorphism strictly for methods. There is no polymorphism on variables.
Here is the example :
public interface TestInterface {
int testvarInterface = 0;
}
public class TestParent {
int testvarFromParent = 0;
}
public class TestClass extends TestParent implements TestInterface {
public static void main(String[] args) {
TestClass s = new TestClass();
System.out.println(s.testvarInterface);
TestInterface in = (TestInterface) s;
in.testvarInterface = 15; // ERROR: The final field
// TestInterface.testvar
// cannot be
// assigned
System.out.println(s.testvarFromParent); // Points to LHS
TestParent parent = (TestParent) s;
parent.testvarFromParent = 20;
System.out.println(parent.testvarFromParent);
}
}
After all you have to remember that the variables points to LHS (naive, bit still), where as in your interface case, since it is public and static final you cannot modify it.
You cannot overwrite the value of I.element in implementing classes because variables defined in interfaces are static final. Being static they are not instance variables. And being final they cannot be overwritten.
So A.element is hiding I.element when you are working with a reference of type A. But not when you cast the A instance to its interface type I.
Related
Can someone explain why the output is 10 and not 20?
Why does the object refers to the value of the parent class instead of the class it is assigned to?
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
}
}
The instance you're creating is of type A, so since both variables have the same name, you'll get the superclass' one, if you want B's you should do
B b = new B()
System.out.println(b.i)
You shouldn't use variables of the same name like that in between superclasses and subclasses, gets very confusing and kinda defeats the purpose of inheriting.
In Java, methods are overridden not variables. So variables belong to their owner classes. a is a reference of type A that point to an object of type B but remains of type A.
To call the i of B, you have to cast a to B.
A a = new B();
System.out.println(((B)a).i);
Can someone explain why the output is 10 and not 20?
Since the value of i is defined in the class A and is NOT overridden/re-assigned by the definition of class B as you might just be assuming. Adding a custom constructor could clarify your doubts further of what you might be intending to do:
class A {
int i = 10;
}
class B extends A {
public B() {
this.i = 20;
}
}
A a = new B();
System.out.println(a.i); // would now print 20
Declaring the same variable i in class B would have its own scope and does not inherit from the class A.
Variables can not be overridden in Java as they are resolved at compile-time; You can use super to set its values,
class A {
int i = 10;
}
class B extends A {
int i = 20;
public B() {
super();
super.i = i;
}
}
A a = new B();
System.out.println(a.i); //20
This question already has answers here:
Is there a way to override class variables in Java?
(17 answers)
Overriding member variables in Java ( Variable Hiding)
(13 answers)
Closed 5 years ago.
I am not able to understand the following output.
I don't know why the output is 10, I think the line A a = new B() creates a new instance of class B, I think the result should be 20
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
}
}
Why this works like this .. please explain.
First, see Hiding Fields (emphasis added)
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different
In other words, this isn't "inheritance" since you're actually hiding A's i behind B's i, and you are using a reference object of A, so you are getting its fields. If you did B b = new B(), you would see 20, as expected.
If you expect true overrides, try using methods.
class A {
public int get() {
return 10;
}
}
class B extends A {
#Override
public int get() {
return 20;
}
}
See
A a = new B();
System.out.print(a.get()); // 20
If you really want to see both at once, see this example.
class A {
int i = 10;
}
class B extends A {
int i = 20;
#Override
public String toString() {
return String.format("super: %d; this: %d", super.i, this.i);
}
}
And
A a = new B();
System.out.print(a); // super: 10; this: 20
In java you cannot override an instance variable. The output you are getting is expected. In Java you can only override instance methods and not instance variables.
If you want 20 as an output you may use getter methods over those instance variables.
class A {
int i = 10;
int getI() {
return i;
}
}
class B extends A {
int i = 20;
int getI() {
return i;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getI());
}
}
Polymorphism is not applicable for fields in Java.Evaluating Variables decision is taken at compile time so always base class variables are accessed.
Because you define 2 variables: one in the subclass B, and one with the same name in superclass A.
A a = new B();
a.i; // refers to A.i
If you cast the A to a B, it will access B.i:
System.out.println(((B)a).i);
I think you need to use 1 variable:
class A {
int i;
public A() {
i = 10;
}
}
class B extends A {
public B() {
i = 20;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i); // will print 20
}
Member variable i is already defined in class A.
In order to achieve what you are looking for, change the class B as shown below:
class B extends A {
public B() {
i = 20;
}
}
After reading through the Generics info I am attempting a simple sample and encountering the following error.
MyClass.java:32: error: cannot find symbol
System.out.println("X = " + temp.x);
^
symbol: variable x
location: variable temp of type T
where T is a type-variable:
T extends Object declared in method tryThis(T)
1 error
Without the reference to "temp.x" it compiles which leads me to believe the definition is correct but possibly the way the variable is referenced is the issue. Or it could be the actual implementation is wrong. Not sure.
The main class has a method which can be called by either of the 2 inner classes. When called, the method attempts to access the variable specific to the inner class that called it.
public class MyClass {
public class InnerClass1 {
int x = 100;
public void runThis() {
tryThis(this);
return;
}
}
public class InnerClass2 {
int x = 200;
public void runThis() {
tryThis(this);
return;
}
}
public static void main(String[] args) {
MyClass x = new MyClass();
}
private <T> void tryThis(T temp) {
System.out.println("X = " + temp.x);
}
}
symbol: variable x
location: variable temp of type T
where T is a type-variable:
T extends Object declared in method tryThis(T)
^^^^^^^^^^^^^^^^
Without further specification, e.g. <T extends InnerClass1>, the only thing that is known about T within that method is that it extends Object, and for Object, the attribute x is not defined.
Maybe you should define a common super-class for those two classes, and declare x in that super-class.
In order to get the value x from each class dynamically, you can define a common interface or abstract class for InnerClass1 and InnerClass2 to implement or extend. This allows the inheritance of methods and variables. Seeing that both holds a value of type T, let us create an interface called ValueHolder<T>:
interface ValueHolder<T> {
public T getValue();
}
Both the InnerClass1 and InnerClass2 will need to implement this interface:
public class InnerClass1 implements ValueHolder<Integer> {
private int x = 100;
#Override
public Integer getValue() {
return this.x;
}
}
public class InnerClass2 implements ValueHolder<String> {
public String x = "200";
#Override
public String getValue() {
return this.x;
}
}
As you can see, InnerClass1 implements ValueHolder<Integer>, meaning the inherited getValue methods return type will be Integer. The same goes for InnerClass2, which implements ValueHolder<String>.
Change your tryThis as follows:
private <T> void tryThis(ValueHolder<T> temp) {
System.out.println("Value = " + temp.getValue());
}
Now each value can be printed like this:
Generics g = new Generics();
g.tryThis(new InnerClass1());
g.tryThis(new InnerClass2());
Output:
X = 100
X = 200
T in
private <T> void tryThis(T temp)</code>
is just a placeholder for any class. The compiler knows nothing more about it, so it knows nothing about the symbol x as well.
To accomplish what you are trying to do, you would need something like this:
public class Generics {
abstract class MyClass {
int x;
}
public class InnerClass1 extends MyClass {
InnerClass1() {
super.x = 100;
}
public void runThis() {
tryThis(this);
return;
}
}
public class InnerClass2 extends MyClass {
InnerClass2() {
super.x = 200;
}
public void runThis() {
tryThis(this);
return;
}
}
public static void main(String[] args) {
Generics x = new Generics();
x.new InnerClass1().runThis();
x.new InnerClass2().runThis();
}
private <T extends MyClass> void tryThis(T temp) {
System.out.println("X = " + temp.x);
}
}
However, you would not need Generics for this specific case:
private void tryThis2(MyClass temp) {
System.out.println("X = " + temp.x);
}
would accomplish the same.
Generics are very complex, although they look easy to use.
I tried this:
class protectedfinal
{
static abstract class A
{
protected final Object a;
}
static class B extends A
{
{ a = new Integer(42); }
}
public static void main (String[] args)
{
B b = new B();
}
}
But I got this error:
protectedfinal.java:12: error: cannot assign a value to final variable a
{ a = new Integer(42); }
^
1 error
How to work around this problem?
Some people suggested here to use a constructor but this works only in some cases. It works for most objects but it is not possible to reference the object itself from within the constructor.
static abstract class X
{
protected final Object x;
X (Object x) { this.x = x; }
}
static class Y extends X
{
Y () { super (new Integer(42)); }
}
static class Z extends X
{
Z () { super (this); }
}
This is the error:
protectedfinal.java:28: error: cannot reference this before supertype constructor has been called
Z () { super (this); }
^
One could argue that it does not make much sense to store this kind of reference, because this exists already. That is right but this is a general problem which occurs with any use of this in the constructor. It is not possible to pass this to any other object to store it in the final variable.
static class Z extends X
{
Z () { super (new Any (this)); }
}
So how can I write an abstract class, which forces all child classes to have a final member which gets initialized in the child?
You have to initialize A.a in its constructor. Subclasses will use super() to pass initializer to A.a.
class protectedfinal {
static abstract class A {
protected final Object a;
protected A(Object a) {
this.a = a;
}
}
static class B extends A {
B() {
super(new Integer(42));
}
}
public static void main (String[] args) {
B b = new B();
}
}
You cannot use this until superclass constructors were called, because at this stage the object is not initialized, even Object constructor hasn't run at this point, therefore calling any instance methods would lead to unpredictable results.
In your case, you have to resolve circular reference with Z class in another way:
Z () { super (new Any (this)); }
Either use a non-final field or change class hierarchy. Your workaround with instance method super(new Any(a())); would not work for the same reason: you cannot call instance methods until superclass constructors were run.
In my personal oppinion, your problems hints towards a flaw in design.
But to answer your question. If absolutly necessary, you can change final fields in java using reflection.
And if everything fails, you can still utilize sun.misc.unsafe.
But I strongly discourage you from doing so, since it potentially kills your vm.
My work around so far is to use methods instead of final members:
class protectedfinal
{
static abstract class AA
{
protected abstract Object a();
}
static class BB extends AA
{
#Override
protected Object a() { return this; }
}
public static void main (String[] args)
{
AA a = new BB();
System.out.println (a.a());
}
}
But I would like to use final members, because I think accessing a final member is faster than calling a method. Is there any chance to implement it with final members?
Why does below code prints "1" ?
class A {
int x = 1;
}
class B extends A {
int x = 2;
}
class Base {
A getObject() {
System.out.println("Base");
return new B();
}
}
public class CovariantReturn extends Base {
B getObject() {
System.out.println("CovariantReturn");
return new B();
}
/**
* #param args
*/
public static void main(String[] args) {
Base test = new CovariantReturn();
System.out.println(test.getObject() instanceof B);
System.out.println(test.getObject().x);
}
}
Because you are referring to fields, which are not affected by polymorphism. If you instead used getX(), it would've returned 2.
What you are asking is, the value of field x defined in class A (because Base.getObject() returns A). Even though CovariantReturn overrides the method to return B, you are not referring to your object as CovariantReturn.
To expand a bit on how fields are not affected by polymorphism - field access is realized at compile time, so whatever the compiler sees, that's what's accessed. In your case the method defines to return A and so A.x is accessed. On the other hands methods are invoked based on the runtime type. So even if you define to return A but return an instance of B, the method you invoke will be invoked on B.
#kris979 Though you are returning B, i think what makes the difference is that the return type is of A. Hence value of x in A i.e. 1 is printed.
As Bozho pointed out - instance variable are never affected by polymorphism. Let me give you a quick small example.
class Base {
int i = 1;
void method() {
System.out.println("in base");
}
}
class Sub extends Base {
int i = 2;
void method() {
System.out.println("in sub");
}
}
public class Test {
public static void main(String[] args) {
Base obj = new Sub();
obj.method();
System.out.println(obj.i);
}
}
This code will print - in sub and 1