Using parameterized(Generic) Java class vs normal class
if I need to write a class that works on data of type 'Comparable', I can do it in two ways:
1)
public class MyClass<T extends Comparable>
{
private T value;
MyClass(T value)
{
this.value = value;
}
other code...
}
2)
public class MyClass
{
private Comparable value;
MyClass(Comparable value)
{
this.value = value;
}
other code...
}
which of these tw开发者_JAVA技巧o approaches is better, and why? In general, if and why is it better to use Generics when the same thing can be achieved without using them?
That depends on the rest of your class. If for instance you have a method getValue
, then the generic approach would be preferable, as you could do this:
public class MyClass<T extends Comparable>
{
private T value;
MyClass(T value)
{
this.value = value;
}
T getValue() {
return this.value;
}
other code...
}
Without generics, some of the type-information would be lost, as you could only return a Comparable
.
Generally, it's not. You should use Generics only when you want to add type-safety that wouldn't otherwise exist. Whether that's the case for your example class, we really can't tell; if your class dealt collectively with multiple Comparable
objects, then generics could be used to insist that they all be Comparable<T>
for the same value of T
; but if not, there's probably no reason to use generics here.
Generics give greater compile-time type safety. Because of type erasure, they have no (direct) effect on run-time performance.
That said, your example probably could benefit by using generics. As it stands, it should generate a compiler complaint about using raw types. It would have to be modified to something like this:
public class MyClass<T extends Comparable<? extends SomeBaseClass>>
{
private T value;
MyClass(T value)
{
this.value = value;
}
// other code...
}
Then the compiler could check the types of objects involved to ensure that they are comparable with one another.
When using a generic you can get back the object as it would be declared compile time. Without using generics you have to cast it to the right type when you want to use it. e.g.
//Generic class
class CGeneric<T extends Comparable>
{
private T obj;
public T getObj() { return obj; }
public void setObj(T value) { obj = value;: }
}
//Non-generic class
class CNormal
{
private Comparable obj;
public Comparable getObj() { return obj; }
public void setObj(Comparable value) {obj = value;}
}
When calling getObj on an instance of CGeneric you can use the object as a MyComparable(if you want to use special methods declared there). If you call getObj on a CNormal you get a Comparable(at compile time), and you have to cast it to MyComparable to use the special methods you may have in there.
Thus generics give you compile-time typechecks and you will not encounter a CastException.
The main reason for generics is so only 1 type could be used (type safety). unless you make it then anything can be used. Personally i would go with step 1.
Well the most notable drawback of generics is simple: They're awfully complicated to get exactly right. T extends Comparable? Well will work, but that's a mishmash of generics and non generics. So the first one would possibly try would be T extends Comparable< T> which will work fine, but sadly is too restrictive because assume a class:
class Foo implements Comparable< Object>
So actually the implementation should be T extends Comparable< ? super T>. Nice and not that complicated. But then we get stuff like Enum< E extends Enum< E>> and really, explain that to someone without confusing him - good luck with that.
So Generics are useful and simple to USE, but extremely hard to WRITE correctly (and don't get me started on writing correct binary backwards compatible versions of an existing library - see the collection lib in the JDK). Luckily only a handful of library writers have to get it right for everyone else to profit from it
精彩评论