I need to make use of reflection in java. I understand that Class clazz creates a variable representing a Class object. However, I am trying to reference a Class object from a String using the forName("aClassName") method. My IDE (Eclipse), seems to prefer the notation Class<?> clazz for declaring the variable. I have seen this notation many times elsewhere. What does this mean?
Edit: Removed reference to ternary operator as it is not relevant to this question.
Class is a raw type - it's basically a generic type that you're treating as if you didn't know about generics at all.
Class<?> is a generic type using an unbound wildcard - it basically means "Class<Foo> for some type Foo, but I don't know what".
Similarly you can have wildcards with bounds:
Class<? extends InputStream> means "Class<Foo> for some type Foo, but I don't know what so long as it's InputStream or a subclass"
Class<? super InputStream> means "Class<Foo> for some type Foo, but I don't know what so long as it's InputStream or a superclass"
See also the Java Generics FAQ for a lot more information:
Raw types
Wildcards
And the Java Language Specification:
Raw types (section 4.8)
Type arguments and wildcards (section 4.5.1)
In particular, from the raw types section:
Raw types are closely related to wildcards. Both are based on existential types. Raw types can be thought of as wildcards whose type rules are deliberately unsound, to accommodate interaction with legacy code. Historically, raw types preceded wildcards; they were first introduced in GJ, and described in the paper Making the future safe for the past: Adding Genericity to the Java Programming Language by Gilad Bracha, Martin Odersky, David Stoutamire, and Philip Wadler, in Proceedings of the ACM Conference on Object-Oriented Programming, Systems, Languages and Applications (OOPSLA 98), October 1998.
The first thing to realize is that, in this case, the "?" is NOT the ternary operator, but is part of Java's generics implementation and indicates that the type of Class is unspecified, as some of the other answers have already explained.
To clarify the question about the ternary operator, it is actually very simple.
Imagine you have the following if statement:
boolean correct = true;
String message;
if (correct) {
message = "You are correct.";
} else {
message = "You are wrong.";
}
You can rewrite that with the ternary operator (think of it as the if-else-shortcut operator):
message = (correct) ? "You are correct." : "You are wrong.";
However, it's best to avoid the ternary operator for all but the simplest statements in order to improve the readability of your code.
In generic types the wildcard ?means "whatever class" (so Class<?> is the same as just Class but as raw type correctly parametrized).
Related
Why do generics in Java work with classes but not with primitive types?
For example, this works fine:
List<Integer> foo = new ArrayList<Integer>();
but this is not allowed:
List<int> bar = new ArrayList<int>();
Generics in Java are an entirely compile-time construct - the compiler turns all generic uses into casts to the right type. This is to maintain backwards compatibility with previous JVM runtimes.
This:
List<ClassA> list = new ArrayList<ClassA>();
list.add(new ClassA());
ClassA a = list.get(0);
gets turned into (roughly):
List list = new ArrayList();
list.add(new ClassA());
ClassA a = (ClassA)list.get(0);
So, anything that is used as generics has to be convertable to Object (in this example get(0) returns an Object), and the primitive types aren't. So they can't be used in generics.
In Java, generics work the way that they do ... at least in part ... because they were added to the language a number of years after the language was designed1. The language designers were constrained in their options for generics by having to come up with a design that was backwards compatible with the existing language and the Java class library.
Other programming languages (e.g. C++, C#, Ada) do allow primitive types to be used as parameter types for generics. But the flip side of doing this is that such languages' implementations of generics (or template types) typically entail generation of a distinct copy of the generic type for each type parameterization.
1 - The reason generics were not included in Java 1.0 was because of time pressure. They felt that they had to get the Java language released quickly to fill the new market opportunity presented by web browsers. James Gosling has stated that he would have liked to include generics if they had had the time. What the Java language would have looked like if this had happened is anyone's guess.
In java generics are implemented by using "Type erasure" for backward compatibility.
All generic types are converted to Object at runtime.
for example,
public class Container<T> {
private T data;
public T getData() {
return data;
}
}
will be seen at runtime as,
public class Container {
private Object data;
public Object getData() {
return data;
}
}
compiler is responsible to provide proper cast to ensure type safety.
Container<Integer> val = new Container<Integer>();
Integer data = val.getData()
will become
Container val = new Container();
Integer data = (Integer) val.getData()
Now the question is why "Object" is chose as type at runtime?
Answer is Object is superclass of all objects and can represent any
user defined object.
Since all primitives doesn't inherit from "Object" so we can't use it
as a generic type.
FYI : Project Valhalla is trying to address above issue.
As per Java Documentation, generic type variables can only be instantiated with reference types, not primitive types.
This is supposed to come in Java 10 under Project Valhalla.
In Brian Goetz paper on State of the Specialization
There is an excellent explanation about the reason for which generic were not supported for primitive. And, how it will be implemented in future releases of Java.
Java's current erased implementation which produces one class for all reference instantiations and no support for primitive instantiations. (This is a homogeneous translation, and the restriction that Java's generics can only range over reference types comes from the limitations of homogeneous translation with respect to the bytecode set of the JVM, which uses different bytecodes for operations on reference types vs primitive types.) However, erased generics in Java provide both behavioral parametricity (generic methods) and data parametricity (raw and wildcard instantiations of generic types.)
...
a homogeneous translation strategy was chosen, where generic type variables are erased to their bounds as they are incorporated into bytecode. This means that whether a class is generic or not, it still compiles to a single class, with the same name, and whose member signatures are the same. Type safety is verified at compile time, and runtime is unfettered by the generic type system. In turn, this imposed the restriction that generics could only work over reference types, since Object is the most general type available, and it does not extend to primitive types.
The collections are defined to require a type which derives from java.lang.Object. The basetypes simply don't do that.
I was reading and reviewing the following site and had a question.
https://www.geeksforgeeks.org/angle-bracket-in-java-with-examples/
In the explanations below they show class definitions followed by <T> and then when actually implementing these classes they use different types such as or as the parameters. My question is: is the '' notation actually a defined syntax in Java? In particular, is the T a necessary thing in order to define a "Generic"? And then does it basically mean that the parameters can be of multiple different types? Also, if anyone can reword or explain in simpler terms what the meaning of a generic is that would be very helpful. Thanks.
The <T> is indeed a syntax defined by Java, but you can use whatever name you want to name a type, you don't need to use T, for example this is valid:
public class Box<MyType> {
private MyType t;
public void set(MyType t) { this.t = t; }
public MyType get() { return t; }
}
But, stick with T or other common type names, as other people are already used to seeing those as the "generic types" so it makes reading your code simpler.
I recommend you read Java's Trail about Generics, where you can find the most commonly used type parameter names:
E - Element
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types
As for "what the meaning of generics is", check this other page.
It’s defined syntax since Java 5. You need a type parameter (one or more) for defining a generic. The type parameter needs not be called T, any Java identifier will do. A single uppercase letter is conventional, and T for type is what we often pick if we haven’t got a specific reason for some other letter.
The actual type parameter has to be a reference type. Values still always go into actual parameters in round brackets, not into type parameters (unlike in C++, for example). You can make a new ArrayList<Integer>(50), a list of Integer objects with an initial capacity for 50 of them.
That the actual type parameter has to be a reference type means that you can have a List<String>, a List<LocalDate> or a list of an interface type that you have declared yourself, even a List<int[]>. In the Java versions I have used (up to Java 10) the type parameter cannot be a primitive type (like int), but it can be an array type (like int[] or String[][], though often impractical). Allowing primitive types may come in a future Java version.
Link: Similar question: What does < T > (angle brackets) mean in Java?
The Java Guidelines for Wildcard Use says:
Using a wildcard as a return type should be avoided because it forces programmers using the code to deal with wildcards.
The Object getClass method returns a Class<?>. The various methods in Class accept a Class<?> and if you pass in a Class the compiler returns an unchecked warning. This leads me to think that always using Class<?> is preferable.
If I have a method which returns a Class, and I don't know how that object will be used, which type should I return Class or Class<?>? Why? Are there any scenarios in which I might want to return simply Class?
Using MyType<?> is always preferable to using a raw MyType (and this extends to Class). The guidelines take it as a given that new code will not use raw types, which are only supported for backwards compatibility. They are not suggesting you abandon generics when ? is the best you can do.
By using the wildcard parameter, the compile-time type safety guarantees of generics still hold. These guarantees only exist in the absence of casts and raw types.
If you want to return a type that is generic then using a wildcard is definitely preferable to using a raw type - if you start using raw types in your code then that effectively switches off all the other type safety checks you would gain from using generics properly.
The guideline says wildcards should be avoided, not that they must not be used. You should use the most specific type that makes sense in a given scenario, which may be a concrete instantiation of the type parameters, a bounded extends or super wildcard, or an unbounded wildcard, but any of these is a better choice than a raw type.
Java lesson on generics are leading me to variance concept. This causes me some headaches as I cannot find a very simple demonstration of what it is.
I have read several similar questions on stackoverflow, but I found them too difficult to understand for a Java learner. Actually the problem is that the explanation of generics requires variance to be understood, and the concept of variance is demonstrated relying heavily on generics understanding.
I had some hope reading this, but in the end I shared C. R.'s feeling:
The title reminds me of the days learning general relativity. – C.R.
Dec 22 '13 at 7:34
Four theory questions are very confusing to me, and I cannot find good and simple explanations. Here they are, with my current partial understanding (I fear experts will have a great fun reading this).
Your help to correct and clarify is welcome (remember this is for beginners, not for experts).
Is there something wrong with this understanding?
What is invariance / covariance / contravariance related to in the context of programing? My best guess is that:
This is something encountered in object-oriented programing.
This has to do when looking at method arguments and result type in the class and an ancestor.
This is used in the context of method overriding and overloading.
This is used to establish a connection between the type of a method argument, or the method return type, and the inheritance of the classes themselves, e.g. if class D is a descendant of class A, what can we say about the types of arguments and the method method return type?
How variance relates to Java methods? My best guess is that, given two classes A and D, with A being an ancestor of D, and a overhiden/overloaded method f(arg):
If the relation between the argument type in the two methods IS THE SAME than the relation between the two classes, the argument type in the method is said COVARIANT with the class type, said otherwise: the inheritance between arg types in A and D is covariant with the inheritance of classes A and D.
If the relation between the arguments REVERSES the relation between classes, the arg type is said CONTRAVARIANT to the class type, said otherwise: the inheritance between arg types in A and D is contravariant with the inheritance of classes A and D..
Why is variance understanding so important for Java programmers? My guess is that:
Java language creators have implemented rules for variance in the language, and this has implications on what a programmer can do.
A rule states that the return type of an overriding/overloading method must be contravariant to the inheritance.
Another rule states that the type of an argument of an overriding/overloading must be is covariant to the inheritance.
The Java compiler checks the variance rules are valid, and provides errors or warnings accordingly. Deciphering the messages is easier with variance knowledge.
What is the difference between overrhiding and overloading? Best guess:
A method overrides another method when argument and return types are both invariant. All other cases are understood by the compiler as overloading.
This is not specific to OO, but has to do with the properties of certain types.
For example, with the function type
A -> B // functional notation
public B meth(A arg) // how this looks in Java
we have the following:
Let C be a subtype of A, and D be a subtype of B. Then the following is valid:
B b = meth(new C()); // B >= B, C < A
Object o = meth(new C()); // Object > B, C < A
but the follwoing are invalid:
D d = meth(new A()); // because D < B
B b = meth(new Object()); // because Object > A
hence, to check whether a call of meth is valid, we must check
The expected return type is a supertype of the declared return type.
The actual argument type is a subtype of the declared argument type.
This is all well known and intuitive. By convention we say that the return type of a function is covariant, and the argument type of a method is contravariant.
With parameterized types, like List, we have it that the argument type is invariant in languages like Java, where we have mutability. We can't say that a list of C's is a list of A's, because, if it were so, we could store an A in a list of Cs, much to the surprise of the caller, who assumes only Cs in the list. However, in languages where values are immutable, like Haskell, this is not a problem. Because the data we pass to functions cannot be mutated, a list of C actually is a list of A if C is a subtype of A. (Note that Haskell has no real subtyping, but has instead the related notion of "more/less polymorphic" types.)
How does Java do this? If there are not multiple Classes being created, then how does it support multiple Typed instantiations of the Generic class?
Until now I used to believe that it is like C++, but now i am totally confused.
Can't figure out how Java pulls this off?
-Ajay
This is due to type erasure. Java's generics are primarily a compile-time feature. All generic types are, at runtime, Objects replaced with their lower bound.
Thanks to Michael for the correction:
Generics are not strictly a compile-time feature. If a class, method or field has a generic type with a concrete type parameter specified, this information will be present at runtime and is available via reflection.
To elaborate:
When runtime inspecting a parameterizable type itself, like java.util.List, there is no way of knowing what type is has been parameterized to. This makes sense since the type can be parameterized to all kinds of types in the same application. But, when you inspect the method or field that declares the use of a parameterized type, you can see at runtime what type the paramerizable type was parameterized to. In short:
You cannot see on a type itself what type it is parameterized to a runtime, but you can see it in fields and methods where it is used and parameterized. Its concrete parameterizations in other words.
Source
Since only reference types can be used as generic type arguments in Java, and all pointers are the same size, the same byte code can be used.
As for type safety, generics in Java a compile/link-time only. That is, during compilation generic types are replaced by their erasure. The erasure of a type variable T is its lower bound (or Object, if it doesn't have one). For instance,
class Complex<N extends Number> {
N real;
N imag;
}
becomes
class Complex {
Number real;
Number imag;
}
as far as byte code is concerned.
Needless to say that is not pretty and causes numerous limitations. The most obvious one is that
new N();
does not compile, because the runtime does not know the type N stands for and hence can't instiate the type. Similarly,
(N) n
will compile, but unlike an ordinary cast in Java, will not be checked at runtime. An incorrect cast can therefore cause a variable to hold an object of the wrong type. This is called heap pollution. To ensure (a weaker form of) type safety, the compiler will introduce casts into calling code. For instance,
boolean right(Complex<Integer> c) {
return c.real > 0;
}
will become
boolean right(Complex c) {
return ((Integer) c.real) > 0;
}
To sum things up, the generics implementation in Java is not pretty, especially compared to the .NET one. The things we have to live with for the sake of backwards compatibility ...
good question. The genetic information is not kept during runtime. E.g if you have this code
List<Apple> apples = new ArrayList<Apple>(); // this is a list of apples
But in runtime it becomes :
List apples = new ArrayList(); // this is how it looks in runtime