0

Previous question

I have the following code:

ArrayList<Object> list = new ArrayList<Object>();
list.add("StringType");
list.add(5);
list.add(new RandomClass());

List<Class<?>> classes = new ArrayList<>();
classes.add(String.class);
classes.add(int.class);
classes.add(RandomClass.class);

for (int i = 0; i < list.size(); i++) {
    if (classes.get(i).isInstance(list.get(i))) {
        ...
    }
}

if (isvalid)
 mymethod(...);


public void mymethod(String string, int num, RandomClass randomClass){ }

Now I'm trying to cast the object into the right type with a method using a string argument.

Instead of:

mymethod( (String) list.get(0), (int) list.get(1), (RandomClass) list.get(2) );

I would like to reuse the definition created above for the cast.

mymethod( ( define.get(0) ) list.get(0), .... );

I've also tried using the Class.cast(obj) but of course it returns a type '?' which again defeats the purpose of casting it again using (String).

1
  • This cannot be type safe as you can change the types at runtime made cause a ClassCastException. Therefore you cannot have what you want. Commented Nov 9, 2014 at 10:34

4 Answers 4

2

What is type safety?

In computer science, type safety is the extent to which a programming language discourages or prevents type errors.

If code is type safe, then the compiler can verify, at compile time, that all the types are correct:

String getName() {
    return "name";
}

The compiler knows that "name" must be a String so it can verify that this code will never throw a type error.

Once you do something like:

int getNumber() {
    (int) number;
}

The need to explicitly cast to int tells you that this code has an error condition, namely when number is not of type int or a type that is assignable to int.

How does it affect you?

Your code:

define.get(0).cast(list.get(0))

You want the return type of this statement to be of the type of get(0). But the compiler has no way of knowing, at compile time, what define.get(0) returns. This is inidcated to you by the return type.

You have a List<Class<?>>, i.e. a List of a class of "I don't care what type". You then use a member of this List to cast a member of your other List - the only result can be an "I don't care what type".

You can hack around this with:

<T> T get(final int i) {
    return (T) define.get(i).cast(list.get(i));
}

This will happily compile:

final String thing = get(0);

As will:

final int thing = get(0);

i.e. all that you have done is to endogenise the cast. The error condition still exists.

Sign up to request clarification or add additional context in comments.

3 Comments

This solves the problem by the 'hack' there. Before I call them method, I would have checked if each object was of the correct type (isInstance part in the forloop). and if all the parameters were valid I would then call the method. This I assume this shouldnt produces any error of wrong type by using the hack. Mind explaining how does the (t) cast and return value <T> T works. Or maybe a link to readup on that.
Are you saying that you have never seen generics before? Hm...
Oh okay. I've seen it and read bits of it but haven't really did a read up on exactly how it works. School doesn't really teach such stuff so yeah.
2

define.get(0).cast(list.get(0)) would attempt to cast list.get(0) to the required type.

2 Comments

Yes i know but for example get(0) it's return value isn't of 'String' type. Which my method definition is method (String string, int num, RandomClass randomclass)
@user755053 it is not possible to do what you want. Find another approach. This seems like an XY problem.
1

In order to be able to select the appropriate method, the compiler needs to know at compile time what the types of the arguments are. Or at least a general category such as List<?> etc.

This is needed to support overloading of methods. There can be many methods with the same name, but with different parameter types.

Since you are asking the VM to call a method when it can't determine which exact method you want to call, because it doesn't know at compile time what the types of your parameters are, what you ask cannot be done in Java.

Here is the relevant section from the Java Language Specification.

What it says is that the system selects at compile time which method signature to use, and then, at run time, the particular implementation of that method signature that's correct for the given instance.

2 Comments

I always thought that overloaded method selection occurs at runtime? Where did you read about it happening at compile time? Could you post a link?
@GermannArlington it is common knowledge that Java is wired at compile time. You may be confusing overloaded methods with overridden methods, which are selected at run time - the latter is called polymorphism.
0

You don't actually need to store object's class separately

list.get(0).getClass()

will get you the class of the stored object and then you can use what @Eran suggested

and

list.get(0).getClass().getName() 

will get you the String name of your class

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.