Like Blocks, there is generally only one instance of each Item class. The Item class holds information that defines what that type of Item is (for example - what it looks like, how much damage it can take before breaking, how it interacts with blocks or entities, etc).
ItemStack is the class used when an Item is actually "created" - in addition to the Item type, it also stores the item count (eg a stack of 46 planks), "damage" (eg pickaxe "wear-and-tear" indicator), and several other pieces of information. ItemStacks are stored in "Slots" in the inventory, in the hotbar, in Containers (eg Chest, Furnace, etc).
Some general notes
- In order to compare two different ItemStacks, you can't use the == operator (a common trap -see here for a discussion based around Strings). Use areItemStacksEqual(itemStack1, itemStack2); instead.
- Each Item defines a maximum stack size for the corresponding ItemStack, up to 64. If this is >=2, the item is "Stackable", otherwise not.
- If an Item can be damaged (maxDamage > 0) then it isDamageable, and the ItemStack.itemDamage is intepreted as the current damage (or "health") of the item. Otherwise, ItemStack.itemDamage is interpreted as the type of item - for example ItemCloth (wool) which uses the itemDamage to specify the colour of the wool. .hasSubTypes = true and .getMetadata are also required.
- If an item is Stackable, it can't be Damageable.
- An ItemStack can store custom information about the item, in the NBT stackTagCompound; see ItemStack.setTagInfo, .setTagCompound, .getTagCompound, etc. Used by vanilla for enchantments.
- An item which is in the world (eg sitting on the ground after the player has thrown it) is represented by the corresponding EntityItem, not an ItemStack.
ItemBlocks are a special type of Item used to represent a Block when you have harvested it - for example Bedrock. For your own custom Blocks, when you register them with GameRegistry.registerBlock a matching ItemBlock will automatically be created - alternatively you can supply your own ItemBlock to GameRegistry.registerBlock to explicitly associate it with the target Block.