This question already has answers here:
Casting to a Class which is determined at run-time
(2 answers)
Closed 9 years ago.
I'm trying to use custom Class as a value in a Map<String, Class<?>>. Following are relevant parts of code:
Following is declaration and initialization of Map in main():
public static Map<String, Class<?>> mapQuery2ResponseType = new HashMap<String, Class<?>>();
static {
mapQuery2ResponseType.put("string1", CustomClass1.class);
mapQuery2ResponseType.put("string2", CustomClass2.class);
mapQuery2ResponseType.put("string3", CustomClass3.class);
}
Now I'm using this map to typecast an object to one of these classes: (assume that all classes contain a method getName() which return a String)
String name = (
(
mapQuery2ResponseType.get("string1")
)obj1
).getName();
where, obj1 is of generic type T,
but it's not allowing me to do so and says: Syntax error on token "obj1", delete this token.
Please help me to understand where am I doing wrong?
Edit:
When I use following code, it worked perfectly giving me the expected result,
String name = (
(
CustomClass1
)obj1
).getName();
and obj1 is of the same type as returned by mapQuery2ResponseType.put("string1", CustomClass1.class);.
Here I can see 1 thing... if I use use it directly, i use it as "CustomClass1", whereas if I get it from map by mapQuery2ResponseType.get("string1"), it returns "CustomClass1.class". I'm not sure if there is any difference in these two approaches? If there is, what is it?
So actually there wont be any conversion, it's just that I'm using it for large number of classes, and so trying to use a generalized approach.
Edit2:
as given in this question: Java: difference between “CustomClass1” and “CustomClass1.class”?, I think, reflection is the only solution for this task. But can anybody explain how to do it using reflection?
Simply put, this is syntactically invalid code. Not coincidentally, the compiler is telling you exactly what the problem is.
Remove ob1. I don't know what it is, or what you think it's supposed to do, but it does not make any sense there. To explain this, I'm going to twiddle your code just a bit:
The original code:
String name = ((mapQuery2ResponseType.get("string1"))obj1).getName();
Now with a local variable:
Class<?> clazz = mapQuery2ResponseType.get("string1");
String name = ((clazz) obj1).getName();
Okay, so now I think I see: you're trying to use a Class instance to cast an object. You can't do this – Java's syntax simply does not permit it. Here's how a cast might normally look:
Object foo = "bar";
String baz = (String) foo;
Note how the token for the cast expression is String, not String.class.
Class#cast() might look like a useful alternative, but that's not going to be of any use here, since you've only got Class<?>, and not Class<T>.
Forget about the Map. I suggest you restructure your code entirely such that the getName() method is defined on an interface which obj1 and all similar objects implement (assuming that the various objects have heterogenous types).
For example:
interface MyCommonInterface {
String getName();
}
class MyClass implements MyCommonInterface {
public String getName() {
// snip
}
}
// ...
MyClass obj1 = /* ... */
String name = obj1.getName();
No casting, no fancy Maps or Class instances. Just proper, simple use of the right parts of the language.
I think its better to use JAVA Reflection to do that.
Typecast needs the Type syntax befor the object to be cast, so you can do like this (CustomClass1.class)obj1, but you can't do it like (mapQuery2ResponseType.get("string1"))obj1 cause compiler can't take the cast in runtime environment.
When compile your code, you map value is considered as a value not a valid type, so you can't make cast like you have showed.
Related
First, this is similar to this question but there was never a satisfactory answer. Second: I know, I know, reflection is bad, but it is the only option I have.
Question: Given a class
package a.pkg.outside.my.code;
class ClassIWant { // Package private class
public ClassIWant instance() {...}
}
I want to call instance(), obtaining an instance of ClassIWant, and return a ClassIWant (not an Object).
I can successfully call instance via reflection and get my hands on an Object:
public class MyClass {
/* type var T will always take value ClassIWant. I can currently get
* get this to type check by using Class.cast and changing return
* type to T, but this doesn't solve my problem.
*/
public <T> ClassIWant callInstance() { // Here T is ClassIWant
Class<T> clazz = Class.forName("a.pkg.outside.my.code.ClassIWant");
Object result = _use reflection_;
return (ClassIWant) result; // Fails at runtime
}
}
The issue is that I don't have access to ClassIWant to cast, and the best I've been able to do is call clazz.cast(result). This returns type T, which doesn't quite do what I want.
It's not even clear to me that this is possible, but my program has been type checking and getting illegal access errors at runtime. This tells me that all the bits and pieces fit together on the type level, and that methods are all pointing to the right place.
Note: It may be possible to change my use case to not need an explicit ClassIWant, but this would probably be a fair amount of work (i.e., lots and lots of calls to reflection). For brevity I haven't included the use case---I'll treat this as a second question if need be.
Edit: Updated in response to Andy Turner's comment (thanks for the catch): in more detail, I'm not explicitly using T here, but I have access to it and I want to make that explicit
I have code like this:
public class Crate<T> {
private T contents;
public T emptyCrate() {
return contents;
}
public void packCrate(T contents)
{
this.contents = contents;
}
}
Now we know - in the end it will be "converted" to the following code:
public class Crate {
private Object contents;
public Object emptyCrate() {
return contents;
}
public void packCrate(Object contents)
{
this.contents = contents;
}
}
Then why we need to create a generics if i already can create a class like Object Based ?
When people talk about type erasure, they normally focus upon the generic class itself. But there is another important place with generics: the call site.
For example, if you've got this code:
Crate<Integer> intCrate = new Crate<>();
intCrate.packCrate(0);
Integer contents = intCrate.emptyCrate();
Then, when it is compiled, it actually becomes:
Crate intCrate = new Crate();
intCrate.packCrate(0);
Integer contents = (Integer) intCrate.emptyCrate();
// ^ Important! This cast.
i.e. there are casts inserted automatically. Also, implicitly, there is a check that the parameter of packCrate is compatible with Integer, so you couldn't write:
intCrate.packCrate("hello");
Now, you can do this without generics, putting in these casts yourself, but the compiler doesn't help you to know what was put into the Crate. You could write something like this:
Crate crate = new Crate();
crate.packCrate(0);
String contents = (String) crate.emptyCrate();
This will fail at runtime, because the crate contains an Integer, not a String.
Generics just help you not to have to remember what you are allowed to pass to an instance, and what you will get out of it.
You see, java code is translated to bytecode. So why don't you write your programs in byte code? They get translated anyway? Or, to be precise: the JIT compiler will turn most bytecode into machine code at some point. So why do you insist on writing java source code, instead of binary machine code?!
I guess the above questions make my point clear: generics allow you to express intent for human readers. They allow you to write better source code; and they enable the compiler to do certain kinds of checks on your input - as nicely summarized in the other answer by Andy Turner.
That is the whole point of any abstraction that programming languages provide to you: they help you the programmer to create source code that expresses "what needs to be done" in a concise way that makes it easier for human readers to understand what is going on, and why!
It doesn't matter what it will be turned into.
Rather the stage of compilation is important. Generics guarantee type safety at compile type (fixing compile-time errors is much easier than runtime ones).
It also eliminates casts and enables the ability to implement generic algorithms.
All collections in Java are Generics. It's the best example of using Generics. For example you create class List. Which types of objects will it hold? When you create List class, you don't know about which types it will hold, so you use Generics. And when you use Listclass, you say, that you want to put Integers(new List<Integer).
Template parameters in generics are used for compile time safety. Compiler will choke if you write for example:
Crate<Integer> cr;
Object o;
cr.packCrate(o); // compilation error here
It can also declare that any class used as parameter will implement some methods:
Interface I {
void myMethod();
}
class Crate<T extends I> {
private T contents;
...
public void applyMethod() {
contents.myMethod(); // T shall implement myMethod
}
}
In fact everything could be done by explicit casting, but you will get only run time errors while generics allow compile time detection of errors.
Suppose you create an object:
class newClass{
public static void main(String[] args){
Object o = new Object();
}
}
Is it possible to return the name as a string, "o", or in anyform, of the given object?
No, this is not possible. If you really want this, you are probably using the wrong design. Note that objects do not have a name. Variables do have a name.
Is it possible to return the name of an Object in Java?
If you write something like this:
String name = obj.toString();
It will return string representation of object but this is not very human-readable. if you want to do it you need to create custom object and override toString() method:
public class MyObject {
private String name;
public String toString() {
return name;
}
}
Now when you write:
String name = myObj.toString();
It will return name in human-readable form. But this depends of your requirements if you want to create custom objects. In this way it's very simple and it works well.
No. The object does not know what the outside world calls it, i.e what reference(s) it has.
This is not possible.
You could use a Map<String, Object> to store a mapping from object name to object value and then return the key.
In reality the "name" of your object is a compile time constant. I.e. it doesn't change once you have compiled the code so
Object o = new Object();
return "o";
Would literally do what you want. Which begs the question, why would you want to do that?
This is not possible using java reflection. However, the information is stored in java class file if compiled with debugging information on. You may use bytecode engineering library like ASM to dig that.
Note: I just read sajmon's answer and he has the more elegant way of doing it to a certain extent
First of all the guys' answers are correct
but
if you really need it
I would extend Object class with something like MyObject
public class MyObject {
private String objectName;
public MyObject(){
}
public MyObject(String name){
setObjectName(name);
}
public getObjectName(){
return this.objectName;
}
public setObjectName(String name){
this.objectName = name;
}
}
but then each time you create an Object use MyObject instance instead and add your object name as a constructor parameter
MyObject mine = new MyObject("mine");
Having said that, it's still an open question as to why you might need it? :)
Since Java supports aliasing this really isn't sensible or possible.
Aliasing means there's no garuantee that an object is referenced by only one variable.
scoping just makes the whole problem even harder, since only references in the current scope would be of any use at that point. and there may be more than one.
it would help if you explained what you're trying to achieve with this code.
In addition to the previous answers, there may be several different variables, with different identifiers, that all reference the same object. A variable may refer to different objects at different times.
If you need a mapping from an object to a String, I suggest a Map<Object,String>.
Am having some arguments say (String a, Treeset b, Set c)
and I try to get the class by arguments[i].getClass(); of the above arguments..
is Iit possible to get the class of the interface <Set>.
For example:
Class[] argumentTypes = new Class [arguments.length];
for (int i = 0 ; i < arguments.length ; i++)
{
argumentTypes[i] = arguments[i].getClass();
}
The code you've given will find the classes of the arguments (i.e. the values provided to the method) - but those can never be interfaces; they'll always be concrete implementations. (You can never pass "just a set" - always a reference to an object which is an instance of an implementation of the interface, or a null reference.)
It sounds like you want the types of the parameters - which you'd get via reflection if you absolutely had to, finding the Method and then getting the parameters from that with getParameterTypes. But given that you're within the method, you already know the parameter types, because they're at the top of the method... I'm not sure the best way of finding "the currently executing" method, if that's what you're after.
If you're just trying to get the class associated with Set, you can use Set.class of course. But again, it's not really clear what you're trying to do.
EDIT: Okay, judging from your comment, there are some logical problems with what you're trying to do. Going from the values of arguments to which method would be invoked is impossible in the general case, because you've lost information. Consider this, for example:
void foo(String x) {}
void foo(Object y) {}
foo("hello"); // Calls first method
foo((Object) "hello"); // Calls second method
Here the argument values are the same - but the expressions have a different type.
You can find all methods which would be valid for the argument values - modulo generic information lost by type erasure - using Class.isAssignableFrom. Does that help you enough?
Note that you'll also need to think carefully about how you handle null argument values, which would obviously be valid for any reference type parameter...
You can use http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getInterfaces()
You will get the class what the caller provided.
I mean,in below class you will get HashSet.
Set set=new HashSet();
System.out.println(set.getClass());
You can do this in two ways given below
Set s = new //any class that implements it for example HashSet or TreeSet etc.;
s.getClass().getName(); //This will return the name of the subclass which is refered by s.
or if in other way can do it
Set s = null;
s.getClass();//This causes NullPointer Exception
I know well, what is a class literal in java, I just wonder, what is the reason for the .class in the syntax. Is there any ambiguity removed by this? I mean, wouldn't an alternative Java syntax using
Class<String> c = String;
instead of
Class<String> c = String.class;
work? To me the class keyword looks like a boilerplate.
Sure, you could make that the syntax. But using the .class suffix makes the compiler's job easier; it has to do less work to know that the code is syntactically correct.
Without the suffix, the compiler would have to work harder to understand the difference between this:
String.getName() // a method inherited from java.lang.Class<T>
and this:
String.valueOf(...) // a static method from java.lang.String
If you don't think that the .class suffix is needed, do you also think that the f and L suffices are useless (for float and long literals, respectively)?
It's just not the same thing. String is a class of type string, and String.member is one of its member variables, String.method() would be one of its methods.
String.class is an object of type Class that defines String. It seems a lot more intuitive that you need to specify .class to indicate that you're trying to refer to an object of type Class.
Not to mention that it's easier to parse this kind of construct, and potentially prevents bugs where you're accidentally returning a Class object when you didn't mean to.
This is even more relevant when you're looking at inner classes, like OuterClass.InnerClass.class.
To work with Matt's example: How would you work on the class object without having to create a temporary variable first? Assuming your class Foo has a static method called getClasses, how would you differentiate between Foo.getClasses and Foo.class.getClasses?
String is the String class pseudo-object which provides access to the classes static fields and methods, including class, which refers to the Class instance which describes the String class. So they are distinct, but because Java doesn't have the metaclass arrangement of (say) Smalltalk-80 this isn't very clear.
You could certainly make String and String.class synonymous if you wanted to, but I think there is a valid basis for the distinction.
Let's use integer as an example:
Class<Integer> c = Integer; // your proposal
int i = Integer.MAX_VALUE; // compare with below
int j = c.MAX_VALUE; // hmm, not a big fan, personally
It just doesn't seem to flow, in my opinion. But that's just my opinion :)