This question already has answers here:
What is the difference between a.getClass() and A.class in Java?
(7 answers)
Closed 7 years ago.
MyClass.class and MyClass.getClass() both seem to return a java.lang.Class. Is there a subtle distinction or can they be used interchangeably? Also, is MyClass.class a public property of the superclass Class class? (I know this exists but can't seem to find any mention of it in the javadocs)
One is an instance method, so it returns the class of the particular object, the other is a Class constant (i.e. known at compile-time).
Class n = Number.class;
Number o = 1;
o.getClass() // returns Integer.class
o = BigDecimal.ZERO;
o.getClass(); // returns BigDecimal.class
Both cases return instances of the Class object, which describes a particular Java class. For the same class, they return the same instance (there is only one Class object for every class).
A third way to get to the Class objects would be
Class n = Class.forName("java.lang.Number");
Keep in mind that interfaces also have Class objects (such as Number above).
Also, is MyClass.class a public property of the superclass Class class?
It is a language keyword.
.getClass() returns the runtime class of the object, so it can be modified when you change the class of the variable
.class on the other hand always return the class constant of the "Type"
NOTE
If the runtime class happens to be the same as the TYPE class, both will be equal.
Example:
Long x = new Long(2);
Class c1 = Long.class;
Class c2 = x.getClass();
//c1==c2
The MyClass doesn't have a static getClass method, in other words, you cannot call MyClass.getClass(), instead you need to call (new MyClass()).getClass() for it to work.
getClass() will return a MyClass.class object. So in other words, MyClass.class is the resulting object while getClass() is a method. The getClass() method is useful in cases where you do not know the actual class of the object, for example:
public void someMethod(Object o) {
if(o.getClass().equals(Set.class)) {
// The object is a set
} else if(o.getClass().equals(List.class)) {
// The object is a List
}
}
Note that the above code example isn't the best possible, I'm just trying to show how it could be used. The same functionality could be achieved with if(o instanceof Set) { ...}
What's the difference between calling MyClass.class and MyClass.getClass()
First of all your question title is a bit misleading! .getClass() is a method defined in java.lang.Object so any object in java can call it where as .class is called on the class itself(like public static variables). So the question should be (sticking to java naming conventions)
What's the difference between calling MyClass.class and myClassObject.getClass()
Now to actual differences
.getClass() is a native java method in java.lang.Object. This method will return java.lang.Class object corresponding to the runtime class of the object on which it is invoked. So
Test t = new TestSubClass();
Class c2 = t.getClass();
System.out.println(c2);
will print class TestSubClass
where as .class will return the statically evaluated (known at compile time) class. It is actually Class object corresponding to the reference type pointing to the actual object.So
Test t = new TestSubClass();
Class c2 = Test.class;
System.out.println(c2);
will print class Test
Related
This question already has answers here:
Can a Java class add a method to itself at runtime?
(11 answers)
Closed 5 years ago.
I have a class that I don't have access to its source.
public class IDontHaveAccessToSource {...}
I'd like to add some methods to it, like so:
public class MyClass extends IDontHaveAccessToSource {
myMethod1() {...}
myMethod2() {...}
#Override
methodInIDontHaveAccessToSource(){...}
}
but it will give me a ClassCastException whenever I want to cast anything that returns IDontHaveAccessToSource to MyClass.
How can I do such things?
I don't want to use
public class MyClass {
IDontHaveAccessToSource obj;
MyClass(IDontHaveAccessToSource obj) {
this.obj = obj;
}
...
}
And there isn't any constructor available for IDontHaveAccessToSource. It 'gets created' by calling a function from another class:
IDontHaveAccessToSource obj = loadObject(filename);
You simply can't. An object that is created with new Super() can not be turned into a subclass object. If that would be possible, you would be able to break all rules of good object oriented programming.
You can only wrap around such objects. Think of decorator or facade patterns for example.
You cannot cast the object of more general class to more specific one since there is no object data in memory that relates to that specific part of your child class.
Say, you have class A that has a field fA. When you instansiate the object of that class, the field is initialized and takes some place in memory. Now you extend the class A to B by adding field fB. You create an object that allocates fA and fB in memory.
A aObj = new B(); is the proper cast since A knows about aF and once you access fA it will find the field in memory;
B bObj = new A(); This iswring since refering to bF won't be succeeded (instanciating of A did not allocate fB in memory)
Here's the code:
public class Main {
public static void main(String[] args) {
Gen<Integer> g = new Gen<Integer>(5);
System.out.println(g.getClass());
System.out.println(g.ob.getClass());
}
}
class Gen<T> {
T ob;
public Gen(T x) {
ob = x;
}
}
And here's the output
class Gen // This I understand
class java.lang.Integer // But if type erasure is happening, shouldn't this be java.lang.Object?
I get it that Type parameter T is erased at runtime, but then why is the type parameter of ob surviving at runtime?
Nope!
Consider this:
Object x = new Integer(1);
System.out.println(x.toString());
You'll get 1.
But shouldn't I get Object.toString()?
No. While x is a reference of type Object, the actual referent is an Integer, so at run-time, the Integer implementation of toString is called.
It is the same for getClass.
Type erasure is happening. Generics are a compile time type checking system. At run-time you still get the class (it is run-time type information). The linked Type erasure documentation says (in part)
Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
Your instance has a type, it's Object. But an Object reference can refer to any sub-class (which is every class) in Java. You get the type it refers to.
No matter what type the variable has, the return value of getClass() depends on the variable's contents. So, since you basically have a variable Object ob which contains an Integer (your int was converted to it at the time you provided it as that constructor's parameter), the output of ob.getClass() is class java.lang.Integer.
Also, about your question as to why getClass() remembers the type argument: it doesn't. All it does is determine the content's class. For example:
class Foo {
public Foo() {}
}
class Bar extends Foo {
public Bar() {}
}
class Baz<T> {
public T object;
public Baz(T object) { this.object = object; }
}
If you now run the following snippet...
public static void main(String... args) {
Baz<Foo> obj = new Baz(new Bar());
System.out.println(obj.object.getClass());
}
You will notice that the output is not class Foo, it's class Bar.
Because when compiled, class Gen has an Object ob; The generics disappear from the final product. The angle brackets only play a role at compile-time, during static type checking. It's something the compiler can do for you to give you better peace of mind, to assure you that you're using collections and other paramterized types correctly.
the actual object assigned to ob at runtime is an instance of the Integer class, and ob.getClass() serves the purpose to find out the actual class of the object referenced by the pointer -> hence you will see java.lang.Integer printed.
Remember, what comes out is effectively class Gen { Object ob; ... }
Since my first exposure to generics was with C# , it took time get a hold of what type erasure is in java.
But after better understanding java generics , i realized that in my question i'm mixing 2 separate topics : Generics and Reflection.
The main question was , why did the second call here
System.out.println(g.getClass());
System.out.println(g.ob.getClass());
returned java.lang.Integer instead of java.lang.Object.
Looking at the docs for getClass() , the answer becomes obvious
Returns the runtime class of this Object.
so, getClass() doesn't return the type of reference but the actual object being referred to by the reference.
For ex :
Object o = "abc";
System.out.println(o.getClass());
The output wouldn't be the type of the reference java.lang.Object but rather the actual type of the object java.lang.String.
This question already has answers here:
Overriding member variables in Java ( Variable Hiding)
(13 answers)
Closed 6 years ago.
class A
{
protected int i=10;
}
class B extends A
{
protected int i=15;
}
public class Test extends B
{
public static void main(String a[])
{
A obj=new Test();
System.out.print("i="+obj.i);
}
}
It's output is i=10, but how?
How is the memory allocation for the object will take place.
A obj=new Test();
Means, you are accessing the members of Class A and executing the methods of Test(polymorphism).
I suggest you to read the official docs on inheritance and polymorphism to understand deep.
Polymorphism is linked to objects not references. Since you are using a reference of type A, you will get A.i if you have method getI() in A and override it in B, then call obj.getI(), then you will get B.i's value
In java, Variable Overriding is not there. We have the concept of method Overriding.
In your code
A obj=new Test();
You can able to access members of A. If you have overridden same method in both the classes (Parent and Child). And you are calling that method with obj. This time you will get output from Child class overridden method. this is the concept of Polymorphism.
Line 1: A a = new A();
the method existence will be checked in A class and the method will be called from A class also.
a.g();//A class method will be called
System.out.print("i="+a.i);//A class i will be accessed
Line 2: A b = new B();
the method existence will be checked in A class and the method will be called from B class.
b.g();//B class method will be called and it will also check that it is` available in A also or not if not then compile time error.
System.out.print("i="+b.i);//A class i will be accessed
class One {
public void doThing(One o) {System.out.println("One");}
}
class Two extends One{
public void doThing(Two t) {System.out.println("Two");}
}
public class Ugly {
public static void main(String[] args) {
Two t = new Two();
One o = t;
o.doThing(new Two());
}
}
Result : One
class One {
public void doThing(One o) {System.out.println("One");}
}
class Two extends One{
public void doThing(Two t) {System.out.println("Two");}
}
public class Ugly {
public static void main(String[] args) {
Two t = new Two();
One o = t;
t.doThing(new Two());
}
}
Result : Two
I know that at runtime, even though the object reference is of the super class type, the actual object type will be known and the actual object's method will be called. But if that is the case, then on runtime the doThing(Two t) method should be called but instead the super class method doThing(One o) is called. I would be glad if somebody explained it
In the second piece of code it prints "Two".
Question : when calling from the super class reference it is calling the doThing(One o)
when calling from the sub class reference it is calling the doThing(Two o)
NOTE: I know that i am over loading and not over riding. i have edited my question for better clarity.
The method doThing() have different method signature in One and Two.
One.doThing(One one)
Two.doThing(Two two)
Since, the signature isn't matched, Two.doThing(Two) doesn't Override One.doThing(One) and since o is of type One, One.doThing() is called.
Also to be noted that One.doThing(One) can take instance of Two as an argument for One.doThing(One) as Two extends One.
Basically, "#nachokk - You are Overloading, not Overriding"
In first scenario, when you did
Two t = new Two();
One o = t;
o.doThing(new Two());
So, o is an instance of One and Two.doThing(Two) isn't available to o thus calls One.doThing(One)
In second scenario,
Two t = new Two();
One o = t;
t.doThing(new Two());
t is an instance of Two and thus Two.doThing(Two) is called.
The excelent book SCJP for Java 6 states:
If a method is overridden but you use a polymorphic (supertype)
reference to refer to the subtype object with the overriding method,
the compiler assumes you’re calling the supertype version of the
method.
So basically with using supertype for reference you're telling compiler to use supertype method.
You are just overloading,as you said
Two t = new Two();
One o = t;
o.doThing(new Two());
Even though the actual object at runtime is a Two object and not a One object, the
choice of which overloaded method to call (in other words, the signature of the
method) is NOT dynamically decided at runtime. Just remember, the reference
type (not the object type) determines which overloaded method is invoked!
When you call doThing() method with Two object argument,you will invoke One super class doThing() method.The doThing() method needs a One object, and Two IS-A One.
So, in this case, the compiler widens the Two reference to a One object, and
the invocation succeeds. The key point here is that reference widening depends on
inheritance, in other words the IS-A test.
This is something trick question
Your statment
One o = t;
I think , you are assuming that class One 'o' is equal to Class Two 't', which is not actually equal to class Two 't'
as Class Two 't' is inherited from Class One, so it will assign the base class One in your case,
So variable 't' is reference of the class One and hence will call the method of class One.
More over you create one more class named as ClassC class and try to set your statement
ClassC c= new ClassC () and then
One o = c;
You will get an error... hope the answer your question.
At the compile time the compiler searches the class One for the method doThing(Two t) but since there isn't a method with that signature it starts widening its search and finds doThing(One o). Then it holds the binary file with the descriptor one parameter whose type is One : void. At runtime since the object invoking the method is of type Two, in class Two it looks for the method that matches the descriptor and doesn't search for the method doThing that accepts an object of Two as it considers the descriptor in the binary file it links the call to the method doThing(One o).
the java specs was of great help explaining this. here is the link
I am looking at the Interface chapter provided on the Java website
Using Interface as a type
So my understanding was that the whole point of interface is that it is like a class but it's not possible to form objects from it, but this page says how to use interface as a data type. the line Relatable obj1 = (Relatable)object1; seems to create an object of type Relatable which is an interface. Although I must say that the new keyword has not been used here, thus not really creating a reference to an object of type Relatable. Is that really the cause for this line NOT creating an object of type Relatable?
Again, it further says
If you make a point of implementing Relatable in a wide variety of
classes, the objects instantiated from any of those classes can be
compared with the findLargest() method—provided that both objects are
of the same class.
What does this mean? Does this mean anything that implements Relatable can call findLargest()? If it's so, why does it say provided that both objects are of the same class?
----- EDIT -----
From the previous chapters of this tutorial:
Definition of relatable:
public interface Relatable {
// this (object calling isLargerThan)
// and other must be instances of
// the same class returns 1, 0, -1
// if this is greater // than, equal
// to, or less than other
public int isLargerThan(Relatable other);
}
Using relatable as a type:
public Object findLargest(Object object1, Object object2) {
Relatable obj1 = (Relatable)object1;
Relatable obj2 = (Relatable)object2;
if ((obj1).isLargerThan(obj2) > 0)
return object1;
else
return object2;
}
----- EDIT 2 -----
In the chapter on anonymous classes, it does this:
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}
.
.
.
HelloWorld englishGreeting = new EnglishGreeting();
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
So how does this work?
the line Relatable obj1 = (Relatable)object1; seems to create an object of type Relatable
No. This line creates a reference (obj1) of type Relatable and assigns it to object1. In order for this to work, object1 has to be cast to the (interface) type Relatable.
No new objects are being created here.
Does this mean anything that implements Relatable can call findLargest()?
Yes.
If it's so, why does it say provided that both objects are of the same class?
It has to do with the implementation of isLargerThan(). Since any class implementing the Relatable interface can't know anything about other classes implementing it, they can't do meaningful comparisons with other classes. Therefore, in order for this to work, both objects need to be of the same class.
Response to EDIT 2
So how does this work?
Instead of first defining a class and then creating an instance of it, as in the case with the EnglishGreeting, the frenchGreeting is created on the fly. What happens under the cover is that a new class implementing HelloWorld is created, just like in the english case, only this time it is anonymous (you never get to give it a name). It is just a convenience shortcut for those times when you need a one-time implementation of an interface.
Interface types belong to the category of reference types in java. You can never instantiate an interface, but it can be assigned references to any of the objects of classes which implement it:
A variable whose declared type is an interface type may have as its
value a reference to any instance of a class which implements the
specified interface.
Interfaces are like behaviors. If a class happens to implement an interface, lets say Serializable, this adds a behavior to the class, which is, the class can be serialized.
This helps you introduce abstraction in your code. For example lets assume that you need a method in one of your utility classes which will be responsible for the actual job of serialization. Without interfaces you will end up writing a lot of methods, one for each object type that you want to serialize. Now imagine if you asked each of those objects to take care of their serialization themselves (by implementing a serialize method declared in the interface they implemented). With such implementation you need to write only one utility method for serialization. This method can take an argument of Serializable type, and instances of any class implementing this interface can be passed to the method. Now within the method you only need to invoke the serialize method on the interface variable. At runtime this will result in actual object's serialize method getting invoked.
Hope I was able to keep it simple.
Interface in Java is a mutual structure for classes that implement the interface, so the classes benefit from the methods/other member of that interface in their own way, which is called polymophism,
interface A
{
// method header only declared here, so implementation can vary between classes
public int foo();
}
class B implements A
{
public override String foo()
{
return "Class B";
}
}
class C implements A
{
public override String foo()
{
return "Class C";
}
}
so you can call foo() both from class B and C but they will react differently since they implement that method in their own way
An interface is just a class that defines the behaviour of an object, but not the underlaying implementation of it.
By making Relatable obj1 = (Relatable)object1; you are just casting the object1 to a Relatable type, and therefore you can call any of the methods defined in the Relatable interface
To your first question about Relatable obj1 = (Relatable)object1;:
A simple Relatable obj1; will not create an instance of Relatable, but specifies that any object assigned to it must be of a type implementing the Relatable-interface.
Therefore any object that is to be cast, must be of a type implementing the Relatable-interface.