code: public <T> T getObject(DataKey<T> key) {
          if (key == null) {
              throw new IllegalArgumentException("key must not be null");
          }
          final Object object = data.get(key.getName());
          if (containsKey(key)) {
              if (object != null) {
                  if (!key.getDataClass().isAssignableFrom(object.getClass())) {
                      throw new IllegalStateException("the type of the key (" + key.getDataClass().getCanonicalName() + ") is not a supertype of the value's class ("
                              + object.getClass().getCanonicalName() + ")");
                  }
              }
          } else {
              if (key.getDefaultValue() != null) {
                  return key.getDefaultValue();
              }
          }
          if (object == null && !key.allowNull()) {
              throw new IllegalStateException("key \"" + key.getName() + "\" does not allow null values but the object is null");
          }
          return (T) object;
      }
docs: returns the associated key (if it exists). If the key has no associated
  value but the key has defined a default value then the value is returned
  instead. If the key was defined to be not nullable but is null due to its
  value or because it does not exist, then an IllegalStateException is thrown
  
  @param <T>
  @param key
  @return