I'm studying Prototype Design pattern I can't understand the syntax below. Can you explain it to me? What does it mean for a class to be put in parentheses and initialized like this :
Person person2 = (Person) person1.doSomthing();
Code in context:
// code in int main
Person person1 = new Person("Fred");// this is understood
System.out.println("person 1:" + person1);// this is understood
Person person2 = (Person) person1.doClone();//not understood
System.out.println("person 2:" + person2);// this is understood
Is this syntax in java for casting?
It is a cast. In other words, the doSomething() method is most likely not declared to return a Person. So you need to first cast the returned value to a Person before assigning it to person2.
If doSomething does return a Person, then the cast is not necessary.
And if the actual type of the object returned by doSomething is not assignable to a Person, the cast will throw a ClassCastException at runtime.
More info about it in the JLS #15.16:
A cast expression converts, at run-time, a value of one numeric type to a similar value of another numeric type; or confirms, at compile-time, that the type of an expression is boolean; or checks, at run-time, that a reference value refers to an object whose class is compatible with a specified reference type.
The parentheses and the type they contain are sometimes called the cast operator.
It's called type casting. What you are saying is that you want to ensure that the JVM makes an attempt to force whatever type of object is returned by that call to be a Person.
Another thing not mentioned by assylias is that this has two additional features:
If the actual returned object is a subclass of Person, it will change the returned value into a Person. This can be useful for when you want to make sure that whatever subclass is actually used, it'll hopefully behave just like a Person.
If Person is an interface, it will let you step outside of the inheritance hierarchy of that particular implementation altogether and use someone else's Person implementation. This is great for use with APIs like Spring which let you configure after build time how classes are chained together in things like security configurations and such.
It is simply used to cast it (person1.doSomthing()) into Person type. Because it may not be returning a Person type, but something that can be casted into a Person type.
You're casting the result of Person.doClone() to also be of type Person. Presumably Person.doClone() returns an Object or similar.
Person person2 = (Person) person1.doSomthing();
It Type casting to Person type which Object returns from person1.doSomthing().
Person person2 = (Person) person1.doClone();
Here it clone the person1 Object cast it into person object.
This is a typecast, to ensure that the object type that is returned from calling person1.doClone() is of type Person, so that it can be assigned to your person2 variable.
If the doClone() method is defined in the Person class, I would expect it to return an object of type Person. In this scenario, the cast is benign and unnecessary.
However, doClone() may be defined in a superclass of Person, and returning a more generic type, thus a narrowing cast may be desired.
If doClone does not return an instance of type Person (or some other class in Person's inheritance hierarchy), then a java.lang.ClassCastException will be thrown.
Related
Java newbie here, I have a basic question that is half answered by previous responses in other threads or the docs, but I still don't fully understand the mechanism and I want to be sure I covers the fundamentals (code at bottom, questions in middle).
Basically, I'm overriding the equals() method to check if two MyDate objects have the same date. I do an instanceof check if the o object is a MyDate object, then you type cast a temp object specifically to a MyDate object o, then you compare dates. Why do you type cast the temp variable to MyDate class of o, when it already is of the MyDate class?
Do you use temp variable as an easier reference the object you want to run the equals() comparison? Because you use equals() as comparing MyDate.equals(MyOtherDate), in the code if I don't designate a variable to hold the reference then you get various errors (temp cannot be resolved as a variable, type mismatch, etc basically the compiler isn't sure where to look unless you write a bunch more code).
2a. Some of the other threads said something to the effect that while instanceof checks if an instance is from a class, it checks the base class, but doesn't check a subclass. You do the typecasting because you're specifically telling the compiler to check for that specific object (type casting from a general object to a specific object). NOTE: This might be a version and flavor specific type question, I've seen different replies to similar questions.
2b. Casting changes the reference, not the object itself. So, if the objects are from the same class, but different subclasses, wouldn't it fail at runtime, instead of compile time. And wouldn't I get a ClassCastException?
public boolean equals(Object o) {
if (o instanceof MyDate) {
MyDate temp = (MyDate) o;
if ((temp.day == day) && (temp.month == month) && (temp.year == year)) {
return true;
}
}
return false;
}
The Java compiler doesn't understand the type class of your object "o" as being MyDate. This happen because you've received a parameter of the type Object so it will be read as an object. In order to access the methods and properties of the parameter of known type MyDate, you need to tell the compiler that this is an object of type MyDate. This is the way the compiler is going to understand what you're doing. Now let's take a look to another view sight.
Every types in Java extends the type Object which means that every time you write a class, you're implicitly extending the Object public/protected properties and behaviors. That's why you are "overriding" the method equals that belongs to the Object type. Alright, when you're doing a comparison between two objects you must first check if both of them belongs to the same type, as you did in your example with: if (o instanceof MyDate) { ... } to ensure that o is of type MyDate. But at this point, as you didn't cast "o" to "MyDate" type you won't be able to access MyDate's specific properties or methods. So think of it for a while, if I have a class A that extends my class B I will be able to access B public methods and properties inside A, but I can't do the same on B because B can't see what's happening down the tree. Do you follow?
Hope I could answer your doubts.
Java has two related-but-separate concepts: the type of an expression, and the runtime-type of a value.
These concepts are compatible to some extent; if an expression has type MyDate, then when you evaluate that expression, you either get a reference to an object whose runtime-type is either MyDate or a subclass of MyDate, or you get a null reference, or you get an exception or infinite loop or whatnot. But the concepts are separate, and even when your runtime-types are fine, sometimes you need to give the compiler some extra information about the types.
> Why do you type cast the temp variable to MyDate class of o, when it already is of the MyDate class?
The variable o is of type Object, not ever of type MyDate. It happens to contain a reference to an object whose runtime-type is MyDate (or a subclass of MyDate), but that doesn't affect the type of o. So you write (MyDate)o to create an expression with the same value (and hence the same runtime-type) and the desired type.
If the compiler were smarter, it could perhaps treat o as having type MyDate inside your if-statement, so you wouldn't need the cast; but the current Java Language Specification doesn't allow that. (And if it did, that could have some weird implications when it comes to static method dispatch.)
Can i storage all my inherited objects as ArrayList? I dont want to create new ArrayList for each object type something like:
ArrayList<MyObjectTypeA>
ArrayList<MyObjectTypeB>
ArrayList<MyObjectTypeC>
I know i can do:
ArrayList<Object>
Then cast it to valid object type, but maybe there is faster and more performanced method to do it like:
ArrayList<MyObject>
and cast it to valid object type, will i lose additional object type data or cast will bring it back to my type?
If MyObjectTypeA and the rest inherit from MyObject then you can indeed create an ArrayList<MyObject> and store all of them and the cast them back to the correct object type.
However, note that this is an antipattern and usually a smell of bad code. You should only be doing this if you want to use any type of MyObject. If you want to use a specific type then you should create different Lists.
Regardless, if you are going to go through with bundling them all together in one list, at least before doing any casting you should check if the object you are casting is actually an instance of the type you are casting to like so:
if (object instanceof MyObjectTypeA){
MyObjectTypeA typeA = (MyObjectTypeA) object;
} else if (object instanceof MyObjectTypeB) {
// etc.
}
Note that the process of casting does not change the object itself. That's why the correct naming is type casting. You essentially declare than an instance is of a specific type. This essentially "enables" the usage of the specific type's methods and members whereas previously they were there but they were not accessible because the compiler didn't know about them (since he thought the type of the object did not contain such members but inside the program memory it actually did).
As an example, if you try cheat like so:
MyObjectTypeA typeA = new MyObjectTypeA();
MyObject object = (MyObject) typeA;
MyObjectTypeB typeB = (MyObjectTypeB) object;
This will actually compile since the compiler knows that object can be of type MyObjectTypeB but it will warn you that you are doing an unchecked casting (not checking with instanceof like I showed earlier). That specific scenario, when reaching line 3 will throw a ClassCastException since the interpreter will attempt to cast object to MyObjectTypeB but will fail since object is of type MyObjectTypeB.
You can declare an arraylist of type base class and add to it objects of the inherited types.
ArrayList<BaseClass>
You need to clearly define your objects.
For example, if you have a Class A, and classes B and C inherit from A, then yes do the following:
ArrayList<A> temp= new ArrayList<A>;
Here you will be able to call the methods you would want using polymorphism.
You should also be aware of type-safety and type-casting. The object class is too generic.
Why not use a HashMap and store the Object as the value and the Key as the type?
HashMap<Type, Object> typeObjectMap = new HashMap<Type, Object>();
I'm trying to access a HashMap<String, Number> via reflection:
Serializable obj; //here goes the HashMap
String name;
...
return (double)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name);
but so far all I got is a casting error caused by the line above:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
Indeed, the map value that was accessed by the key name was Integer.So I've changed the line to:
return obj.getClass().getDeclaredMethod("get", Number.class).invoke(obj, name).doubleValue();
but that didn't work out either. I even got doubleValue() underlined as "undefined for the type Object" (but why Object if I have Number.class?).
I'm not sure what casting rules I'm breaking. Can someone, please, help me if my map entries have various number values (Integer, Float, Double) but I need the method to return a double value (primitive).
PS
It's not really a duplicate. My question is more general. But thank you for your input. I forgot that invoke always returns Object.
The working code is:
return ((Number)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name)).doubleValue();
You have the wrong assumption that there was a relationship between the Class object you pass to getDeclaredMethod and the return type of Method.invoke.
The Class objects you pass to getMethod or getDeclaredMethod describe the parameter types of the method, not the return type.
Further, while you may pass arguments of a subtype of the declared parameter type, you have to specify exactly the declared parameter type.
The parameter type of Map.get is Object, invariably, so you have to specify Object.class, regardless of which actual key you will pass to invoke.
Further, due to type erasure, the reflective return type will always be Object, regardless of the actual Map’s parametrization.
Not that it matters, Method.invoke’s declared return type is always Object, as different Method instances may represent different methods.
So when you have a HashMap<String, Number>, you can rely on the returned objects to be Number instances, but not necessarily Double instances. As you experienced, there could be Integer instances. So what you have to do, is to type-cast to Number, followed by invoking doubleValue():
return ((Number)obj.getClass().getDeclaredMethod("get", Object.class)
.invoke(obj, name)).doubleValue();
That said, if you know that the object implements the Map interface, there is no reason to use Reflection at all:
return ((Number)((Map<?,?>)obj).get(name)).doubleValue();
does the job much more efficient.
class Person { void f() {} }
class Student extends Person { void f() {} }
So when I execute the following code:
Person p = new Student();
((Person) p).f();
Why is the f() function in the Student class called when the variable is cast as a Person? I understand why the f() function is called when it is just p.f(), but I guess I'm just confused to what exactly the cast does.
This is one of the cornerstones of Object Oriented: Polymorphism. You have all kinds of Person entities each doing f() in its own way! It is the actual instance of the object and not what you cast it to that does f().
You can always convert subtypes to Type this casting is always allowed in java however because instance is of subtype subtype methods will get executed.
You can check Here for more information
In Java there are two types of reference variable casting:
Downcasting: If you have a reference variable that refers to a subtype object, you can assign it to a reference variable of the
subtype. You must make an explicit cast to do this, and the result is
that you can access the subtype's members with this new reference
variable.
Upcasting: You can assign a reference variable to a supertype reference variable explicitly or implicitly. This is an inherently
safe operation because the assignment restricts the access
capabilities of the new variable.
Yes, you need to implement the interface directly or indirectly to enable assigning your class object reference to the interface type.
When invoking methods, it will be always executed on object type, not reference type due to ploymorphsim.
The same method -- the one in Student -- will be called whether or not you've cast the Student to a Person.
Up-casting a reference (from subclass to superclass) serves no real function (and in fact will generally be a no-op internally). Down-casting, on the other hand, tells the JVM that you believe the superclass to be of the specified subclass, and if it's not a cast error will be raised.
(I'll give gefei credit for pointing out an omission above: The cast ALSO tells the compiler the type, and the compiler uses this information to know what methods and fields the object (supposedly) has. This is not strictly necessary to compile a Java program to bytecodes, but it does allow the compiler to do the usual compile time validity checks.)
The upcasting is irrelevant here. The overridden method will always be called if present.
The cast in your example is totally useless. The compiler knows that p is of type Person. More interesting would be a narrowing cast:
Person p = getPerson();
if (p instanceof Student) {
Student s = (Student) p;
// do something Student-specific with s
}
Casting reference types in Java does not change the nature of the object; it only tells the compiler what assumptions can be made about the object. At run time, the object's actual type is used to determine what method is called. (Note that this is not true of primitive types; casting an int to a byte will change the data.)
I currently posses a List of Objects(Using Java 1.3), and let's say that I wanted to cast one of the Objects returned from list.get(i) to a type of which I only know the name of the Class as a String. Essentially, how do I
Object o = (classname)list.get(i); where className is a String variable of a className.
I thought that I could use ( Class.forName(className) )list.get(i), but I received a syntax error claiming that I forgot a semicolon.
Unfortunately, since I am using Java 1.3, I do not have access to the Class.cast(Object) method.
What is the name of the class used when casting to another type in Java 1.3? Is there some method that can give me the correct type I need with a String parameter of the class name?
what is the point of casting when all you do is assign the result to object?
All you would achieve is an exception if it did not implement the interface/extend or was the class or do nothing if it did.
For that a simple:
public static boolean IsInstance(object x, String className)
{
Class cls = Class.forName(className);
return cls.isInstance(x);
}
is sufficient (and cleaner)
If you were to the use reflection to get at the fields/methods of the class that's just fine
No, and you can't do this across most languages.
The reason is that the type to cast to has to be known at compile time, not at runtime (which is what you are trying to do).
If you think about it, it makes sense, because given that the variable could be any type name, how are you supposed to access the various members? You can't, not unless they are defined in a base type/interface that all instances implement, in which case you should just use that.
One scenario where the need for this arises is when enforcing type safety with a legacy system. For example, suppose you have a persistence system like Hibernate that provides a raw List of results from a "finder" method. Casting this raw List to a parameterized type will result in an unchecked warning, and if the List contains an object of the wrong type, a ClassCastException can be raised at an unspecified time in some distantly related code. It may be best to validate the contents of the list up front, using a mechanism like the OP suggests.
Here's the Java 1.3 version (without generics):
private static void checkType(Collection objs, String className)
throws ClassNotFoundException
{
Class clz = Class.forName(className);
Iterator i = objs.iterator();
while (i.hasNext()) {
Object obj = i.next();
if (!clz.isInstance(obj)) {
throw new ClassCastException();
}
}
}
In Java 5 and later, with generics, you can do something similar with the Class.cast() method to verify the contents of a collection, justifying the use of a SuppressWarnings annotation. In our review process, suppressing a warning without some "proof" that it is safe is filed as a bug.
I assume that you really wanted to write the following, instead of using Object on the left side. Since otherwise, it's really just about checking whether the object in the list is of the right type.
ClassName o = (classname)list.get(i);
Well, Java is statically typed. It's not possible that you give it a string and it gives you the corresponding static type, so that you can go without casting. Even with generics and Class<T>.cast, the cast destination type is not given by a string, but by the generic type-argument T, which is known at compile-time. You have to manually cast to the right type, or keep using the most common type (may be Object in your case).
If you do Class.forName(className), it gives you back an object of the type Class which contains information about the type at runtime, so that it allows you to do
Class.forName("my.stuff.MyClass").newInstance()
But the cast wants a type - not an object of some type. That is why the compiler told you there is something wrong with that code.
The static type of the reference returned by that is of Object. This is important: The dynamic type of an object that is referenced, and the static type of the reference that points to that object. The dynamic type of the object is what can be "controlled" by a string (by using Class.forName), but the static type of the reference that you have to do with at compile time, and that is (just to give an example) used to select functions that overload each other, can not be determined by a string.
The question was answered already, but I'd like to add that it seems a bit dubious that you should have a List in which you keep several different kinds of objects (in this case, any objects), yet you'd apparently like to invoke operations on them that are specific to each different type...
What's the point of this collection? Don't the instances you keep in it have anything in common - any common supertype that you could cast them into?