The efficiency of Java Class.cast() compared to normal cast? - java

I am working on a generic class and I want to use Class.cast() to do some casting to avoid those nasty unchecked cast warnings or the #SupressWarning annotation on the methods.
I think Class.cast() should be basically the same thing as casting directly. But like all reflection methods, it might not be the case. Does anyone know the exact different between them?

I recommend using Class.cast() over #SuppressWarnings where possible.
Don't care about performance here. If you have performance issues, profile your application, and I would be very surprised if this turned out to be a hot spot.

Related

Advantage of #SuppressWarnings annotation

#SuppressWarnings annotation is for cleaner code or by adding it is there any performance gain or any advantage ?
or can we reduce compile time by doing so.
The #SuppressWarnings annotation type allows Java programmers to disable compilation warnings for a certain part of a program (type, field, method, parameter, constructor, and local variable). Normally warnings are good. However in some cases they would be inappropriate and annoying. So programmers can choose to tell the compiler ignoring such warnings if needed.
There is no relation with performance.
The developer who wrote the code knew that it was always going to be safe, decided to use #SuppressWarnings("unchecked") to suppress the warning at compilation.
As mentioned by others, it is just a trust between the developer and code written.
more info here and here
There is no performance gain, only when compiling, compiler will or will not write a waring. However after compilation, there is no difference whatsoever.
It does not make your code cleaner or improve the performance. It just helps you to concentrate your attention on potentially dangerous code. If you have a list of 130 warnings you will soon stop to read them.
Most warnings represents bad programming practices or potencial problems that the compiler is not able to solve. A finished program should, ideally, compile with no warnings. This way, when you modify it and a new warning appears you can decide what to do.
For example:
Unreachable code. What was I thinking here
Lib ZZZ is deprecated. Should I upgrade to the new one? Can I continue with this for now?
Add type arguments to list... ups, I should be using generics
SuppressWarnings annotation is just to suppress warnings that you know are sure to occur and you don't care about it. Its just helps you to have a cleaner inspection, suppressing warnings you expect to see. No performance gain.

Using Generics in a non collection

Saw a couple of similar questions today- got me thinking:
What are the rules for when to use generics?
When a collection is involved?
When there are getter methods which return collection elements?
Whether the object changes type during its lifetime?
Whether the relationship is composition/aggregation to the class?
There doesn't seem to be a consensus on the questions you should ask yourself in order to determine whether you should use generics. Is it purely an opinionated decision?
Is it easier to ask when you shouldn't use generics??
Let me start with some general points about generics and type information before I get back to the first point on your bullet list.
Generics prevent unnecessary type casts.
Do you remember Java before generics were introduced? Type casts were used everywhere.
This is what type casts essentially are: You are telling the compiler about an object's type, because the compiler doesn't know or cannot infer it.
The problem with type casts is that you sometimes make mistakes. You can suggest to the compiler that an instance of class Fiddle is a Frobble ((Frobble)fiddle), and the compiler will happily believe you and compile your source code. But if it turns out that you were wrong, you'll much later get a nice run-time error.
Generics are a different, and usually safer way of letting the compiler retain type information. Basically, the compiler is less likely to make typing mistakes than a human programmer... the less type casts required, the fewer potential error sources! Once you've established that a list can only contain Fiddle objects (List<Fiddle>), the compiler will keep this information and prevent you from having to type-cast each item in that list to some type. (You still could cast a list item to Frobble, but why should you, now that the compiler let's you know that the item is a Fiddle!?)
I have found that generics greatly reduce the need for type casting, so the presence of lots of type casts — especially when you always cast to the same type — might be an indicator that generics should be used instead.
Letting the compiler keep as much type information as possible is a good thing because typing errors can be discovered earlier (at compile-time instead of at run-time).
Generics as a replacement for the "generic" java.lang.Object type:
Before generics, if you wanted to write a method that worked on any type, you employed the java.lang.Object supertype, because every class derives from it.
Generics allow you to also write methods that work for any type, but without forcing you or the compiler to throw away known type information — that's exactly what happens when you cast an object to the Object type. So, frequent use of the Object type might be another indicator that generics might be appropriate.
When a collection is involved?
Why do generics seem an especially good fit for collections? Because, according to the above reasoning, collections are rarely allowed to contain just any kind of object. If that were so, then the Object type would be appropriate because it doesn't put any restrictions whatsoever on the collection. Usually however, you expect all items in a collection to be (at least) a Frobble (or some other type), and it helps if you let the compiler know. Generics are the way how to do just that.
Whether the relationship is composition/aggregation to the class?
You've linked to another question that asks about a class Person having a car property should be made generic as class Person<T extends ICar>.
In that case, it depends whether your program needs to distinguish between Honda people and Opel people. By making such a Person class generic, you essentially introduce the possibility of different kinds of people. If this actually solves a problem in your code, then go for it. If, however, it only introduces hurdles and difficulties, then resist the urge and stay with your non-generic Person class.
Side node: Keep in mind that you don't have to make a whole class generic; you can make only a few specific methods generic. At least in the .NET ecosystem, it is recommended to keep generics as "local" as possible, i.e. don't turn a class into a generic one when it's sufficient to make only a method generic.
I find myself using generics when the following three criteria are met:
I note that I am repeating code, and start thinking of how to refactor it into a new method/class.
The class/method I am rewriting doesn't really care about what the concrete type of one of the arguments is, only that it follows a certain contract (eg <T extends Bar>).
The return type of the method/one of the methods is related to said parameter or
two or more parameters are related and need to have the same type, although I don't really care what that type is.
Usually when these criteria are met, there is a Collection of some kind involved, but not necessarily.
In my opinion the second statement (when not to use them) is correct.
When not to use generics: when the strong typing is too restrictive (typically generics in generics). In some cases you want to ensure loose coupling among your components and the point is "send me what you want, the API will somehow handle it", than you will employ some kind of visitor, rather than specifying complete concrete API using some generic type.
When you should: if you had not, you would have to cast the variable to some type (you even you might have to guess or use instanceof)...
Just one sidenote: every structured type is some kind of collection...
Is it easier to ask when you shouldn't use generics??
To answer this question, one of the major problems with Generics is its treatment for Checked Exceptions. Here is a write-up from Geotz about this.
Reason why you should consider generics, again there is a cache of information shared.

Does using instanceof help and java cast type exception hits performance?

I use legacy library and need use cast Object to Collection.
For avoid exceptions I think to use instanceof.
So questions two:
1. If I use instanceof - need use try.. catch cast exception to avoid exceptions?
2. Does it hits performance?
Thanks.
If you use instanceOf then you do not need try-catch(ClasscastException e). instanceOf is guaranteed to work, even with nulls.
In today's VMs, casting does not show any measurable performance hit. Rather if you find doing casting too often, then revisit your design.
NOTE: instanceof does not work with Generics due to type erasure.
Instanceof does not really hit on performance in modern JVMs, any impact would be negligible.
here's an article on this subject with some figures!
Sometimes, knowing the type of an object during run time is useful, specially in casting. In Java, an invalid cast causes a run-time error. Many invalid casts can be caught at compile time. However, casts involving class hierarchies can produce invalid casts that can be detected only at run time. Java provides the run-time operator instanceof to answer this question. It does not through any exception.
Modern JVM/JIC compilers have removed the performance hit of most of the traditionally "slow" operations, including instanceof, exception handling, reflection, etc.
please refer this stackoverflow link
hence go for instanceof without any worry, but you wont be able to use it in collection they dont work there.
java generics and instanceof

How do you test the type-safetiness of your genericized API?

You can use e.g. JUnit to test the functionality of your library, but how do you test its type-safetiness with regards to generics and wildcards?
Only testing against codes that compile is a "happy path" testing; shouldn't you also test your API against non-type-safe usage and confirm that those codes do NOT compile?
// how do you write and verify these kinds of "tests"?
List<Number> numbers = new ArrayList<Number>();
List<Object> objects = new ArrayList<Object>();
objects.addAll(numbers); // expect: this compiles
numbers.addAll(objects); // expect: this does not compile
So how do you verify that your genericized API raises the proper errors at compile time? Do you just build a suite a non-compiling code to test your library against, and consider a compilation error as a test success and vice versa? (Of course you have to confirm that the errors are generics-related).
Are there frameworks that facilitate such testing?
Since this is not testing in the traditional sense (that is - you can't "run" the test), and I don't think such a tool exists, here's what I can suggest:
Make a regular unit-test
Generate code in it - both the right code and the wrong code
Use the Java compiler API to try to compile it and inspect the result
You can make an easy-to-use wrapper for that functionality and contribute it for anyone with your requirements.
It sounds like you are trying to test the Java compiler to make sure it would raise the right compilation errors if you assign the wrong types (as opposed to testing your own api).
If that is the case, why aren't you also concerned about the compiler not failing when you assign Integers to String fields, and when you call methods on objects that have not been initialized, and the million other things compilers are supposed to check when they compile code?!
I guess your question isn't limited to generics. We can raise the same question to non-generic codes. If the tool you described exists, I'll be terrified. There are lots of people very happy to test their getters and setters(and try to enforce that on others). Now they are happier to write new tests to make sure that accesses to their private fields don't compile! Oh the humanity!
But then I guess generics are way more complicated so your question isn't moot. To most programmers, they'll be happy if they can get their damn generics code finally compile. If a piece of generics code doesn't compile, which is the norm during dev, they aren't really sure who to blame.
"How do you test the type-safetiness of your genericized API?" IMHO, the short answer to your question should be:
Don't use any #SuppressWarnings
Make sure you compile without warnings (or errors)
The longer answer is that "type safety" is not a property of an API, it is a property of the programming language and its type system. Java 5 generics is type safe in the sense that it gives you the guarantee that you will not have a type error (ClassCastException) at runtime unless it originates from a user-level cast operation (and if you program with generics, you rarely need such casts anymore). The only backdoor is the use of raw types for interoperability with pre-Java 5 code, but for these cases the compiler will issue warnings such as the infamous "unchecked cast" warning to indicate that type-safety may be compromised. However, short of such warnings, Java will guarantee your type safety.
So unless you are a compiler writer (or you do not trust the compiler), it seems strange to want to test "type safety". In the code example that you give, if you are the implementor of ArrayList<T>, you should only care to give addAll the most flexible type signature that allows you to write a functionally correct implementation. For example, you could type the argument as Collection<T>, but also as Collection<? extends T>, where the latter is preferred because it is more flexible. While you can over-constrain your types, the programming language and the compiler will make sure that you cannot write something that is not type-safe: for example, you simply cannot write a correct implementation for addAll where the argument has type Collection<?> or Collection<? super T>.
The only exception I can think of, is where you are writing a facade for some unsafe part of the system, and want to use generics to enforce some kind of guarantees on the use of this part through the facade. For example, although Java's reflection is not controlled as such by the type system, Java uses generics in things such as Class<T>, to allow that some reflective operations, such as clazz.newInstance(), to integrate with the type system.
Maybe you can use Collections.checkedList() in your unit test. The following example will compile but will throw a ClassCassException. Example below is copied from #Simon G.
List<String> stringList = new ArrayList<String>();
List<Number> numberList = Collections.checkedList(new ArrayList<Number>(), Number.class);
stringList.add("a string");
List list = stringList;
numberList.addAll(list);
System.out.println("Number list is " + numberList);
Testing for compilation failures sounds like barking up the wrong tree, then using a screwdriver to strip the bark off again. Use the right tool for the right job.
I would think you want one or more of:
code reviews (maybe supported by a code review tool like JRT).
static analysis tools (FindBugs/CheckStyle)
switch language to C++, with an implementation that supports concepts (may require also switching universe to one in which such an implementation exists).
If you really needed to to this as a 'test', you could use reflection to enforce any desired rule, say 'any function starting with add must have an argument that is a generic'. That's not very different from a custom Checkstyle rule, just clumsier and less reusable.
Well, in C++ they tried to do this with concepts but that got booted from the standard.
Using Eclipse I get pretty fast turn around time when something in Java doesn't compile, and the error messages are pretty straight forward. For example if you expect a type to have a certain method call and it doesn't then your compiler tells you what you need to know. Same with type mismatches.
Good luck building compile time concepts into java :P

How to avoid unchecked-conversion-warning in Java, if you use legacy libraries?

I like the generics-feature in java and use it often. But I have a problem, if I use libraries that aren't yet aware of generics. An example are servlets. If you use ServletRequest.getParameterMap() the result will be a raw map, but it includes only String as keys and String[] as values. So I want to assign it to a Map<String, String[]>. But for this assignment I get an warning. How can I avoid this warning with the language, not by simply suppressing the warning with the #SuppressWarnings annotation.
As others have said the warnings cannot be avoided except by suppressing them. The issue IMHO is that either you have to litter your code with annotations that apply to small scope or ignore them globally and risk errors.
IIRC there is a proposal to generate warnings where the raw types are being returned instead of at the call.
Meanwhile, I think the best approach is to use a wrapper method so that the warnings are limited to a single place, where it is safe to ignore them:
class NoWarn {
public static Map<String, String[]> getParameterMap(ServletRequest r)
{
#SuppressWarnings("unchecked")
Map<String, String[]> result = r.getParameterMap();
return result;
}
}
Note
This answer was edited with a comment that annotations cannot be inside method bodies. That is incorrect, the above is syntactically correct. I have reverted the change.
The cleanest thing you can do is to encapsulate the conversion from legacy to generic code and suppress the warning only there.
E.g. you could put a generic facade on your legacy library, though this might not always be worthwhile.
How can I avoid this warning with the
language, not by simply suppressing
the warning with the
SuppressWarnings-annotation.
The annotation is the way to avoid the warning with the language. There is no other way.
Stumbled upon this question as I was also trying to figure out a way to avoid using the suppress annotation in such cases. I found another alternative which I thought was worth mentioning:
Map<?, ?> map = servletRequest.getParameterMap();
String[] values = (String[]) map.get("key");
We are basically using wildcard '?' to indicate that the map can have any type of key and value.
Potential downside I see here is that we are doing an explicit cast while fetching values, which I think will result in a slight performance overhead during runtime.
I don't think you can. The warning will appear unless you suppress it, or filter it from your IDE's warnings list.
I had the same problem, i just turned off all generic warnings and im happy :) You could also turn off serialVersionUID warning since many people dont use serialVersionUID.
in Eclipse - Window/Perferences/Java/Compiler/Errors/Warnings and turn off all Generic types.
P.S. Many bad warnings make you ignore all the warnings and some might be usefull.
as others said, the only way to get rid of this warning is to suppress it.
the best practice is to encapsulate the warning using methods and classes.
but with other warnings, always try to solve the problem that are making them, like remove unused imports and etc... it makes your application leaner and better.
happy coding

Categories