001    package com.basilv.examples.java5;
002    
003    import java.lang.reflect.Array;
004    import java.util.*;
005    
006    
007    class BusinessEntity {
008      private Integer id;
009    
010      public BusinessEntity(Integer id) {
011        this.id = id;
012      }
013      
014      public Integer getId() {
015        return id;
016      }
017    
018      public int getIdAsPrimitiveInt() {
019        return id; // Unboxing (Integer to int). What happens if id is null???
020      }
021    
022      @Override // Annotation (Java standard) 
023      public String toString() {
024        return "Id:" + id;
025      }
026      
027      public BusinessEntity getMyself() {
028        return this;
029      }
030      
031      
032    }
033    
034    class PersonEntity extends BusinessEntity {
035    
036      // Enumerated Type (enum)
037      // Can get list of values with AddressType.values();
038      // Can get particular instance with AddressType.valueOf("Mailing");
039      // Can even have abstract methods that particular enumerated value constant overrides.
040      public enum AddressType {
041        MAILING("Mailing", 1),
042        BILLING("Billing", 2);
043        
044        private String displayName;
045        
046        // Annotation (warning type Eclipse-specific)
047        @SuppressWarnings("unused")  
048        private int id;
049        
050        private AddressType(String displayName, int id) {
051            this.displayName = displayName;
052            this.id = id;
053        }
054    
055        public String getDisplayName() {
056          return displayName;
057        }
058    
059      }
060      
061      public PersonEntity(Integer id) {
062        super(id);
063      }
064    
065      private AddressType addressType;
066    
067      public AddressType getAddressType() {
068        return addressType;
069      }
070      public void setAddressType(AddressType addressType) {
071        this.addressType = addressType;
072      }
073    
074      @Override 
075      // Covariant return - note return type of method in parent class.
076      public PersonEntity getMyself() { 
077        return this;
078      }
079    
080    }
081    
082    // Generic type definition.
083    // This can get more complex with the use of wildcards.
084    abstract class BusinessService<T extends BusinessEntity> {
085      public abstract List<T> findAll();
086      
087      public abstract T loadByPrimaryKey(Long id);
088      
089      
090      // Static generic method
091      public static <T> T[] toArray(List<T> list, Class<T> clazz) {
092        // This construct is not allowed because the specific type of the generic
093        // is not kept at runtime - this is called erasure.
094        // T[] array = new T[]();
095    
096        // Instead, pass in the class as a 'Type Token'
097        // Note that the class Class is itself genericized.
098        
099        @SuppressWarnings("unchecked") // Annotation - needed for cast. 
100        T[] array = (T[]) Array.newInstance(clazz, 0);
101        return list.toArray(array);
102      }
103    }
104    
105    // Instantiation of a generic type
106    public class PersonServiceImpl extends BusinessService<PersonEntity> {
107    
108      @Override
109      @Deprecated // Annotation (Java standard)
110      public List<PersonEntity> findAll() {
111        // Using a list from the collections API
112        List<PersonEntity> list = new ArrayList<PersonEntity>();
113        list.add(new PersonEntity(123)); // Autoboxing (int to Integer)
114        return list;
115      }
116      
117      @Override public PersonEntity loadByPrimaryKey(Long id) {
118        List<PersonEntity> personList = findAll();
119        for (PersonEntity person : personList) { // Enhanced for loop over list.
120          if (person.getId().equals(id)) {
121            return person;
122          }
123        }
124        
125        PersonEntity[] backupArray = {
126          new PersonEntity(1),
127          new PersonEntity(2),
128        };
129        
130        for (PersonEntity person : backupArray) { // Enhanced for loop over array
131          if (person.getId().equals(id)) {
132            return person;
133          }
134        }
135        
136        return null;
137      }
138      
139      // Use of generic wildcard.
140      // Use of Varargs (variable arguments)
141      public Map<Integer,? extends PersonEntity> collectIntoMap(PersonEntity... people) {
142        // Using a map from the collections API
143        Map<Integer, PersonEntity> map = new HashMap<Integer,PersonEntity>();
144        for (PersonEntity person : people) {
145          map.put(person.getId(), person);
146        }
147        return map;
148      }
149      
150    }
151    
152    // Other notes:
153    // - You can define your own annotations. Used mostly by frameworks (i.e. EJB 3)