What is java.lang.Class<?>[] in java . Specifically what is <?>.
I am a beginner in java , I cannot figure out what is the meaning of <?>
Thanks,
Puneet
A type argument for a parameterized type is not limited to a concrete
class or interface. Java allows the use of type wildcards to serve as
type arguments for parameterized types. Wildcards are type arguments
in the form "?", possibly with an upper or lower bound. Given that the
exact type represented by a wildcard is unknown, restrictions are
placed on the type of methods that may be called on object of the
parameterized type.
Source:
Generics In Java
Also:
Wildcards in Generics
Instances of the class Class represent classes and interfaces in a running Java application. The <?> part indicates that a Class can be a represantation of any java object, basicly. This is Java Generics.
<?> means any type.
Since all java classes directly/indirectly inherit Object, you can simply think of <?> as <Object>, although this is not so precise.
Related
I have an equals() method that contains this code:
if (other instanceof Peach<K, V>) {
...
}
However, this does not compile. How to fix this line of code?
As already pointed out, this is not possible. I would like to add that this is because of what is known as Type Erasure. The official Java tutorial has the following short summary:
Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety.
Generate bridge methods to preserve polymorphism in extended generic types.
Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.
The key here is "The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.". Because of this, it is not possible, to do the instanceof check you seek to do.
In short, you can't. Java erases generics types, so, at runtime, you don't have this information anymore.
You can use
if (other instanceof Peach) {
...
}
I am reading through AngelikaLangerDoc. I am reading it after a gap of almost three days.
In my earlier lesson, i learnt that, arrays of unbounded wild card are allowed to be created.
I also studied unbounded wild-card parameterized types are called Reifiable types. When i searched
the definition of reifiable type, it states that, a type whose type information is known at run-time
is called reifiable type. Picking a code snippet from the article.
Pair<?,?>[] iniPair = new Pair<?,?>[10];
I have the following confusion in mind.
Why we say unbounded wild-card parameterized type is called reifiable?
In example above, how the type information is known?
I know it's a basic question. I am just trying to get back the refresher to get back on
track of Generics. Can anyone elaborate on this issue?
From that website:
the reifiable types in Java are only those types for which reification does not make a difference, that is, the types that do not need any runtime representation of type arguments
There is no type information in the wildcard parameters, therefore nothing is lost by erasure.
Since Java compiler replace all unbounded type parameters to Object.
According to Type Erasure
To implement generics, the Java compiler applies type erasure to:
1.Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode,
therefore, contains only ordinary classes, interfaces, and methods.
2.Insert type casts if necessary to preserve type safety.
3.Generate bridge methods to preserve polymorphism in extended generic types.
The term Reifiable according to Javadoc
A reifiable type is a type whose type information is fully available at runtime. This includes primitives, non-generic types, raw types, and invocations of unbound wildcards.
I've thought java erasure wipes generic types out in compile time however when i test it by myself i realized there are some information about generic types in Bytecode.
here is my test :
i wrote 2 classes:
import java.util.*;
public class Test {
List integerList;
}
and
import java.util.*;
public class Test {
List<Integer> integerList;
}
i compiled both classes and somewhere in generic class i saw this line
integerList{blah blah}Ljava/util/List;{blah blah}
Signature{blah blah}%Ljava/util/List<Ljava/lang/Integer;>;{blah blah}<init>
in non generic class :
integerList{blah blah}Ljava/util/List;{blah blah}<init>
so obviously i have generic information inside bytecode so what is this erasure thing ??
what is this erasure thing ??
Erasure is a mapping from generic to raw types. The common phrase "because of erasure" is essentially meaningless. What is significant are the specifications that use the mapping.
There are two interesting uses.
It's used to map method signatures from using generics to raw types. It is the raw-type signatures that used for overloading. This causes the vast majority of the problems with "erasure". For instance, you can't have two methods add(List<String>) and add(List<Integer>) in the same type. Overloading probably isn't a great idea, and there's not a great willingness to add this feature.
The type available for an instance of an object at runtime is the type it was created with erased. So if you cast to, say, (String) that will be checked at runtime, but if you cast to List<String> only the erasure of that type (List) will be checked. You can have the variables of type List<String> and List<Integer> point to exactly the same instance. In practice, you shouldn't be using casts (of reference types) in 1.5 and later.
Where practical, generic information is kept in class files and made available through reflection. So you'll find it on class definitions, supertypes, fields, methods, constructors, etc.
Some Generic type information is stored in Signature attributes . Refer JLS 4.8 and 4.6 and JVM spec 4.3.4. Read here:
Probably the most common complaint about generics in Java is that they are not reified - there is not a way to know at runtime that a List<String> is any different from a List<Long>. I've gotten so used to this that I was quite surprised to run across Neil Gafter's work on Super Type Tokens. It turns out that while the JVM will not track the actual type arguments for instances of a generic class, it does track the actual type arguments for subclasses of generic classes. In other words, while a new ArrayList<String>() is really just a new ArrayList() at runtime, if a class extends ArrayList<String>, then the JVM knows that String is the actual type argument for List's type parameter.
and Neal Gafter's blog.
This is one instance where accurate use of terminology actually matters: Bytecode is the instruction set of the Java Virtual Machine. A class file contains bytecode, but also information used for linking (field signatures, method signatures, ...), for the bytecode verifier, for the debugger, ...
Type erasure means that generic type informations is not translated into byte code; more specifically, all instances of a generic type share the same representation in byte code. Likewise, the dynamic type of an object the runtime keeps track of (as used by the cast and instanceof operators, and available through getClass()) is the same for all instances of a generic class, irrespective of any type parameters supplied in the source code.
Your experiment proves that generic type information is retained in the class file, more specifically, in the types of method and field signatures. That's unsurprising, because the signatures are actually used at compile time. The might also be used at link time, and are even accessible through the reflection api. The crucial difference is that they are the declared types of fields or methods, not the runtime types of actual objects.
That is, since Java 1.5 we must distinguish between a variable's declared type, and the runtime type of the object it refers to. The former supports generics, the latter does not. And yes, this means there isn't a one-to-one correspondence between compile time and runtime types.
Type info will be erased from here
integerList = new ArrayList<Integer>();
in the bytecode it will be equivalent to
integerList = new ArrayList();
and there is no chance to know in runtime from integerList object what was its compile time type.
Erasure means that generic typing is not incorporated in the byte code (when the list is created or used).
The signature you see is used just to indicate that the field is generic.
How can you determine what type of object a generic is using at runtime ?
Due to type erasure, you cannot determine the actual type parameter(s) of a generic object instance. The best you can do is set things up so you can pass a class object to code that needs to know the actual type. For example, this is what java.util.EnumMap does in one of its constructor.
If you mean the T in List<T> (for instance), you can't, because Java uses type erasure. At runtime, a List<T> just looks like a List. This is true except in the edge case of anonymous classes, where it's possible if you jump through hoops to find the parameter type. But in the general case, you cannot. You usually have to communicate that information separately.
First we explain What is Generic
Generic in Java is one of important feature added in Java 5,
From Oracle's documentation:
Generics were introduced to the Java language to provide tighter type
checks at compile time and to support generic programming. To
implement generics, the Java compiler applies type erasure to:
Replace all type parameters in generic types with their bounds or
Object if the type parameters are unbounded. The produced bytecode,
therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety.
Generate bridge methods to preserve polymorphism in extended generic types.
Type erasure ensures that no new classes are created for parameterized
types; consequently, generics incur no runtime overhead.
Now how to make possible to get the generic type on runtime, with the help of this link
read: http://www.west-wind.com/weblog/posts/2011/Nov/11/Dynamically-creating-a-Generic-Type-at-Runtime
It is not possible to get the object type of "Generics" at run time. If we use object.getclass(), so we can get object of any class with the class name.
What does this work without a type?
ArrayList l = new ArrayList();
Does it just default to type object if you don't specify a type, and that cast everything to object?
And what does it mean in the api when it says ClassType (won't display) a question mark within less than greater than signs.
That's called a raw type. Avoid raw types where possible, as they reduce type safety.
Basically they're there for backward compatibility, so that when generics were introduced, existing code still compiled. As ever, see the Java Generics FAQ for more details.
Note that using a raw type is not the same as using a type with a type argument of Object, as raw types have all traces of generics removed from their effective API - even generic methods using other type parameters. That's part of what makes them dangerous.
Does it just default to type object if you don't specify a type, and that cast everything to object?
Yes. That's almost* right.
A generic type (such as ArrayList) which is not provided with type parameters is called a raw type. Raw types are covered in the official trail Type Erasure:
For instance, Box<String> is translated to type Box, which is called the raw type — a raw type is a generic class or interface name without any type arguments. This means that you can't find out what type of Object a generic class is using at runtime.
[...]
Type erasure exists so that new code may continue to interface with legacy code. Using a raw type for any other reason is considered bad programming practice and should be avoided whenever possible.
*) You can put any Object into an ArrayList, but as #newacct points out in the comments, ArrayList is not to be considered the same as ArrayList<Object>, since ArrayList (and ArrayList<?> btw) are both supertypes of ArrayList<WhatEver>, while ArrayList<Object> is not.
Yes.
This is how Java used to work before generics were introduced. And in fact, this is still how it works, under the hood. The compiler performs basic type-checking, and then performs type erasure, so the bytecode that you're left with will be identical to that of the above.
You'll find a zip file in the root of the directory where you installed your JDK. In there, there is an src.zip.
I use eclipse as an IDE. In that you can attach the source so when you push CTRL+SHIFT+T and type ArrayList you'll be able to see it's source yourself ;)
Actually it is also a good way to see how more expert ppl write source-code :)