1 package com.fasterxml.jackson.databind.type; 2 3 import java.lang.reflect.Array; 4 5 import com.fasterxml.jackson.databind.JavaType; 6 7 /** 8 * Array types represent Java arrays, both primitive and object valued. 9 * Further, Object-valued arrays can have element type of any other 10 * legal {@link JavaType}. 11 */ 12 public final class ArrayType 13 extends TypeBase 14 { 15 private static final long serialVersionUID = 1L; 16 17 /** 18 * Type of elements in the array. 19 */ 20 protected final JavaType _componentType; 21 22 /** 23 * We will also keep track of shareable instance of empty array, 24 * since it usually needs to be constructed any way; and because 25 * it is essentially immutable and thus can be shared. 26 */ 27 protected final Object _emptyArray; 28 ArrayType(JavaType componentType, TypeBindings bindings, Object emptyInstance, Object valueHandler, Object typeHandler, boolean asStatic)29 protected ArrayType(JavaType componentType, TypeBindings bindings, Object emptyInstance, 30 Object valueHandler, Object typeHandler, boolean asStatic) 31 { 32 // No super-class, interfaces, for now 33 super(emptyInstance.getClass(), bindings, null, null, 34 componentType.hashCode(), 35 valueHandler, typeHandler, asStatic); 36 _componentType = componentType; 37 _emptyArray = emptyInstance; 38 } 39 construct(JavaType componentType, TypeBindings bindings)40 public static ArrayType construct(JavaType componentType, TypeBindings bindings) { 41 return construct(componentType, bindings, null, null); 42 } 43 construct(JavaType componentType, TypeBindings bindings, Object valueHandler, Object typeHandler)44 public static ArrayType construct(JavaType componentType, TypeBindings bindings, 45 Object valueHandler, Object typeHandler) { 46 // Figuring out raw class for generic array is actually bit tricky... 47 Object emptyInstance = Array.newInstance(componentType.getRawClass(), 0); 48 return new ArrayType(componentType, bindings, emptyInstance, valueHandler, typeHandler, false); 49 } 50 51 @Override withContentType(JavaType contentType)52 public JavaType withContentType(JavaType contentType) { 53 Object emptyInstance = Array.newInstance(contentType.getRawClass(), 0); 54 return new ArrayType(contentType, _bindings, emptyInstance, 55 _valueHandler, _typeHandler, _asStatic); 56 } 57 58 @Override withTypeHandler(Object h)59 public ArrayType withTypeHandler(Object h) 60 { 61 if (h == _typeHandler) { 62 return this; 63 } 64 return new ArrayType(_componentType, _bindings, _emptyArray, _valueHandler, h, _asStatic); 65 } 66 67 @Override withContentTypeHandler(Object h)68 public ArrayType withContentTypeHandler(Object h) 69 { 70 if (h == _componentType.<Object>getTypeHandler()) { 71 return this; 72 } 73 return new ArrayType(_componentType.withTypeHandler(h), _bindings, _emptyArray, 74 _valueHandler, _typeHandler, _asStatic); 75 } 76 77 @Override withValueHandler(Object h)78 public ArrayType withValueHandler(Object h) { 79 if (h == _valueHandler) { 80 return this; 81 } 82 return new ArrayType(_componentType, _bindings, _emptyArray, h, _typeHandler,_asStatic); 83 } 84 85 @Override withContentValueHandler(Object h)86 public ArrayType withContentValueHandler(Object h) { 87 if (h == _componentType.<Object>getValueHandler()) { 88 return this; 89 } 90 return new ArrayType(_componentType.withValueHandler(h), _bindings, _emptyArray, 91 _valueHandler, _typeHandler, _asStatic); 92 } 93 94 @Override withStaticTyping()95 public ArrayType withStaticTyping() { 96 if (_asStatic) { 97 return this; 98 } 99 return new ArrayType(_componentType.withStaticTyping(), _bindings, 100 _emptyArray, _valueHandler, _typeHandler, true); 101 } 102 103 /* 104 /********************************************************** 105 /* Methods for narrowing conversions 106 /********************************************************** 107 */ 108 109 /** 110 * Handling of narrowing conversions for arrays is trickier: for now, 111 * it is not even allowed. 112 */ 113 @Override 114 @Deprecated // since 2.7 _narrow(Class<?> subclass)115 protected JavaType _narrow(Class<?> subclass) { 116 return _reportUnsupported(); 117 } 118 119 // Should not be called, as array types in Java are not extensible; but 120 // let's not freak out even if it is called? 121 @Override refine(Class<?> contentClass, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces)122 public JavaType refine(Class<?> contentClass, TypeBindings bindings, 123 JavaType superClass, JavaType[] superInterfaces) { 124 return null; 125 } 126 _reportUnsupported()127 private JavaType _reportUnsupported() { 128 throw new UnsupportedOperationException("Cannot narrow or widen array types"); 129 } 130 131 /* 132 /********************************************************** 133 /* Overridden methods 134 /********************************************************** 135 */ 136 137 @Override isArrayType()138 public boolean isArrayType() { return true; } 139 140 /** 141 * For some odd reason, modifiers for array classes would 142 * claim they are abstract types. Not so, at least for our 143 * purposes. 144 */ 145 @Override isAbstract()146 public boolean isAbstract() { return false; } 147 148 /** 149 * For some odd reason, modifiers for array classes would 150 * claim they are abstract types. Not so, at least for our 151 * purposes. 152 */ 153 @Override isConcrete()154 public boolean isConcrete() { return true; } 155 156 @Override hasGenericTypes()157 public boolean hasGenericTypes() { 158 // arrays are not parameterized, but element type may be: 159 return _componentType.hasGenericTypes(); 160 } 161 162 /* 163 /********************************************************** 164 /* Public API 165 /********************************************************** 166 */ 167 168 @Override isContainerType()169 public boolean isContainerType() { return true; } 170 171 @Override getContentType()172 public JavaType getContentType() { return _componentType; } 173 174 @Override getContentValueHandler()175 public Object getContentValueHandler() { 176 return _componentType.getValueHandler(); 177 } 178 179 @Override getContentTypeHandler()180 public Object getContentTypeHandler() { 181 return _componentType.getTypeHandler(); 182 } 183 184 @Override hasHandlers()185 public boolean hasHandlers() { 186 return super.hasHandlers() || _componentType.hasHandlers(); 187 } 188 189 @Override getGenericSignature(StringBuilder sb)190 public StringBuilder getGenericSignature(StringBuilder sb) { 191 sb.append('['); 192 return _componentType.getGenericSignature(sb); 193 } 194 195 @Override getErasedSignature(StringBuilder sb)196 public StringBuilder getErasedSignature(StringBuilder sb) { 197 sb.append('['); 198 return _componentType.getErasedSignature(sb); 199 } 200 201 /* 202 /********************************************************** 203 /* Extended API 204 /********************************************************** 205 */ 206 207 /** 208 * @since 2.12 209 */ getEmptyArray()210 public Object[] getEmptyArray() { 211 return (Object[]) _emptyArray; 212 } 213 214 /* 215 /********************************************************** 216 /* Standard methods 217 /********************************************************** 218 */ 219 220 @Override toString()221 public String toString() 222 { 223 return "[array type, component type: "+_componentType+"]"; 224 } 225 226 @Override equals(Object o)227 public boolean equals(Object o) 228 { 229 if (o == this) return true; 230 if (o == null) return false; 231 if (o.getClass() != getClass()) return false; 232 233 ArrayType other = (ArrayType) o; 234 return _componentType.equals(other._componentType); 235 } 236 } 237