I'm learning programming in java using generic types and got a probably very basic question.
Where's the difference between the further two snippets?
1.)
public void build(House house) {
// work only with house objects that extending House
}
2.)
public <T extends House> void build(T house) {
// work only with house objects that extending House
}
There is no difference between these two methods with respect to what they can take in as parameters; however, in the latter example, one does have access to the specific type T. Regardless, this example does not illustrate the power of generics.
As an example consider a LinkedList of Node<T> objects. We can define a wrapper, Node<T>, which can hold an object of any type. This is a very useful construct, as it allows us to write one piece of code that can be used for many different objects.
The difference is that inside the second function you have access to type type T, the type the caller used to access your method.
I can't think however of any way to use that type that would differ meaningfully from using House directly. It might make a difference with some other parameters or return types of the method.
They are logically the same.
Although, on the second case the compiler can make some advanced verifications.
Let´s say there is are two subclasses of House called XHouse and YHouse.
We have the following source code:
XHouse house = build(yHouse)
This will fail if yHouse is an object of type YHouse and YHouse is not a subclass of XHouse.
Think of a generic as a sort of template. When you fill the generic argument, you sort of create a new method. In the example above, the usage of the generic method is virtually creating the following:
public XHouse void build(XHouse house) {
// work only with XHouse objects that extending XHouse
}
Notice I even changed the comments.
Related
I have a class with a type parameter.
class MyObject<IdType> {
#Setter
#Getter
private IdType id;
}
And I thought I can add some method for conveniency so I did.
<T extends MyObject<? super IdType>> void copyIdTo(T object) {
object.setId(getId());
}
< T extends MyObject<? extends IdType>> void copyIdFrom(T object) {
object.copyIdTo(this);
}
And I just realized that I can do this.
void copyIdTo(MyObject<? super IdType> object) {
object.setId(getId());
}
void copyIdFrom(MyObject<? extends IdType> object) {
object.copyIdTo(this);
}
Are those two sets of methods are equivalent? Which way (or style) is prefer?
In your case, the two approaches are effectively equivalent. They both restrict the argument's type to MyObject<...> or a subtype.
Since your example methods return void there's no real benefit from making the method generic. The only important thing for your method is that the argument is a MyObject<...>—beyond that the real type is meaningless. Adding the ability to make the argument's type more specific adds nothing for the method's implementation and does nothing for the caller. In other words, it's irrelevant "fluff".
So for your examples, I would say prefer the non-generic option. It's cleaner and more straightforward.
However, if your methods returned the given argument back to the caller then making the method generic could prove useful; it would allow you to declare the return type as T. This opens up possibilities to the caller such as method chaining or invoking the method "inside" another method call, all based on the specific type passed as an argument. An example of this in the core library would be Objects.requireNonNull(T).
Another good case for making the method generic is mentioned by #Thilo in the comments:
Another case would be if your method takes multiple arguments. Then you can introduce a T to make sure those two arguments have the same type (instead of two distinct types that happen to [fulfill] the constraints individually).
Yes they are equivalent. Both sets of methods declare the same thing - that the method parameter must be of type MyObject<> or a compatible subtype (subclass).
The only reason to declare T in this way is if you need to refer to T elsewhere, such as the return type of the method, or if you have multiple parameters of the same type, or inside the method body.
I would always prefer the shorter, simpler, clearer version with less angle brackets to hurt the eyeballs :)
The Java class Class<T> being Generic is confusing because of following reasons.
Imagine a class Cake<T>{}
So you can create
new Cake<Pineapple> and new Cake<Apple> etc
If each class e.x Apple has a parameterizable Class Object, and If class Class is generic, then it seems like a possibility to create Apple<Something> or Integer<Something>, which does not make any sense.
I dont know what i am perceiving wrongly here. It seems like inception, but a deeper level is the same level as above level.
Assume below generic Class
public class Cake<T> {
T cakeType;
void setCakeType(T cakeArg){
this.cakeType = cakeArg;
}
void doStuff(){
System.out.println(cakeType.toString());
}
}
Assume Pineapple is the non generic class as Parameter type for Cake
public class Pineapple {
#Override
public String toString() {
return "I am a Pineapple";
}
}
If class Class was not generic, then by intuition, there will be Pineapple Class object
But as class Class<T> itself is generic. Then it seems like a possibility to create parameterizable class object of Pineapple i.e Pineapple<Something>.
Base Assumption: There is only one Class Object for each class. What is the sense about parameterizing it ?
I'll try to tackle this from a few different approaches; I think there's a fundamental disconnect between what's happening, so a scattershot approach might have a better chance of one of the points making it all "click."
The hierarchy
So, firstly, don't think of Apple as having a Class object; rather, there is an Apple class, and, sitting next to it, a Class object which describes it. But that Class object just exists on its own, and is not part of Apple's hierarchy. It's not Apple's parent; it's its best friend.
The base class for all classes is Object, not Class. Now, if Object were parameterized, you'd have something along the lines of what you're describing -- but it's not. Since Class is not part of Apple's hierarchy, it does not logically follow that Class being parametrized makes Apple parameterized.
By analogy to other generic classes
The point of a Class object is to talk about other objects -- to tell us things like "this is a T," or "here's how you create a T." So, how does each instance tell us at compile-time which kind of things it's talking about? Via the parameter.
Similarly, the point of a List object is to talk about other objects -- to put them into a group together. And it also uses the generic parameter to describe the kinds of things it talks about. With a List, you can tell what's in it just by the type signature: a List<String> concerns Strings while a List<Integer> concerns Integers. Well, in just the same way, a Class<String> talks about Strings while a Class<Integer> talks about Integers. The fact that Class is parameterized has no more effect on String or Integer than does the fact that List is parameterized.
In other words: at the highest level, List<String> does things with Strings. So does a Class<String>
Some use cases
Finally, it may be helpful to think about why Class is parameterized. There are only a few methods on Class that return the T type. Let's take a look at two of them:
T newInstance()
T cast(Object o);
If Class were not parameterized, both of these would return Object. You'd have to do something like this:
Class<Apple> appleClass = ...;
Apple newApple = (Apple) appleClass.newInstance();
Apple existingApple = (Apple) appleClass.cast(existingObject);
Okay, as such that's not too bad. But in this case, we already knew the type of thing we were interested in (an Apple). That's why we could add the Apple casts, but by the same token, it's why using the Class<Apple> isn't useful. That snippet above would be better off just being done as:
Apple newApple = new Apple();
Apple existingApple = (Apple) existingObject;
Instead, the generic aspect of classes are most often useful when you're in a method that is itself generic. For instance:
<T> T tryConsume(Consumer<T> consumer, Object item, Class<T> consumeClass) {
T itemCasted = consumeClass.cast(item);
consumer.consume(itemCasted);
}
Granted, this example isn't very interesting. But the one thing I'll point out is that without the consumeClass, you would have to cast item to (T). Due to type erasure, this would actually be a no-op at runtime, and if the item were of the wrong class, the ClassCastException would come in from a weird, generated line within the consumer code -- not from within tryConsume, where it's nice and clear. To make that cast method actually do the cast, and do it usefully, you need consumeClass.cast(item) to return a T. And to do that, consumeClass has to be of type Class<T>.
I am learning about generics in Java, and was wondering if this would be considered poor coding.
If I declare an ArrayList<Object> I know that I can put any type of object into this list, as all objects descend from Object. I also know that when I call ArrayList.remove(index) the object that gets taken out of the array is of type Object, and that I need to typecast it to the type of object that I want to use.
Now suppose I have object of Dog, Cat, and Car. Would it be bad to put all three objects into the array, considering they are not similar classes?
Let us revise the definition of a Collection, as found in the Java Introduction to Collections tutorial:
A collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data. Typically, they represent data items that form a natural group [...].
Look at the bold words. That should give you your answer.
If you put objects in ArrayList which do not belong to same implementations, you are definitely inviting trouble in situations when you want to retrieve objects from the list and typecast them to appropriate types. So you should AVOID doing that.
Consider you store objects of Dog and Car in ArrayList.
Then for each object stored, you want to call some method, say barkLoudly(). Now,this method will work fine with the Dog object. But when this is called on Car, boooom....An Exception will arise.
I think the answer is "usually, but not always." There's not a lot of hard and fast rules in coding; if you look hard enough you can always find an exception. But if you pull objects out of a collection that you then have to cast to the correct type, that's usually a design error.
Try to make code so that the objects you work with already have the correct type for what you want to do. If you don't need to cast, then Object can be fine. If you do need to cast, you should probably rethink your design.
The design will be really bad, to avoid all such kind of issues, Generics were introduced.
But the same you can achive using below, provided you have same type of objects.
Cat and Dog extends Animal
Car and Bike extends Vehicle
But do not mix the the above two statements.
Animal class:
public abstract class Animal {
protected String name;
}
Dog class:
public class Dog extends Animal {
public Dog(String name) {
this.name=name;
}
}
Cat class:
public class Cat extends Animal {
public Cat(String name) {
this.name=name;
}
}
Main class:
public class Main {
public static void main(String[] args) {
Cat Cat = new Cat("C");
Dog Dog = new Dog("D");
ArrayList<Animal> list = new ArrayList<Animal>();
list.add(Cat);
list.add(Dog);
}
}
You shouldn't do this
Lets look at it this way, if an we call a generic Object just a "thing" and you create a(n) (Array) List of just "things" then how useful is that to you? To store those three things that have seemingly nothing in common in one list doesn't make sense. Containers were added so that programmers could store groups of similar things.
If we take a look at it from more of a programming point of view as opposed to a real world point of view it raises more problems. Your code might try to perform an action that only Car can do, the compiler doesn't like that your Dog class just tried to turnOnEngine(), and throws an error that you didn't expect.
So in short, it is bad practice to add unrelated items to a collection.
The purpose of generics is to have the compiler doing all the type checking for us. So that we don't need to worry about casting or have to remember what types are really in the list. So using generics also helps documenting your code by making the contained type more explicit.
You could:
not use generics and enforce your own type checking (by safe downcasting with instanceof)
use generics with separate lists for each type
use generics with an abstraction for related class, for example: List<Animal>
It depends on what you want to use the List for.
You should declare the generic type value of the List to be the most restrictive that suits your needs, and that way you get the strongest check from the compiler to eliminate the errors at compile time.
There might be cases when you really just want to store any type of objects in a List in which case you would use List<Object>. Again, depends on what you want to use the List and the elements for.
In the following code you're able to apply any Function f (e.g., add, subtract, etc.). How do I do that through Java?
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f)
{
for ( ; first!=last; ++first ) f(*first);
return f;
}
There are two major changes you'll need to make to this code to make it work in Java. First, you'll need to replace the STL-style iterators with Java-style iterators, which fortunately isn't too hard. Second, you'll have to change the use of a function pointer or functor parameter with an object of a different type, since Java does not support function pointers.
In Java, iterators are heavier than in C++ and encapsulate the full range they traverse, not just the start or end of that range. With a Java iterator, you use the .next() and .hasNext() methods to walk across the range.
As for the function parameter, you will probably need to create your own interface representing some object that can be called as a function. For example:
public interface Operation<T> {
void apply(T argument);
}
This interface is a generic parameterized on some type T saying what the argument type is, and then exports a function called apply() that applies the function.
Given this, a simple but naive way to replicate for_each would be to write
public static <T> forEach(Iterator<T> itr, Operation<T> op) {
while (itr.hasNext())
op.apply(itr.next());
}
The reason I say that this is naive is that it doesn't use bounded wildcards correctly to expand the scope of where it can be used. A more proper version that's more Java-friendly would be this:
public static <T> forEach(Iterator<T> itr, Operation<? super T> op) {
while (itr.hasNext())
op.apply(itr.next());
}
Consult a reference on Java genetics for why this works.
Hope this helps!
To implement the template class you'd use Java Generics
For the callback, more than likely you'd want to create an Interface and pass an object that implemented it to the Generic class where you'd call the method defined therin.
You should use interfaces, but if you want to do it in the hard way, using reflection (not tested, not exception-checked, etc. But you can get the idea):
public void myFunction(Collection items, String methodName) {
foreach(Object o : items) {
Method method = o.getClass().getMethod(methodName);
method.invoke(o);
}
}
With good OO design, first through last would be objects of a specific (implements an interface) type and f() would take an object of that type (interface) as a parameter so you are done--it's pretty much like you wrote.
if you are talking about doing it on primitives instead then it's going to need generics, but at this point you'd want to look for a better design or better way to do that.
You didn't really give enough info for a more detailed answer, if we knew more about the problem you were trying to solve and the restrictions we might be able to give better advice.
this morning I came across this code, and I have absolutely no idea what that means. Can anyone explain me what do these <T> represent? For example:
public class MyClass<T>
...
some bits of code then
private Something<T> so;
private OtherThing<T> to;
private Class<T> c;
Thank you
You have bumped into "generics". They are explained very nicely in this guide.
In short, they allow you to specify what type that a storage-class, such as a List or Set contains. If you write Set<String>, you have stated that this set must only contain Strings, and will get a compilation error if you try to put something else in there:
Set<String> stringSet = new HashSet<String>();
stringSet.add("hello"); //ok.
stringSet.add(3);
^^^^^^^^^^^ //does not compile
Furthermore, another useful example of what generics can do is that they allow you to more closely specify an abstract class:
public abstract class AbstClass<T extends Variable> {
In this way, the extending classes does not have to extend Variable, but they need to extend a class that extends Variable.
Accordingly, a method that handles an AbstClass can be defined like this:
public void doThing(AbstClass<?> abstExtension) {
where ? is a wildcard that means "all classes that extend AbstClass with some Variable".
What you see here is something called Generics. They were introduced to Java in release 1.5.
You can read about them here and here. Hope this helps.
Imagine you're writing a List or Array class. This class must be able to hold elements of an unknown type. How do you do that?
Generics answers this question. Those <T> you're seeing can be read as some type. With generics you can write class MyList<T> { ... }, which in this context means a list that holds some type.
As an usage example, declare a list to store integers, MyList<Integer> listOfInts, or strings, MyList<String> listOfStrings, or one class you've written yourself MyList<MyClass> listOfMyClass.
What you are seeing is Java generics, which allows classes and methods to be parameterized by other classes. This is especially useful when creating container classes, since it saves you having to create separate classes for "a list of integers", "a list of strings", etc. Instead, you can have a single "list of some type T, where T is a variable" and then you can instantiate the list for some specific type T. Note that Java generics is not quite the same as template types in C++; Java generics actually use the same class definition but add implicit casting (generated by the compiler) and add additional type-checking. However, the different instantiations actually make use of the same exact type (this is known as erasure), where the parameterized types are replaced with Object. You can read more about this at the link.
Since noone has mentioned it yet, there is a very comprehensive guide/FAQ/tutorial on generics which can be found on Angelika Langer's site.