0

NB: This is not a duplicate of the question I have already linked to below. I obviously read that question/answer first before posting and did not have my question answered in any form.

This linked question does go into more detail explaining why the generic Class exists. However I don't get an answer specifically to the benefits of Class in my situation.

What does the generic nature of the class Class<T> mean? What is T?

I've written a utility method that accepts a parameter 'cl' of type Class and performs logic by using cl.isInstance(objectInstance) method.

However I've seen example code that declares parameters using the generic wildcard Class<?>.

Why not just use Class without the generic wildcard? Can't Class represent all possible class types including generics? What is the benefit, if any of using Class<?> in my situation?

The accepted answer in an existing related question (see below) does not actually provide a useful answer.

What does Class<?> mean in Java?

Community
  • 1
  • 1
Ash
  • 60,973
  • 31
  • 151
  • 169
  • The accepted answer describes the situation perfectly. If you're not happy with it, that's unfortunate. The "benefit" is that you'll be writing syntactically correct code and won't get warnings. – Kayaman Feb 29 '16 at 07:06
  • No it does not! Please read the comments under the accepted question. My question is what is the benefit of using Class> over Class. I am trying to learn this. I am moving into Java from .NET that has a System.Type class but no System.Type<>. This is a completely reasonable question. Voting to re-open. – Ash Feb 29 '16 at 07:18
  • I told you there is no benefit. It's a syntax requirement due to the fact that `Class` is generic. I didn't say it's not a reasonable question, I just said that the answer is already valid. The fact that `.NET` doesn't have `System.Type<>` is irrelevant. – Kayaman Feb 29 '16 at 07:20
  • Netbeans 8.1 gives no warning where I have use Class cl as a parameter so that is not even correct. I have not turned off any warnings. – Ash Feb 29 '16 at 07:21
  • Well, my Eclipse correctly warns about a raw type when using `Class`, so you're wrong in any case. – Kayaman Feb 29 '16 at 07:22
  • Kayaman are you being deliberately obnoxious? Read the other question and note that it simply does not answer "Why would you not just use Class as the parameter?" – Ash Feb 29 '16 at 07:22
  • Kayaman, Firstly, I flagged your comment as rude or offensive. Secondly, as stated, I do not get a warning. Thirdly why not post that as an answer? – Ash Feb 29 '16 at 07:28
  • Firstly, I don't really care. You're the one banging your head against the wall. Secondly, that's not correct, meaning that your system has a flaw. Either Netbeans is doing a sloppy job, or some other reason. Third, I did not think this warrants an answer since the duplicate is... well, a perfect duplicate. The "problem" here exists completely in your head and with your Netbeans installation. – Kayaman Feb 29 '16 at 07:31
  • @Jim Garrison Could you please reopen this question. I have explained why this is not a duplicate. I'm moving to Java from .NET, I want to learn the platform/language but having a valid question closed within seconds is not positive. – Ash Feb 29 '16 at 07:33
  • @Kayaman, Please read the other question carefully. Then read the accepted answer. Then read the comments complaining that the question is not answered. If you still think it has been perfectly answered you have serious comprehension issues. – Ash Feb 29 '16 at 07:35
  • Java is not C#. The rules are different. If you are asking why Java's rules are not the same as C# you're venturing into questions with no answer. It just is different. – Jim Garrison Feb 29 '16 at 07:36
  • @Jim Garrison No I'm not. I'm asking this question: "Why would you not just use Class as the parameter?". This is quoted from the other question and is not answered there by the accepted answer (also see comments complaining about this). – Ash Feb 29 '16 at 07:38
  • @Jim Garrison As someone coming from .NET, where we don't have a System.Type<>, it makes this an even more valid question. – Ash Feb 29 '16 at 07:40
  • @Ash I commented on the accepted answer in the duplicate question. – Kayaman Feb 29 '16 at 07:52
  • @Kayaman, that is fine. However that implies that you have added useful information to that question, but that actually belongs as an answer to this question. This question is much more specific and is something that other people have also asked (see the other comments). This is why it should be re-opened and why you should add your answer here. – Ash Feb 29 '16 at 07:59
  • @Jim Garrison, You have not even linked to the most applicable question. I've since found question 9406025 that explains why Class<> exists. It still doesn't actually answer what is wrong (if anything) with using the non-generic Class as a parameter type. This is what I want to have answered. However at least it is more relevant than the question you linked to. – Ash Feb 29 '16 at 08:09
  • @Ash the basic answer is that referring to a generic type without giving generic arguments pretty much turns off type checking for anything to do with that type, and is essentially always a bad idea. There is basically never a good reason to refer to a generic type as a raw type, whether it's `Class` or something else. – Louis Wasserman Feb 29 '16 at 12:53

2 Answers2

6

The main difference lies in the (self-)documentation of the code to the reader. A variable declared as Class<?> says: “the actual type represented by this Class instance is unknown or not representable at compile-time and I know that”. In contrast the type Class says: “I’m not using Generics here”, perhaps, because you don’t know that Class is generic, or you are a bit sloppy, didn’t understand the difference between Class<?> and Class, or this is very old pre-Generics code.

This has consequences for the code. E.g.

Class<?> unknownType=Object.class;
Class<String> string=unknownType;

produces a compile-time error as you are assigning an explicitly unknown type to a variable declaring a known type.

In contrast

Class nonGenericType=Object.class;
Class<String> string=nonGenericType;

will only produce a (suppressible) warning as you are performing a non-generic, aka unchecked, operation.

Regarding what you can do with a Class object, besides assignments, there is no difference, as, when you use it to create a new instance, the compile-time type of the returned reference will be the most abstract type there is, java.lang.Object, in both cases. Had Class methods receiving arguments related to the type parameter, a difference showed up as you can’t invoke such methods for an unknown type, Class<?> (it would be the same as trying to insert an element into a List<?>) while you could invoke such a method unchecked on a raw Class instance. But since there are no such methods, there’s no difference in functionality between Class<?> and Class.

Still, you should always use Class<?> to be sure that no accidental unchecked operations, like the assignment shown above, happen. If using Class doesn’t produce compiler warnings, you should check how to (re-)enable them. If the compiler silently ignores raw types or unchecked operations, there might be other problems, with other types than Class, hiding somewhere.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • +1. Re: "when you use it to create a new instance, you’ll get the most abstract type there is, `java.lang.Object`": It took me a few reads to understand this statement -- at first I thought you were saying the new instance would not be an instance of any more-specific class (due to some sort of X-treme Erasure™). I don't have a specific suggestion for how to make it clearer, though. :-/ – ruakh Feb 29 '16 at 18:17
  • @Holger, thanks for the explanation. It seems that if Java had real generics (i.e. at byte code level) it would remove this confusing (to newcomers) expectation for Class to be generic. For example, System.Type in .NET is the direct equivalent of java.lang.Class and it is a raw (non generic) type. There is no sensible reason for it to be generic. After all the main purpose of both System.Type and java.lang.Class is as a 'meta object' that describes another class. .NET is *far* from perfect, but at least they did generics right. Thanks again. – Ash Mar 01 '16 at 08:20
2

The difference between the wildcard type <?> and the raw type in this particular scenario is only whether the compiler will warn you or not. Otherwise they're equivalent, so if for some reason you don't wouldn't want to use the <?> syntax and you didn't care about compiler warnings, you could use the raw type without any problems.

Netbeans not complaining about the raw type is not correct behaviour, and my Eclipse will complain when using a raw Class.

The Class object has distinct usage patterns, which affect whether the type will be a concrete type (seen in method parameters as Class<T> clazz) or the wildcard Class<?>.

The most common form seen in the API is the concrete type, since it allows you to use newInstance() (primarily) in a type-safe way (making all Class<T> objects automatically type-safe factories), such as the following:

public static void List<T> fill(Class<T> clazz, int size) {
    List<T> l = new ArrayList<T>();
    for(int i = 0;i < size; i++)
        l.add(clazz.newInstance());
    return l;
}

So Class<T> is useful, but what about Class<?>? Well, not so much. As indicated at the beginning, it's just required for syntax compliance. The alternative would be to use a concrete T type redundantly.

public void foo(Class<?> clazz) {
    // Do something non-typed, we don't have a type
}

vs.

public <T> void foo(Class<T> clazz) {
    // Do something non-typed, even though we have a type T
}
Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • Thanks. What do you think about this question: 9406025 as a duplicate? It seems a bit broader but is more relevant to what I am asking. I don't mind if there actually is a real duplicate question, I simply want to understand things. – Ash Feb 29 '16 at 08:13
  • In that question he is talking about Class, not Class>, ie more generally. I'm asking more specifically about Class> but that question explains why the Class was introduced. – Ash Feb 29 '16 at 08:21