Skip to content

Commit 6a7931c

Browse files
committed
Minor fix to non-working earlier optimization for creating ArrayList/HashMap
1 parent c9909b2 commit 6a7931c

File tree

3 files changed

+164
-76
lines changed

3 files changed

+164
-76
lines changed

src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java

+155-48
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.fasterxml.jackson.databind.deser.impl;
22

33
import java.io.IOException;
4+
import java.lang.reflect.AnnotatedElement;
45
import java.lang.reflect.Member;
6+
import java.lang.reflect.Type;
57
import java.util.*;
68

79
import com.fasterxml.jackson.databind.*;
@@ -77,7 +79,7 @@ public class CreatorCollector
7779
/* Life-cycle
7880
/**********************************************************
7981
*/
80-
82+
8183
public CreatorCollector(BeanDescription beanDesc, MapperConfig<?> config)
8284
{
8385
_beanDesc = beanDesc;
@@ -91,26 +93,12 @@ public ValueInstantiator constructValueInstantiator(DeserializationConfig config
9193
final JavaType arrayDelegateType = _computeDelegateType(_creators[C_ARRAY_DELEGATE], _arrayDelegateArgs);
9294
final JavaType type = _beanDesc.getType();
9395

94-
// Any non-standard creator will prevent; with one exception: int-valued constructor
95-
// that standard containers have can be ignored
96-
if (!_hasNonDefaultCreator) {
97-
/* 10-May-2014, tatu: If we have nothing special, and we are dealing with one
98-
* of "well-known" types, can create a non-reflection-based instantiator.
99-
*/
100-
final Class<?> rawType = type.getRawClass();
101-
if (rawType == Collection.class || rawType == List.class || rawType == ArrayList.class) {
102-
return new Vanilla(Vanilla.TYPE_COLLECTION);
103-
}
104-
if (rawType == Map.class || rawType == LinkedHashMap.class) {
105-
return new Vanilla(Vanilla.TYPE_MAP);
106-
}
107-
if (rawType == HashMap.class) {
108-
return new Vanilla(Vanilla.TYPE_HASH_MAP);
109-
}
110-
}
111-
96+
// 11-Jul-2016, tatu: Earlier optimization by replacing the whole instantiator did not
97+
// work well, so let's replace by lower-level check:
98+
AnnotatedWithParams defaultCtor = StdTypeConstructor.tryToOptimize(_creators[C_DEFAULT]);
99+
112100
StdValueInstantiator inst = new StdValueInstantiator(config, type);
113-
inst.configureFromObjectSettings(_creators[C_DEFAULT],
101+
inst.configureFromObjectSettings(defaultCtor,
114102
_creators[C_DELEGATE], delegateType, _delegateArgs,
115103
_creators[C_PROPS], _propertyBasedArgs);
116104
inst.configureFromArraySettings(_creators[C_ARRAY_DELEGATE], arrayDelegateType, _arrayDelegateArgs);
@@ -122,13 +110,13 @@ public ValueInstantiator constructValueInstantiator(DeserializationConfig config
122110
inst.configureIncompleteParameter(_incompleteParameter);
123111
return inst;
124112
}
125-
113+
126114
/*
127115
/**********************************************************
128116
/* Setters
129117
/**********************************************************
130118
*/
131-
119+
132120
/**
133121
* Method called to indicate the default creator: no-arguments
134122
* constructor or factory method that is called to instantiate
@@ -179,15 +167,16 @@ public void addPropertyCreator(AnnotatedWithParams creator, boolean explicit,
179167
HashMap<String,Integer> names = new HashMap<String,Integer>();
180168
for (int i = 0, len = properties.length; i < len; ++i) {
181169
String name = properties[i].getName();
182-
/* [Issue-13]: Need to consider Injectables, which may not have
183-
* a name at all, and need to be skipped
184-
*/
170+
// Need to consider Injectables, which may not have
171+
// a name at all, and need to be skipped
185172
if (name.length() == 0 && properties[i].getInjectableValueId() != null) {
186173
continue;
187174
}
188175
Integer old = names.put(name, Integer.valueOf(i));
189176
if (old != null) {
190-
throw new IllegalArgumentException("Duplicate creator property \""+name+"\" (index "+old+" vs "+i+")");
177+
throw new IllegalArgumentException(String.format(
178+
"Duplicate creator property \"%s\" (index %s vs %d)",
179+
name, old, i));
191180
}
192181
}
193182
}
@@ -344,46 +333,164 @@ protected void verifyNonDup(AnnotatedWithParams newOne, int typeIndex, boolean e
344333
/**********************************************************
345334
*/
346335

347-
protected final static class Vanilla
348-
extends ValueInstantiator.Base
336+
/**
337+
* Replacement for default constructor to use for a small set of
338+
* "well-known" types.
339+
*<p>
340+
* Note: replaces earlier <code>Vanilla</code> <code>ValueInstantiator</code>
341+
* implementation
342+
*
343+
* @since 2.8.1 (replacing earlier <code>Vanilla</code> instantiator
344+
*/
345+
protected final static class StdTypeConstructor
346+
extends AnnotatedWithParams
349347
implements java.io.Serializable
350348
{
351349
private static final long serialVersionUID = 1L;
352350

353-
public final static int TYPE_COLLECTION = 1;
354-
public final static int TYPE_MAP = 2;
355-
public final static int TYPE_HASH_MAP = 3;
351+
public final static int TYPE_ARRAY_LIST = 1;
352+
public final static int TYPE_HASH_MAP = 2;
353+
public final static int TYPE_LINKED_HASH_MAP = 3;
354+
355+
private final AnnotatedWithParams _base;
356356

357357
private final int _type;
358358

359-
public Vanilla(int t) {
360-
super(_type(t));
359+
public StdTypeConstructor(AnnotatedWithParams base, int t)
360+
{
361+
super(base, null);
362+
_base = base;
361363
_type = t;
362364
}
363365

364-
private static Class<?> _type(int t) {
365-
switch (t) {
366-
case TYPE_COLLECTION: return ArrayList.class;
367-
case TYPE_MAP: return LinkedHashMap.class;
368-
case TYPE_HASH_MAP: return HashMap.class;
366+
public static AnnotatedWithParams tryToOptimize(AnnotatedWithParams src)
367+
{
368+
if (src != null) {
369+
final Class<?> rawType = src.getDeclaringClass();
370+
if (rawType == List.class || rawType == ArrayList.class) {
371+
return new StdTypeConstructor(src, TYPE_ARRAY_LIST);
372+
}
373+
if (rawType == LinkedHashMap.class) {
374+
return new StdTypeConstructor(src, TYPE_LINKED_HASH_MAP);
375+
}
376+
if (rawType == HashMap.class) {
377+
return new StdTypeConstructor(src, TYPE_HASH_MAP);
378+
}
379+
}
380+
return src;
381+
}
382+
383+
protected final Object _construct() {
384+
switch (_type) {
385+
case TYPE_ARRAY_LIST:
386+
return new ArrayList<Object>();
387+
case TYPE_LINKED_HASH_MAP:
388+
return new LinkedHashMap<String,Object>();
389+
case TYPE_HASH_MAP:
390+
return new HashMap<String,Object>();
369391
}
370-
return Object.class;
392+
throw new IllegalStateException("Unknown type "+_type);
371393
}
372394

373395
@Override
374-
public boolean canInstantiate() { return true; }
396+
public int getParameterCount() {
397+
return _base.getParameterCount();
398+
}
375399

376400
@Override
377-
public boolean canCreateUsingDefault() { return true; }
401+
public Class<?> getRawParameterType(int index) {
402+
return _base.getRawParameterType(index);
403+
}
378404

379405
@Override
380-
public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
381-
switch (_type) {
382-
case TYPE_COLLECTION: return new ArrayList<Object>();
383-
case TYPE_MAP: return new LinkedHashMap<String,Object>();
384-
case TYPE_HASH_MAP: return new HashMap<String,Object>();
385-
}
386-
throw new IllegalStateException("Unknown type "+_type);
406+
public JavaType getParameterType(int index) {
407+
return _base.getParameterType(index);
408+
}
409+
410+
@SuppressWarnings("deprecation")
411+
@Override
412+
public Type getGenericParameterType(int index) {
413+
return _base.getGenericParameterType(index);
414+
}
415+
416+
@Override
417+
public Object call() throws Exception {
418+
return _construct();
419+
}
420+
421+
@Override
422+
public Object call(Object[] args) throws Exception {
423+
return _construct();
424+
}
425+
426+
@Override
427+
public Object call1(Object arg) throws Exception {
428+
return _construct();
429+
}
430+
431+
@Override
432+
public Class<?> getDeclaringClass() {
433+
return _base.getDeclaringClass();
434+
}
435+
436+
@Override
437+
public Member getMember() {
438+
return _base.getMember();
439+
}
440+
441+
@Override
442+
public void setValue(Object pojo, Object value) throws UnsupportedOperationException, IllegalArgumentException {
443+
throw new UnsupportedOperationException();
444+
}
445+
446+
@Override
447+
public Object getValue(Object pojo) throws UnsupportedOperationException, IllegalArgumentException {
448+
throw new UnsupportedOperationException();
449+
}
450+
451+
@Override
452+
public Annotated withAnnotations(AnnotationMap fallback) {
453+
throw new UnsupportedOperationException();
454+
}
455+
456+
@Override
457+
public AnnotatedElement getAnnotated() {
458+
return _base.getAnnotated();
459+
}
460+
461+
@Override
462+
protected int getModifiers() {
463+
return _base.getMember().getModifiers();
464+
}
465+
466+
@Override
467+
public String getName() {
468+
return _base.getName();
469+
}
470+
471+
@Override
472+
public JavaType getType() {
473+
return _base.getType();
474+
}
475+
476+
@Override
477+
public Class<?> getRawType() {
478+
return _base.getRawType();
479+
}
480+
481+
@Override
482+
public boolean equals(Object o) {
483+
return (o == this);
484+
}
485+
486+
@Override
487+
public int hashCode() {
488+
return _base.hashCode();
489+
}
490+
491+
@Override
492+
public String toString() {
493+
return _base.toString();
387494
}
388495
}
389496
}

src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedConstructor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public final class AnnotatedConstructor
1919
* @since 2.1
2020
*/
2121
protected Serialization _serialization;
22-
22+
2323
/*
2424
/**********************************************************
2525
/* Life-cycle

src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedWithParams.java

+8-27
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ protected AnnotatedWithParams(TypeResolutionContext ctxt, AnnotationMap annotati
3232
_paramAnnotations = paramAnnotations;
3333
}
3434

35+
/**
36+
* @since 2.8.1
37+
*/
38+
protected AnnotatedWithParams(AnnotatedWithParams base, AnnotationMap[] paramAnnotations) {
39+
super(base);
40+
_paramAnnotations = paramAnnotations;
41+
}
42+
3543
/**
3644
* Method called to override a method parameter annotation,
3745
* usually due to a mix-in
@@ -58,33 +66,6 @@ protected AnnotatedParameter replaceParameterAnnotations(int index, AnnotationMa
5866
return getParameter(index);
5967
}
6068

61-
/*
62-
/**********************************************************
63-
/* Helper methods for subclasses
64-
/**********************************************************
65-
*/
66-
67-
/*
68-
protected JavaType getType(TypeBindings bindings, TypeVariable<?>[] typeParams)
69-
{
70-
// [JACKSON-468] Need to consider local type binding declarations too...
71-
if (typeParams != null && typeParams.length > 0) {
72-
bindings = bindings.childInstance();
73-
for (TypeVariable<?> var : typeParams) {
74-
String name = var.getName();
75-
// to prevent infinite loops, need to first add placeholder ("<T extends Enum<T>>" etc)
76-
bindings._addPlaceholder(name);
77-
// About only useful piece of information is the lower bound (which is at least Object.class)
78-
Type lowerBound = var.getBounds()[0];
79-
JavaType type = (lowerBound == null) ? TypeFactory.unknownType()
80-
: bindings.resolveType(lowerBound);
81-
bindings.addBinding(var.getName(), type);
82-
}
83-
}
84-
return bindings.resolveType(getGenericType());
85-
}
86-
*/
87-
8869
/*
8970
/**********************************************************
9071
/* Extended API

0 commit comments

Comments
 (0)