Skip to content

Latest commit

 

History

History
124 lines (114 loc) · 9.08 KB

File metadata and controls

124 lines (114 loc) · 9.08 KB

Lesson Twelve

Table of Contents

The Lesson
The Program
The Assignment

  • In this lesson we are going to learn about a wonderful feature called generics!
    • What is generic programming?
      • Generic programming is programming when you don't really know about the data type you are working with.
      • This is very useful when working with storage types as well as for a few other things.
    • How do Generics work?
      • When doing generic programing, langauges usually go about two different ways of doing it:
        • The first is called Template programming and is used in C++, and a few other languages.
          • When you specify the type for the object the whole class is copied and the template type is replaced with the specified one.
          • This is really powerful as you can do different things for different templates if necessary.
          • It does result in slightly longer compile times and larger files.
            • But since whole new classes are made there is no casting or type checking so it is usually faster.
        • The second method is called Generic programming and is clearly used by Java (and some others) since the names are the same.
          • When you compile your code the compiler will look at all of the uses of your generic class and then do what is called type erasure.
          • Type erasure will take the information you write in your code and decide on a good base class for everything.
          • So if you are creating a box class that can only hold things that extend the square class the compiler will replace the generic type with Square.
            • But if you are creating a very general list that can hold anything it will probably use the Object class.
              • The Object class is used most often as it fits most cases.
          • Then after doing type erasure the compiler inserts casts and type checks into your code.
            • These casts and type checks are done at execution/run time and so it SLIGHTLY slows your code.
              • The decrease in speed is impossible to notice between a program that uses generics and one that doesn't.
              • The only time this decrease is noticed is when comparing languages that use generics and ones that use templates.
              • So if you think you should use generics don't be afraid to use them the speed decrease is incredibly small.
            • Because of type erasure and the casts and type checks code compilation tends to be faster and files smaller.
              • This is because there are not a lot of versions of your generic class and instead only one.
    • How do we use generics in java?
      • There are two cases where generics can be used: Creating generic classes and parametizing (specifying the type) for a generic class.
        • In both cases we will be using the carrot brackets ("<" and ">") with something in between them.
      • Creation:
        • When creating a generic class we put the brackets next to the name of the class when we declare it (where we write "class NAME")
          • Within the brackets we write the name of our generic type.
          • We try to keep names to one letter and there is a certain convention that we try to follow.
            • E - Element
            • K - Key (Used in maps)
            • V - Value (Used in maps)
            • N - Number (No idea where this is used)
            • T - Type (The most common generic type)
            • S, U, V, etc. - 2nd, 3rd, 4th types
          • These aren't the only names you can use and the name means absolutely nothing.
            • It will help people understand what you are trying to do with your generic type though which is helpful.
        • After creating the generic class, any time we need to use that generic class just refer to it by it's name as if it was a normal class.
          • So if a method must return our generic type and our type is called "U" (apparently T and S were taken) we would type:
            • U METHODNAME() { ... }
      • Paremetizing
        • Paremetizing a generic class is pretty easy.
        • When you go to create a new instance of that class all you have to do is type the type within brackets after the class name.
          • Example: new ArrayList() or new LinkedList()
        • You can optionally leave out the paremetization but this is extremely frowned upon.
          • The only reason you can even do it is for backwards compatibility with older code.
    • Limits of generics:
      • Generics are really cool and all but there are some limits to what they can do.
      • Arrays:
        • The first problem is that you cannot create an array from a generic type.
          • This is because in java, arrays like to know a few things about themselves at compile time.
            • One of these things happens to be it's type and so generic arrays really can't be done.
          • But then how does the generic class ArrayList (which is backed by an array) work?
            • Well it is most likely a little bit more complicated than our program below but I did my best to show you a rough draft.
              • The real version would probably have more safety checks and such since it is actually part of java.
      • instanceof:
        • You cannot use the "instanceof" keyword with generics as yet again, we really don't know the type of a generic so we can't see if something matches it.
          • This is made worse because of type erasure so most things would just wind up being "instanceof Object" which everything is.
      • primitive data types:
        • You cannot use primitive data types inside your parametization (no ArrayList or ).
        • Instead you have to use the Class versions of the primitives (Integer, Float, Double, etc...).
        • You don't have to worry too much about interchanging between the Class versions and the primitives as the compiler will take care of this for you.
          • This is called auto boxing and it is a cool feature but a dangerous one.
            • We will talk about it soon.
    • Generics in parameters:
      • One really cool thing you can do with generics is accept specific types of generic objects in your parameters.
      • For example, the Class class is actually generic and is generic according to the class of the object.
        • So if you have a String object and call the .getClass() method on it, it will return a Class object.
      • When creating something that stores classes of a certain type (for example a list of all entity classes) you can use inheritance with your generics.
        • If all of our entities extend the Entity class we can use the wildcard operator along with generic bounding to improve our list.
      • Wild Card Operator:
        • The wild card is the question mark (?) and is used for an unknown type.
      • Generic Bounding:
        • This is quite an interesting and complicated topic but for now you just need to know that you can use this to tell if something extends another class.
        • This is done with the "extends" keyword.
      • So for our object that stores classes that all extend Entity we could have it be parametized to <? extends Entity>.
        • Now it can store any type (?) but only if it extends Entity.
    • The Diamond (<>):
      • The diamond is one of the few new features in java that I will actually be teaching you.
      • All it does is prevent you from having to retype the parametization if it is already obvious what it is.
        • This usally happens when you declare and instantialize a variable at the same time.
      • The compiler will infer the parametization and put it in for you.
      • In order to use the diamond just use empty brackets.
      • An example of this is: Box<Box> boxOfBoxes = new Box<>();
    • Inheritance:
      • The Java official tutorials makes a special point about this so I decided I would do the same.
      • Due to how generics work, inheritance is impossible to do for the most part and when it can be done it is not like you think.
      • If you have class B that extends from class A (making A the base class) and then have an arraylist of a and b, then:
        • While an object of type B could be stored in a variable of type A.
        • An object of type ArrayList could NOT be stored in a variable of type ArrayList.
      • Even though the generic type being used is a subclass of the other one, the two arraylists are not related.
  • In this program I have made a simple version of an ArrayList (a common list we will learn about next lesson).
  • This list uses generics in order to allow you to make a list that can store any data type.
  • Our arraylist will automatically resize to double the previous size when you try to add a new element past it's old limit.
  • Your assignment for this lesson is to create your own version of a Linked List.
  • What is a Linked List:
    • It is called a linked list because the list consists of nodes that are linked to each other.
    • The actual Linked List will usually contain a variable for the first node in the list, and one for the last node.
    • Upon adding something to the list you add it to the Node, add the new node to the last node, and then make the new node the last node.
    • If you need get a certain one you can do this with a counter decremented each time it moves to the next node.
    • You should be able to store and retrieve anything using generics.