I have a class with multiple subclasses:
class A {
static int i = 5;
}
class B extends A{
static int i = 6;
}
class C extends A {
static int i = 7;
}
I'm trying to write a comparator that takes two A's and compares them based on their values of i. I'm stuck at:
public int compare(A a1, A a2) {
}
Neither a1.i nor a1.class.getField("i").getInt(null); work.
How can I get the value of the static field from the object?
a1.i
Because a1 is declared a A, it is equivalent to A.i. The compiler should tell you about that with a warning. Most IDE will do that to and give a little message about what to do about it.
a1.class.getField("i").getInt(null);
Can't work because class is static.
You can use
a1.getClass().getDeclaredField("i").getInt(null);
getClass is an instance method to get the class of an object. getDeclaredField will return all fields, while getField will only return the public ones.
Related
I come to you with a simple OOP question.
Let's say there are three classes - A, B and C.
B and C both inherit a static variable from A. Let's also say that A defines the value of this variable as being 0.
Let's say that both B and C modify the value of this static variable.
My question is this - since static variables remain constant across members of the same class, does this mean that setting the value of a variable of a superclass from a subclass will have no effect on the value of the super class?
In other words, if we change the value of B's variable to 1, that value will only be 1 for objects of class B and not C or A?
A static field only belongs to one class and is not inherited by its sub-classes
Here you can find simple java implementation for your problem.
The results can interpret solution.
class A {
static int variable = 0;
}
class B extends A{
}
class C extends A{
}
public class Runclass {
public static void main(String arg[]){
A a = new A();
System.out.println("A "+a.variable);
B b = new B();
System.out.println("B "+b.variable);
C c = new C();
System.out.println("C "+c.variable);
b.variable=1;
System.out.println("After modifying B "+b.variable);
System.out.println(" A "+a.variable);
}
}
Output:
A 0
B 0
C 0
After modifying B 1
A 1
static doesn't mean constant. final means that you can't change the value.You can reach the variable in the superclass A and change it, using this code for example in B: A.someVariable=1;After this, you will see the value 1 from C, B and A too, if you use the superclass A variable (A.someVariable).I give you a code example:
package teszt;
class A {
static int statValami=0;
}
package teszt;
class B extends A{
void writeOut(){
A.statValami=1;
System.out.println(statValami);
}
}
package teszt;
class C extends A {
void writeOut(){
A.statValami=100;
System.out.println(statValami);
}
}
package teszt;
class Over {
public static void main(String args[]){
new B().writeOut();
new C().writeOut();
System.out.println(A.statValami);
}
}
OUTPUT is:1100100
As I've learned, in Java method overloading, we use same name for all overloaded methods. And also, their return type is not a matter. But what happens if we use same method as static and non-static form, as in the below example? Can we consider this method overloading?
class Adder {
static int add(int a, int b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
}
class Test {
public static void main(String[] args) {
Adder a1 = new Adder();
System.out.println(Adder.add(11, 11));
System.out.println(a1.add(11, 11, 51));
}
}
I read some articles, but they didn't clarify my question.
Use of keyword static doesn't make a difference in method overloading.
Your code compiles because the method signature of both add() methods are different (2 params vs 3 params).
However, if you were to write something like this, then it would result in a compilation error.
class Adder {
static int add(int a, int b) {
return a + b;
}
int add(int a, int b) {
return a + b;
}
}
Yes they can overload each other. See this JLS :
If two methods of a class (whether both declared in the same class, or
both inherited by a class, or one declared and one inherited) have the
same name but signatures that are not override-equivalent, then the
method name is said to be overloaded.
See this Thread .
U have two methods one is static and another is non static.. so this is not overloading... Because both methods get stored in memory saperately...
Consider class A
class A {
int i;
int j;
int k;
}
and here is the class B
class B {
int a;
int b;
int c;
}
I was wondering if java has any such ting which allows to write/define our own custom casting logic.
For e.g.
to cast class B's object into class A's object where
i -> a // i pointing to value of a
j -> b // j pointing to value of b
k -> c // k pointing to value of c
(I can customize the logic to whatever i wish)
I have a few heavy weight objects to "cast" into some other classes to use and i do not want to write a converter method for this.
(casting operates only on the object in consideration and does not create another object)
any thoughts/suggestions for this ?
Thanks in Anticipation !
You can use the frameworks like ModelMapper (documentation) to define your maping logic and use it to convert object from one type to object of another type. E.g. this is how the configuration would be:
//Model Classes
class A{
int a;
}
class B{
int d;
}
//Mappings
PropertyMap<A, B> map = new PropertyMap<A, B>() {
protected void configure() {
map(source.a, destination.d);
}
};
//Test Program
public static void main(String[] args) throws Exception {
ModelMapper mapper = new ModelMapper();
PropertyMap<A, B> map = new PropertyMap<A, B>() {
protected void configure() {
map(source.a, destination.d);
}
};
mapper.addMappings(map);
A a = new A();
a.a = 10;
B b = mapper.map(a, B.class);
System.out.println(b.d);
}
This defeats the safety purposes of Java for two reasons.
Let's consider an updated version of your class code.
class A {
int i;
int j;
int k;
int l;
}
class B {
int a;
int b;
int c;
}
Now imagine what would happen if you did something like this, assuming the classes were written right above: (Warning:code will not compile)
public static void main(String[] args)
{
B classTwo = new B();
A classOne = (A) classTwo;
classOne.l = 3; // <-- what would happen?
}
As you can see, it won't work, because creating an instance of B will not allocate the variabls properly. This is why Java does not permit casting like that.
What Java does permit is converting between superclasses and subclasses.
For example:
class Fruit {
int i;
}
class Apple extends Fruit {
int j;
}
And now inside the main function:
Fruit f = new Fruit();
Apple a = (Apple)f; // this compiles, but will raise a ClassCastException
You'll ask, why does it raise a ClassCastException? Apple extends Fruit.
Yes, Apple extends Fruit. But, Fruit does not allocate memory for the j variable.
What is allowed is the other way around, casting an Apple to a Fruit, because all Apples have properties of Fruits (even in real life).
If you want to use your idea of casting, you could try an interface.
interface C {
public int getVarOne();
public int getVarTwo();
// NO variables here, only functions
}
Any class which implements (not extends) an interface must also implement all of the methods defined in it.
Once you've implemented the interface, the behavior is similar to casting to a superclass. There are also other uses for interfaces, but that is beyond the scope of this question.
No. There's no such thing as unions known from C. You cannot modify the memory directly in JVM. That's the point of Java. It sacrifices some potential for tricks, but in the end the code tends to be less buggy and easier to maintain than the code written in C.
If your concern is memory consumption caused by copying, you can convert A and B into interfaces. The interfaces should expose getters and setters. For example: int getI() and int getA(). Then you can introduce a class implementing both of them.
The indirection caused by the interface calls will have some performance cost, but in many cases, it won't be noticable.
I'm learning Java and I'm doing this exercise and I have to say what the main method prints. Its goal is to better understand Java inheritance.
interface X extends Remote{
A m(B bb) throws RemoteException;
}
class A implements Serializable{
int a;
A m(A aa){
aa.a = 3;
System.out.println("A.m");
return aa;
}
}
class B extends A{
int b;
A m(B bb){
bb.b = 7;
System.out.println("B.m");
return bb;
}
}
class C extends A implements X{
public B m(B bb){
if(bb.b == 7) bb.b = 9; else bb.b = 1;
System.out.println("C.m");
return bb;
}
}
Now I have a main method in which I call:
X x = new C();
B b = new B();
(x.m(b)).m(b); // prints C.m() A.m()
The third line of my main method, prints "C.m() A.m()" but I don't understand why it prints A.m(). The x.m(b) returns an object that has both static and dynamic type == B; on this object it is invoked m(b) method; so why it is not called the m() method of B class?
I've seen that the m() mehtod in B class is not an overriding of the m() method in A class because they have different explicit parameter.
thanks in advance
b in an instance of B, which extends A. As such, B has 2 m methods.
To know which is called, what is important is the type of the object on which the method is called.
(x.m(b))
is the result of the call to the m method from the X interface, because the declaring type of x is X.
Therefore (x.m(b)) is an object of type A (even though the actual implementation is a B).
This being a type A, the m method from the A class is called.
If you change the names of the methods, it will become clearer that the m methods from A and B are really different objects.
Your mistake is assuming that
The x.m(b) returns an object that has both static and dynamic type == B;
Which is wrong, because x is declared of type X, making the result of x.m a type A.
In the following code, I don't understand why when a1.k() is called, this.x in class C returns 100 instead of 1. My understanding is that this refers to the current object, but the static type of the current variable a1 is A. So shouldn't this.x returns 1, which is the variable for A type?
I mean a1.x should return 1, right? Many thanks!
class A {
public int x = 1;
public String k() { return "A" + this.x; }
}
class B extends A {
public int x = 10;
...
}
class C extends B {
public int x = 100;
public String k() { return "C" + this.x; }
}
class TestABC {
public static void main(String[] args) {
A a1 = new C();
C c1 = new C();
System.out.println(a1.k());
}
}
When you call a1.k() you dynamically dispatch to the k method that is defined by the actual object whose reference is in a1. In this case, it is a C not an A or a B, and hence the k method is the override defined in C.
The static type (of a1 for example) is used for static resolution; e.g. resolving static methods, overload signatures, and fields. But for instance method invocation, the ultimate selection of the method to be invoked is dynamic.
I know the k() in class C should be called, instead of the k() in class A. But why this.x returns 100? I thought the instance variable is bounded to the static type.
Well it is. But it is the static type that determines which x is used by this.x in the k() call is the static type of this in the C.k method body!
This feature is called Dynamic Polymorphism. The methods being called is not dependent of type of its declaration but by the type being assigned to it (definition).
For this the classes must inherit and also override the methods in the parent class.
Here C,B extends A and overrides the method k;
if you try to call some C specific methods or variable it will throw error. (Since A doesn't know about that)
A is holding reference to C (pointing to C)
a1.k is actually C constructed Object and its new C().k() where x is 100 in C.
class Base{
int x=10;
public int getx(){return x;}
}
class Sub extends Base{
int x=100;
public int getx(){return x;}
}
class Test
{
public static void main (String[] args)
{
Base b = new Base();
Sub s = new Sub();
System.out.println("sub: getx:"+s.getx()+" .x:"+s.x+" Class: "+s.getClass().getName());
System.out.println("base: getx:"+b.getx()+" .x:"+b.x+" Class: "+b.getClass().getName());
Base btoS = new Sub();
System.out.println("btos: getx"+btoS.getx()+" .x:"+btoS.x+" Class: "+btoS.getClass().getName());
}
}
Results in
sub: getx:100 .x:100 Class: Sub
base: getx:10 .x:10 Class: Base
btos: getx100 .x:10 Class: Sub
Since you declare a1 as new C(), a1 will be seen as an object instance of class C, which overrides the fields of its parent class B and A. So why you would do things like A a1 = new C(); (or you might see a lot of such implementation), there is a recommendation saying "programming to interface rather than the actual implementation.", and I think this explains better.