I notice that in Java 7 ,the collection classes(ConcurrentLinkedQueue in my case) use UNSAFE class for swap and find operations.
The offset seems to be calculated on the compile time declaration:
itemOffset = UNSAFE.objectFieldOffset(local.getDeclaredField("item"));
How would this work in a scenario where we do not have the exact parametrized type at compile time e.g when we try to insert an apple in to a method having Collection<? super Apple> in the declaration.
Does it use 'Apple' as the declared class to calculate offset?
Would appreciate any help in understanding the way UNSAFE works to calculate offsets here.
Jave doesn't allow us to use primitive types as type parameters of generics, only reference types are allowed. Reference types are stored as references that always have the same size, so that internal representation of objects of certain generic class is always the same, no matter how they're parameterized.
Therefore exact type of collection's items doesn't matter, because item is a reference that always has the same size.
Related
Consider the following API method taken from Shiro's org.apache.shiro.subject.PrincipalCollection interface but probably present in other libraries as well:
Collection fromRealm(String realmName);
Yes even nowadays there are still libraries that are using raw-types, probably to preserve pre Java 1.5 compatibility?!
If I now want to use this method together with streams or optionals like this:
principals.fromRealm(realmName).stream().collect(Collectors.toSet());
I get a warning about unchecked conversion and using raw types and that I should prefer using parameterized types.
Eclipse:
Type safety: The method collect(Collector) belongs to the raw type Stream. References to generic type Stream<T> should be parameterized
javac:
Note: GenericsTest.java uses unchecked or unsafe operations.
As I can't change the API method's signature to get rid of this warning I can either annotate with #SuppressWarnings("unchecked") or simply cast to Collection<?> like this:
((Collection<?>) principals.fromRealm(realmName)).stream().collect(Collectors.toSet());
As this cast of course always works I'm wondering why the compilers are not simply treating Collection as Collection<?> but warn about this situation. Adding the annotation or the cast doesn't improve the code a single bit, but decreases readability or might even shadow actual valid warnings about usage of unparameterized types.
The reason is quite simple:
You may read Objects from a Collection<?> the same way as from Collection. But you can't add Objects to a Collection<?> (The compiler forbids this) whereas to a Collection you can.
If after the release of Java 5 the compiler had translated every Collection to Collection<?>, then previously written code would not compile anymore and thus would destroy the backward compatibility.
The major difference between raw type and unbounded wildcard <?> is that the latter is type safe, that is, on a compile level, it checks whether the items in the collection are of the same type. Compiler won't allow you to add string and integer to the collection of wildcard type, but it will allow you to do this:
List raw = new ArrayList();
raw.add("");
raw.add(1);
Actually, in case of unbounded wildcard collections (List<?> wildcard = new ArrayList<String>()), you can't add anything at all to the list but null (from Oracle docs):
Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.
A Collection<?> screams:
Please don't add anything to me. I have a strict content type, ... well uh, I just forgot what type it is.
While a Collection says:
It's all cool ! You can add whatever you like, I have no restrictions.
So, why shouldn't the compiler translate Collection to Collection<?> ?
Because it would put up a lot of restrictions.
A use-case that I can think of as to why Collection is not considered as Collection<?> is let say we have a instance of ArrayList
Now if the instance is of type ArrayList<Integer> or ArrayList<Double> or ArrayList<String>, you can add that type only(type checking). ArrayList<?> is not equivalent to ArrayList<Object>.
But with only ArrayList, you can add object of any type. This may be one of the reason why compiler is not considering ArrayList as ArrayList<?> (type checking).
One more reason could be backward compatibility with Java version that didn't have generics.
I know you can use public fields, or some other workarounds. Or maybe you don't need them at all. But just out of curiosity why Sun leave structures out.
Here's a link that explains Sun's decision:
2.2.2 No More Structures or Unions
Java has no structures or unions as complex data types. You don't need structures and unions when you have classes; you can achieve the same effect simply by declaring a class with the appropriate instance variables.
Although Java can support arbitrarily many kinds of classes, the Runtime only supports a few variable types: int, long, float, double, and reference; additionally, the Runtime only recognizes a few object types: byte[], char[], short[], int[], long[], float[], double[], reference[], and non-array object. The system will record a class type for each reference variable or array instance, and the Runtime will perform certain checks like ensuring that a reference stored into an array is compatible with the array type, but such behaviors merely regard the types of objects as "data".
I disagree with the claim that the existence of classes eliminates the need for structures, since structures have semantics which are fundamentally different from class objects. On the other hand, from a Runtime-system design perspective, adding structures greatly complicates the type system. In the absence of structures, the type system only needs eight array types. Adding structures to the type system would require the type system to recognize an arbitrary number of distinct variable types and array types. Such recognition is useful, but Sun felt that it wasn't worth the complexity.
Given the constraints under which Java's Runtime and type system operate, I personally think it should have included a limited form of aggregate type. Much of this would be handled by the language compiler, but it would need a couple of features in the Runtime to really work well. Given a declaration
aggregate TimedNamedPoint
{ int x,y; long startTime; String name; }
a field declaration like TimedNamedPoint tpt; would create four variables: tpt.x, tpt.y of type int, tpt.startTime of type long, and tpt.name of type String. Declaring a parameter of that type would behave similarly.
For such types to be useful, the Runtime would need a couple of slight additions: it would be necessary to allow functions to leave multiple values on the stack when they return, rather than simply having a single return value of one the five main types. Additionally, it would be necessary to have a means of storing multiple kinds of things in an array. While that could be accomplished by having the creation of something declared as TimedNamedPoint[12] actually be an Object[4] which would be initialized to identify two instances of int[12], a long[12], and a String[12], it would be better to have a means by which code could construct a single array instance could hold 24 values of type int, 12 of type long, and 12 of type String.
Personally, I think that for things like Point, the semantics of a simple aggregate would be much cleaner than for a class. Further, the lack of aggregates often makes it impractical to have a method that can return more than one kind of information simultaneously. There are many situations where it would be possible to have a method simultaneously compute and report the sine and cosine of a passed-in angle with much less work than would be required to compute both separately, but having to constructing a SineAndCosineResult object instance would negate any speed advantage that could have been gained by doing so. The execution model wouldn't need to change much to allow a method to leave two floating-point values on the evaluation stack when it returns, but at present no such thing is supported.
I've a doubt reading this written in the Java tutorial:
In the introduction, we saw invocations of the generic type
declaration List, such as List. In the invocation (usually
called a parameterized type), all occurrences of the formal type
parameter (E in this case) are replaced by the actual type argument
(in this case, Integer).
but if there are no restrictions the formal type parameter is not replaced by Object?
Why is said that E is replaced by Integer?
Also, here, in the Java tutorial is said:
To reference the generic Box class from within your code, you must
perform a generic type invocation, which replaces T with some concrete
value, such as Integer:
but, again, thanks to the erasure a compile time T in box class is replaced
by Object and not by Integer. Integer type is written only for casting operations.
In fact, still in the same tutorial is said:
During the type erasure process, the Java compiler erases all type
parameters and replaces each with its first bound if the type
parameter is bounded, or Object if the type parameter is unbounded.
I'm really confused. Which is the truth?
Is T replaced by Integer or by Object?
You speak of different things.
The citations from the tutorial speak about type instantiation. This has nothing to do with type erasure, which is a IMHO misnamed concept, and simply means that the generic types are not available at runtime anymore.
But at compile time they are, and instantiation happens at compile time.
To answer your question, "at compile time" is a broad thing. THe following hapens all at compile time:
read source files
lexical analysis
parsing
...
type checking
...
code generation
The list is, by no means, complete, mind you.
However, as you see, during type checking, the compiler knows your type instantiations and can check them.
Later, it emits byte code, and since byte code has no way of representing generics, the types are "erased", which means, a cast is inserted here and there.
So, your assumption that "compile time" is somehow an instant where everything happens at once is not correct.
Further edit:
I think you take all this (i.e. the word "replace") too literally. For sure, the compiler has some data structures where the types and names and scopes of all items in the program are held.
Look, it's quite simple in principle, if we have:
static <X> List<X> meth(X[] arr) { .... }
And later, you do:
Integer arr = new Integer[100];
List<Integer> list = meth(arr);
Integer foo = list.get(1);
then you are instantiating the type of the meth method:
static List<Integer> meth(Integer[] arr) { .... }
The point of the generics is to say that meth works for any type. This is just what the compiler checks. And it will know, that, for all X if you pass an array of X, you get back a list of X, hence, since you passed Integer[], the result must be List<Integer> and the list assignment is correct. Furthermore, the compiler knows, that ** for all X **, if you get an element from a List<X>, it will be an X.
Therefore, the compiler notes and checks that foo is an Integer. Later, on code generation, it will insert there a cast to Integer, because, due to type erasure, the return value from List.get is Object.
Note also, that "replace" does not mean that the compiler somehow alters your code. It just creates (maybe temporary) from the generic type signature a non-generic one (by substituting - if you like this better - all the type parameters with their actual types), and uses this to check the type.
It is just like in math, if I say: Please replace the a with 42 and check if the equation is true:
a + 1 = 43
then it makes no sense to ask "where exactly" this replacement takes place. Most probably in your brain.
the formal type parameter is not replaced by Object?
Generic type represented as Object in runtime. But you can get information about <YourType> with reflection. Erasure relates to compatibility with old clases. It was a bad idea. Article about it.
I saw sometimes a type object inside <> beside of another object type declaration.
For instance:
NavigableMap<Double, Integer> colorMap = new TreeMap<Double, Integer>()
or
private final CopyOnWriteArrayList<EventListener> ListenerRecords =
new CopyOnWriteArrayList<EventListener>();
Could you give me an easy explication?
They're known as generics in java, and templates in C++.
http://java.sun.com/developer/technicalArticles/J2SE/generics/
These are called Generics. Here http://java.sun.com/docs/books/tutorial/java/generics/index.html is a tut from sun for them.
As some others said before: Your dealing with Java Generics. They're in Java since SDK 1.5.
E.g:
new CopyOnWriteArrayList<EventListener>()
means that you're creating a new (concurrent) ArrayList which is able to store objects of type EventListener. If you would create an ArrayList the old (pre Java 1.5) way like:
new ArrayList()
All contained objects would be of type Object and you would have to cast them to their real type. See also http://en.wikipedia.org/wiki/Generics_in_Java#Motivation_for_generics.
These are called Generics in Java. They give you a way to tell the compiler what type the collection is going to hold.
http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html
They're called Generics, and allow the compiler to do type checking of contents of lists etc, and also reduces the amount of casting you have to do in your code.
It's also helpful when reading code, as you know what type of object can be put into the item in question, or what type to expect out of it.
Java's implementation isn't as thorough as C++, as Java's is only available at compile time.
At runtime, the type information is no longer available.
In your example TreeMap the key of the TreeMap has type Double and the value referenced by this key has the type Integer. And as already answered it's called generics.
This is an extension introduced in java 1.5. This makes code more readable
They are Generics, classes that are written with one or more types left to be specified later, so they can be used with any type. The generics can be very useful for containers or algorithms, where the algorithm or the data structure used is independent from the actual type stored or manipulated.
I'm refatoring a home-grown DAO container, hoping to make the class generic. It internally uses an ArrayList to store the retrieved objects.
One usage of this class puts the container's list into a request scope, and due to a limitation of Websphere, I can't pass the generic List<Foo> to the request scope (Websphere doesn't handle generics out-of-the-box)
If I go ahead with my refactorings, I will need to convert/cast the List<Foo> into a non-generic List object..
// Boils down to this...
List<Foo> listFoo = new FooListing().findAllFoo();
List listThings = listFoo;
request.setAttribute("listThings", listThings);
What are the implications of reversing a generification like this? Should I avoid doing this kind of manipulation?
EDIT: The code snippet is verbose to explicitly demonstrate what I'm describing..
If the component type of the List does match the expected type, there is no problem.
Generics in Java are only used for type-checks by the compiler, they have not effect at runtime. If you are using an older library that does not support generics, you have no choice but to ignore the generic type.
Things should continue to work, as this system has been designed with backwards compatibility in mind.
So all you are losing is the compile-time type checking (it puts you back to where Java was at 1.4, which means, if the types match, everything will work, if not, you'll get ClassCastExceptions or other unwanted behaviour at runtime).
However, I think you can just write
request.setAttribute("listThings", listFoo);
This method takes any kind of Object. Even if it wanted a List, you could still pass a List<Foo> (which is still a List).
Java uses "type erasure" for generics -- essentially that means that the compiler checks the generics, but the runtime forgets all about it and just treats it as a list of objects.*
Whenever you treat a List<Foo> as just a List, you won't get compiler checks to make sure you don't put a Bla into your list. So you could get a ClassCastException if you call List<Foo>.get() and it turns out to be a Bla hiding in the list. But that can only happen if you some code puts a Bla in your list.
If you wan't to be cautious, then if you pass the List<Foo> as a List to anything that might add a non-Foo to the list, don't treat it as a List<Foo> whenever you access it, but treat it as a list of Objects and add instanceof checks.
*Some of the information is accessible at runtime, but let's not complicate matters.
A "non-generic" version of a generic type is called a "raw type".
Passing a generic type where the raw equivalent is requested is generally ok. This is actually the main reason generics in Java work the way they do (with erasure): to enable interoperability between "generified" code and pre-generics code.
The main thing you need to be careful about is that if you pass a List<Foo> to something that askes for a List, they may put non-Foo objects into the List. You won't get any compile time checking to help you here. You do get some runtime checks: a ClassCastException will be thrown when you use a method that returns a Foo on your List<Foo> and it has to return a non-Foo.
If you want more fail-fast behavior you can wrap your List<Foo> with Collections.checkedList() to get a List that'll check the type of elements on insertion.
Things get more complicated if Foo itself is a generic type. Runtime checks are only done on reified types (ie: the type with generic type parameters removed) so if you give them a List<Set<Bar>> and they insert a Set<Baz> or just a Set, you won't know since the runtime/reified type of the element is Set either way.
First, you can't cast a generic to a non-generic list so yeah you'd have to convert it.
Second, the two main advantages to a generic list are 1) it ensures that all objects are of the specified type and 2) it allows you to directly access methods of the object collection without needing to recast them. This allows you to write cleaner code and saves some processing cycles from having to cast back and fourth.
Neither one of these advantages is a dire need however. If you can't use them you won't notice a difference in performance. Your code may look a little messier though.
I have similar problems with Weblogic Portal. Just use none-generic type for this case.